安卓ListView自定义适配器ImageButton

6

如果有更好的方法,请告诉我,这可能不是正确的方法。

我创建了一个自定义适配器类,在我的getView方法中填充我想要使用的视图。

public View getView(int position, View convertView, ViewGroup parent) 
    {
        View v = mInflater.inflate(R.layout.wherelayout, null);
        if (convertView != null) 
        {
            v = convertView;
        }
        HashMap<String, Object> whereHash = (HashMap<String, Object>) this.getItem(position);
        if (whereHash != null) 
        {
            TextView whereId = (TextView) v.findViewById(R.id.tvWhere);
            TextView whereDetails = (TextView) v.findViewById(R.id.tvWhereDetails);
            ImageButton ibDelWhere = (ImageButton) v.findViewById(R.id.ibDelWhere);

            whereId.setText((CharSequence) whereHash.get("where"));
            whereDetails.setText((CharSequence) whereHash.get("details"));
            if (ibDelWhere != null)
            {
                ibDelWhere.setId(position);
                ibDelWhere.setOnClickListener(new OnClickListener() 
                  {

                    @Override
                    public void onClick(View v) 
                    {
                        //do stuff when clicked
                    }
                  }
                );
            }
        }
        return v;
    }

这个视图由两个左对齐的TextView和一个右对齐的ImageButton组成。当点击按钮时,我想要能够从ListView中删除该项。布局如下 -

    <RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="horizontal" android:clickable="true">
<TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:textSize="25sp" android:id="@+id/tvWhere" android:textColor="#00FF00" android:text="TextView" android:gravity="top|left" android:layout_alignParentTop="true" android:layout_alignParentLeft="true"></TextView>
<TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="@+id/tvWhereDetails" android:textColor="#0000FF" android:text="TextView" android:textSize="18sp" android:layout_below="@+id/tvWhere" android:gravity="bottom|left" android:layout_alignParentLeft="true"></TextView>
<ImageButton android:layout_height="wrap_content" android:layout_width="wrap_content" android:src="@drawable/eraser" android:id="@+id/ibDelWhere" android:layout_alignParentRight="true" android:layout_alignParentTop="true"></ImageButton>
</RelativeLayout>

问题是,当ImageButton位于布局中时,我可以点击它并且onClick()会按预期触发,但是我无法点击实际的列表项本身,即无法点击TextView项目来触发已分配给它的ListView.onItemClick。 如果我从布局中删除ImageButton,则单击项时将触发ListView.onItemClick事件。 有没有办法同时启用单击ListView项目和布局中的按钮? 谢谢大家。
6个回答

24

您需要将ImageButton设置为非 focusable 和非 focusableInTouchMode(可点击是可以的)。

请注意,与其他视图不同,您无法在xml中进行此操作,因为android:focusable会在ImageButton的构造函数中被覆盖。 更准确地说,这是ImageViewImageButton之间的几个差异之一。查看以下是ImageButton完整源代码。

@RemoteView
public class ImageButton extends ImageView {
    public ImageButton(Context context) {
        this(context, null);
    }

    public ImageButton(Context context, AttributeSet attrs) {
        this(context, attrs, com.android.internal.R.attr.imageButtonStyle);
    }

    public ImageButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setFocusable(true);
    }

    @Override
    protected boolean onSetAlpha(int alpha) {
        return false;
    }
}

要解决这个问题,只需从Java中调用setFocusable(false)。或者使用一个ImageView :)

myImageButton.setFocusable(false);

希望能有所帮助。


谢谢。与其他视图不同,您无法在XML中这样做。这些信息非常有用。 - Zafer

2

你可以使两者都可点击,但这并不被官方支持,罗曼·盖伊(Romain Guy)会批评你。此外,你也无法通过轨迹球聚焦/按下按钮。尽管如此,你仍然可以为按钮添加以下属性,这应该能让两者都可点击:

android:focusable="false"
android:focusableInTouchMode="false"

只要确保你能承担后果。


抱歉,那没起作用。我还尝试更改包含TextView和ImageButton的布局的FOCUSABLE属性 - 但也没有任何区别。谢谢。 - daveD
2
我将ImageButton更改为ImageView并连接了点击监听器,它在listview.onItemClick事件中也可以正常工作。它看起来确实是一个焦点问题,不确定为什么你的答案没有起作用。我想我会坚持使用ImageView,只要它是可点击的,就不需要按钮。无论如何,谢谢。 - daveD
@daveD,那正是我通常做的事情。 :) - st0le

1
尝试在相对布局上设置android:clickable="false"。
我曾经遇到过一个类似的问题,即一个LinearLayout嵌套在另一个LinearLayout中。 外部LinearLayout的clickable属性为true,结果是ListView.OnItemClickListener无法触发。 将其设置为clickable=false后,问题得以解决。

谢谢,但是这已经尝试过了,没有起作用。我改变了它的方式,不再使用按钮,而是响应长按。 - daveD

0

