复选框列表项无法点击

23
我有一个包含复选框的列表项,我想能够单击复选框和列表项本身。不幸的是,似乎存在某种冲突,因为当我注释掉复选框时,我只能单击该项。我记得有一种方法可以解决这个问题,但是我现在找不到了。谢谢。
编辑:这是使用ListFragment的情况,所以无需调用setOnItemClickListener。
好的,这是列表项的XML。问题出在复选框上,但我觉得最好把所有内容都复制一遍。
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_item_survey"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    style="@style/SimpleListItem">
    <TextView
        android:id="@+id/survey_title"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        style="@style/ListItemTitle" />
    <TextView
        android:id="@+id/survey_date"
        android:layout_below="@id/survey_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/ListItemSubtitle" />
    <TextView
        android:id="@+id/survey_completed"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_below="@id/survey_title"
        android:textColor="@color/accent_1"
        android:text="@string/survey_completed"
        style="@style/ListItemSubtitle" />
    <CheckBox
        android:id="@+id/survey_did_not_attend"
        android:layout_below="@id/survey_date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/survey_did_not_attend"
        android:focusable="false"
        style="@style/ListItemSubtitle" />
 </RelativeLayout>

展示一下你正在尝试的代码。 - Lalit Poptani
@Shawan Lauzon:请指定您的主要列表代码,以便更好地理解您的问题。 - Rahul Mandaliya
嗯,看起来这要么是一个错误,要么就是按设计工作的:http://code.google.com/p/android/issues/detail?id=3414&can=1&q=listview&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars - Shawn Lauzon
9个回答

28
你需要将android:descendantFocusability="blocksDescendants"添加到你的自定义适配器 XML 文件中。

4
适配器XML文件有点令人困惑,它是项目XML文件的一种。 - Dominic

23

将此内容插入到项行的根元素的XML文件中

android:descendantFocusability="blocksDescendants"

对我有用...添加到根元素中。 - For Guru

8

此处此处所述,这要么是一个已知的问题,要么是按设计工作。如果列表项中有任何可单击或可聚焦的项,则列表项本身无法被单击。Romain Guy 表示,“这是有意为之,以支持轨迹球/ dpad 导航。”


6
这对我起了作用。
<CheckBox
...                
android:focusable="false"
android:clickable="false"
android:focusableInTouchMode="false" />

android:clickable="false" 是唯一对我有效的方法。谢谢。 - Brian Tacker

1
我是这样解决问题的。我在适配器中实现了OnClickListener,而不是在Fragment/Activity中实现,它运行良好。现在我可以使用带有复选框的ListView,并且可以同时单击两者。以下是我的代码:
public class MyFragment extends Fragment
{
    ...

    private void setView()
    {
        ListView listView = (ListView) mRootView.findViewById(R.id.listview);
        mItems = DatabaseManager.getManager().getItems();

        // create adapter
        if(listView.getAdapter()==null)
        {
            MyAdapter adapter = new MyAdapter(this, mItems);
            try
            {
                listView.setAdapter(adapter);
            }
            catch(Exception e)
            {
                e.printStackTrace();
                return;
            }
        } 
        else 
        {
            try
            {
                ((MyAdapter) listView.getAdapter()).refill(mItems);
                BaseAdapter adapter = (BaseAdapter) listView.getAdapter();
                listView.requestLayout();
                adapter.notifyDataSetChanged();
            }
            catch(Exception e)
            {
                e.printStackTrace();
                return;
            }
        }

        // handle listview item click
        listView.setClickable(true);
        // listView.setOnItemClickListener(...); // this method does not work in our case, so we can handle that in adapter
    }

    ...
}


public class MyAdapter extends BaseAdapter
{
    ...

    @Override
    public View getView(final int position, View convertView, ViewGroup parent)
    {
        View view = convertView;
        if (view == null) 
        {
            LayoutInflater inflater = (LayoutInflater) mFragment.getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.listview_item, null);
        }

        ...

        // handle listview item click
        // this method works pretty well also with checkboxes
        view.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                // do something here
                // for communication with Fragment/Activity, you can use your own listener
            }
        });

        return view;
    }

    ...
}

1
你尝试过设置吗?
android:focusable="false"
android:focusableInTouchMode="false"

?

它对我有效。


1

通过使用android:descendantFocusability="blocksDescendants",它能够正常工作。


0

好的.. 创建一个 CheckBox 实例,像这样

CheckBox check;
check = (CheckBox) myView.findViewById(R.id.check);
check.setOnClickListener(new CheckBoxSelect(position));

将上述代码放置在您正在使用的onItemClickListenerAdapter中。现在创建一个类,如下所示。
private class CheckBoxSelect implements OnClickListener 
    {
        int pos;
        String str;

        public CheckBoxSelect(int position) 
        {
            pos = position;
        }

        public void onClick(View v) 
        {

        }

    }

onClick 中执行任何功能。


问题不在于复选框,而在于ListView中的项目无法点击。 - Shawn Lauzon
你使用过 listView.setClickable(true) 吗?如果没有,请在 onItemClickListener 之前加上。 - Balban
这是一个ListFragment,所以嵌入的ListView会自动可点击。请参见上面的答案——这是SDK中的一个问题。 - Shawn Lauzon

0

虽然有些晚了,但这是为所有仍需要它的人提供的解决方案。

确实,使用内置机制:

final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
    getActivity(),
    android.R.layout.simple_list_item_multiple_choice, lst);

不允许同时进行两个操作,即勾选复选框和点击列表项。无论在哪里单击,复选框都会捕获事件。

但是,如果您使用getView创建自己的ArrayAdapter,就可以正常工作:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (v == null) {
        LayoutInflater vi = (LayoutInflater) mContext
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.list_item_ecu_fehler, null);
    }

    v.setFocusable(true);
    v.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
        if (DEBUG)
            Log.i(this.getClass().getSimpleName(),
                " ->>"
                    + Thread.currentThread().getStackTrace()[2]
                        .getMethodName());
        }
    });

            CheckBox selectedForClearingCB = (CheckBox) v
            .findViewById(R.id.checkBox);


        if (selectedForClearingCB != null) {
        selectedForClearingCB.setTag(position); //so we know position in the list       selectedForClearingCB.setChecked(true);
        selectedForClearingCB.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

            if (((CheckBox) v).isChecked()) {
                if (DEBUG)
                Log.i(this.getClass().getSimpleName(),
                    " -> CB checked: "
                        + Integer.toString((Integer) v
                            .getTag()));

            }

            }
        });
        }
    }
    return v;
    }

}

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