将 CheckBox 添加到列表行会丢失我的 onItemClick 事件?

Posted

技术标签:

【中文标题】将 CheckBox 添加到列表行会丢失我的 onItemClick 事件?【英文标题】:adding CheckBox to list row loses my onItemClick events? 【发布时间】:2011-07-19 10:37:44 【问题描述】:

我有一个带有 ArrayList 适配器的 ListView。行不是很复杂(左侧的图像,内部带有 TextViews 的 LinearLayout,右侧的 CheckBox ......布局复制到下面。)目标是在用户单击时出现 QuickAction 栏在图像或文本上,如果用户单击 CheckBox,则 CheckBox 会更改状态。我让每个部分独立工作,但不是当它们在布局中一起工作时 - 不知何故,我失去了 onItemClick 事件。

“QuickAction”栏由 OnItemClickListener() 激活,它工作正常 - 除非我在布局中有 CheckBox,在这种情况下 CheckBox 工作正常(使用 onClick())但如果用户在行中但在 CheckBox 之外单击。布局(减去一些样式的东西)是:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/vw1"
    android:layout_
    android:layout_
    android:orientation="horizontal">

    <ImageView android:id="@+id/img"
        android:layout_alignParentLeft="true"
        android:layout_
        android:layout_/>

    <CheckBox android:id="@+id/ckb"
    android:layout_
    android:layout_
    android:layout_alignParentRight="true"
    android:layout_gravity="right"
    android:checked="false" />

<!-- stack text in middle section of the row -->
    <LinearLayout
        android:layout_
        android:layout_
        android:orientation="vertical"
        >

        <TextView android:id="@+id/text1"
            android:layout_
            android:layout_"/>

        <TextView android:id="@+id/text2"
            android:layout_
            android:layout_/>
    </LinearLayout>
</RelativeLayout>

背后的代码并不复杂:

public class ListGroupsActivity extends BaseActivityForList 
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list);

        // add QuickAction bar
        ListView lv = getListView();
        lv.setOnItemClickListener(new QAListener(this));
    


    //inner classes of the ListGroupsActivity
    class CbOnClickListener implements OnClickListener 
        // ...
        // test the checkbox isChecked() and keep state in 'selectedItems' array

    class GroupListAdapter extends ArrayAdapter<Group> 
        super(/*...*/)
    CbOnClickListener cblistener = null; // common listener for all the CheckBoxes

        @Override
        public View getView(int position, View convertView, ViewGroup parent) 
            // here do normal testing for convertView being null etc 
            // heres the view inflation from the layout into the ViewHolder
            holder.tv1 = (TextView) convertView.findViewById(R.id.text1);
            holder.tv2 = (TextView) convertView.findViewById(R.id.text2);
            holder.img = (ImageView) convertView.findViewById(R.id.img);
            holder.ckb = (CheckBox) convertView.findViewById(R.id.ckb);

            Group g = groups.get(position); // this is the data obj for the row

            holder.tv1.setText(g.getName());
            holder.tv2.setText("child groups");
            Bitmap bm = BitmapFactory.decodeFile(g.getIconUri());
            holder.img.setImageBitmap(bm);
            Integer key = (Integer) g.getId();
            holder.ckb.setChecked(selectedItems.contains(key)); 

            holder.ckb.setOnClickListener(cblistener); // hook onClick to cblistener
            return convertView;
    

QAListener 位于我所有列表活动的超类中:

public class BaseActivityForList extends
    OrmLiteBaseListActivity<DatabaseHelper> 

    // QAListener inner class, constructs new quick action bar when item clicked
    class QAListener implements OnItemClickListener 
        public void onItemClick(AdapterView<?> parent, View view,
                                int position, long id) 
            // has three ActionItem instances, 'copyAction', 'delAction', 'editAction'
            ActionItem copyAction = new ActionItem();

            copyAction.setOnClickListener(new OnClickListener() 
                 @Override
                 public void onClick(View v) 
                     // ... does some stuff
                     mQuickAction.dismiss();
                 
             ); // end setOnClickListener
         // end onItemClick
     // end QAListener
 end BaseActivityForList

那么,如何安排 Checkbox 拾取 onClick,而列表的其余部分拾取 onItemClick()?

【问题讨论】:

【参考方案1】:

经过几个小时的调试和研究。我得到它的工作 在复选框上设置以下属性:

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

ImageView 也可能需要按照http://blog.sachin.name/?p=62 中的描述进行配置(感谢那个人)

在我这边,我发现项目视图不能是可点击的,文本视图也不应该是可点击的。我花了一段时间才意识到我在代码中某处的项目视图上调用了 setClickable(true)。

【讨论】:

我认为这通常适用于嵌套可点击元素的情况。我在使用 GridView 时遇到了类似的问题,当添加到 GridView 中包含的 CheckBox 时,这解决了问题。 @Alex:如果您执行上述操作,如何检查复选框? @esse:我和你有同样的问题(使用网格视图)。我在我的复选框属性中添加了上面的代码,但我仍然没有收到任何事件。【参考方案2】:

只是为了补充这个公认的答案:在 ImageButton 而不是 CheckBox 的情况下,将 xml focusablefocusableInTouchMode 设置为 false 是不够的,但在运行时需要聚焦设置为假。这意味着要确保检测到onItemClick,必须这样做:

button.setFocusable(false);

所以事情完全正常......作者here的原始学分。希望它对某人有所帮助。

干杯 ;)

编辑:还有更优雅的解决方案尝试在列表元素的根布局中添加android:descendantFocusability="blocksDescendants"。这将使点击 onListItem 成为可能,并且您可以单独处理 Button 或 ImageButton 点击​​

【讨论】:

以上是关于将 CheckBox 添加到列表行会丢失我的 onItemClick 事件?的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin 表单列表视图添加幻灯片功能

如何使用 Ajax 将复选框信息添加到 MySQL 数据库?

关于JS 事件冒泡和onclick,click,on()事件触发顺序

如何将复选框添加到 ListActivity 而不会丢失 onListItemClick 功能?

VS2017将程序添加到“打开方式”列表中

将选中的复选框值添加到下拉列表中