我曾经遇到过同样的问题。我的解决方案是在适配器中设置视图的onClick方法,而不是使用onItemClick。

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View v = convertView;
    if(v == null){
        LayoutInflater inflater = context.getLayoutInflater();
        v = inflater.inflate(R.layout.list_item, parent, false);
    }
    v.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            //This should replace the onListItemClick method
        }
    });

    v.findViewById(R.id.someinnerview).setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            //Write one of these for each of your inner views
        }
    });
    return v;
}

希望这能有所帮助!根据您程序的其余部分,这可能会迫使您将更多数据交给适配器(我不得不这样做)但它有效。

0

这是ListView中自定义适配器的示例。

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout  
    android:id="@+id/relativeLayout1"  
   android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    xmlns:android="http://schemas.android.com/apk/res/android"  
   android:padding="5dip">  

   <ImageView  
      android:layout_width="50dip"  
      android:layout_height="50dip"  
    android:id="@+id/imgViewLogo"  
       android:src="@drawable/icon"  
      android:layout_alignParentLeft="true"  
      android:layout_centerInParent="true"  
      android:scaleType="center">  
  </ImageView>  

 <TextView  
      android:textAppearance="?android:attr/textAppearanceLarge"  
       android:layout_height="wrap_content"  
      android:text="TextView"  
      android:layout_width="wrap_content"  
       android:id="@+id/txtViewTitle"  
      android:layout_toRightOf="@+id/imgViewLogo"  
       android:layout_marginLeft="2dip">  
   </TextView>  

  <TextView  
      android:layout_height="wrap_content"  
      android:text="TextView"  
       android:layout_width="wrap_content"  
       android:id="@+id/txtViewDescription"  
       android:layout_toRightOf="@+id/imgViewLogo"  
       android:layout_below="@+id/txtViewTitle"  
       android:layout_marginLeft="2dip">  
  </TextView>   

       <TextView  
      android:layout_height="wrap_content"  
      android:text="TextView"  
       android:layout_width="wrap_content"  
       android:id="@+id/txtViewMobile"  
       android:layout_toRightOf="@+id/imgViewLogo"  
       android:layout_below="@+id/txtViewDescription"  
       android:layout_marginLeft="2dip">  
  </TextView>    

在 BaseAdapter 上创建 Java 文件

public class ListViewCustomAdapter extends BaseAdapter {
Context context;  
String[] mobile;
String[] month;
 String[] number;
 public LayoutInflater inflater; 


public ListViewCustomAdapter(Context context,String[] month, String[] number, String[] mobile) {
    // TODO Auto-generated constructor stub
     super();  
     this.context = context;  
    this.month=month;
    this.number=number;
    this.mobile=mobile;
    Log.i("88888888888888888","*******333********");
    this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
}

 //ADC71C 95AA1F

public int getCount() {  
    // TODO Auto-generated method stub  
    return month.length;  

}  

public Object getItem(int position) {  
    // TODO Auto-generated method stub  
    return position;  
}  

public long getItemId(int position) {  
    // TODO Auto-generated method stub  
    return 0;  
}  

private class ViewHolder {  
    TextView txtViewTitle;  
    ImageView imgViewLogo;  
    TextView txtViewDescription;
    TextView txtViewMobile;

}  

public View getView(int position, View convertView, ViewGroup parent)  
{  
    // TODO Auto-generated method stub 
     Log.i("88888888888888888","*******444********");

    ViewHolder holder;  
    LayoutInflater inflater =  ((Activity) context).getLayoutInflater();  

    if (convertView == null)  
    {  
         Log.i("88888888888888888","*******555********");
        convertView = inflater.inflate(R.layout.listitem_row, null);  
        holder = new ViewHolder();  
        holder.imgViewLogo = (ImageView) convertView.findViewById(R.id.imgViewLogo);  
        holder.txtViewTitle = (TextView) convertView.findViewById(R.id.txtViewTitle);  
        holder.txtViewDescription = (TextView) convertView.findViewById(R.id.txtViewDescription);  
        holder.txtViewMobile = (TextView) convertView.findViewById(R.id.txtViewMobile);
        convertView.setTag(holder);  
    }  
    else  
    {  
         Log.i("88888888888888888","*******666********");
        holder = (ViewHolder) convertView.getTag();  
    }  
    Log.i("888888888888","Display the value of the textbox like(9856321584)other wise (TextView)");
    holder.txtViewTitle.setText(month[position]);  
    holder.txtViewDescription.setText(number[position]); 
    holder.txtViewMobile.setText(mobile[position]);

return convertView;  
}  
}  

0
即点击TextView项以触发已分配给它的ListView.onItemClick。
当您单击TextView时,如果ImageButton存在会发生什么?它会注册按钮的点击吗?还是根本不做任何事情?
ImageButton在行中占用多少空间?它可能足够大,以至于您无法在其外部单击该行。

列表视图项在按钮区域之外可见。除非我移除按钮,否则列表视图的OnItemClickListener事件根本不会触发。 - daveD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接