Java Android中项目的自定义ListView点击问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1121192/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:01:29  来源:igfitidea点击:

Custom ListView click issue on items in Android

javaandroidandroid-listview

提问by MattC

So I have a custom ListView object. The list items have two textviews stacked on top of each other, plus a horizontal progress bar that I want to remain hidden until I actually do something. To the far right is a checkbox that I only want to display when the user needs to download updates to their database(s). When I disable the checkbox by setting the visibility to Visibility.GONE, I am able to click on the list items. When the checkbox is visible, I am unable to click on anything in the list except the checkboxes. I've done some searching but haven't found anything relevant to my current situation. I found this questionbut I'm using an overridden ArrayAdapter since I'm using ArrayLists to contain the list of databases internally. Do I just need to get the LinearLayout view and add an onClickListener like Tom did? I'm not sure.

所以我有一个自定义的 ListView 对象。列表项有两个彼此堆叠的文本视图,还有一个水平进度条,我希望在我实际执行某些操作之前保持隐藏状态。最右边是一个复选框,我只想在用户需要将更新下载到他们的数据库时显示。当我通过将可见性设置为 Visibility.GONE 来禁用复选框时,我可以单击列表项。当复选框可见时,除了复选框之外,我无法单击列表中的任何内容。我已经进行了一些搜索,但没有找到与我目前的情况相关的任何内容。我发现了这个问题但我使用的是一个重写的 ArrayAdapter,因为我使用 ArrayLists 在内部包含数据库列表。我是否只需要像 Tom 一样获取 LinearLayout 视图并添加一个 onClickListener ?我不知道。

Here's the listview row layout XML:

这是列表视图行布局 XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="6dip">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="0dip"
        android:layout_weight="1"
        android:layout_height="fill_parent">
        <TextView
            android:id="@+id/UpdateNameText"
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:textSize="18sp"
            android:gravity="center_vertical"
            />
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:id="@+id/UpdateStatusText"
            android:singleLine="true"
            android:ellipsize="marquee"
            />
        <ProgressBar android:id="@+id/UpdateProgress" 
                     android:layout_width="fill_parent" 
                     android:layout_height="wrap_content"
                     android:indeterminateOnly="false" 
                     android:progressDrawable="@android:drawable/progress_horizontal" 
                     android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal" 
                     android:minHeight="10dip" 
                     android:maxHeight="10dip"                    
                     />
    </LinearLayout>
    <CheckBox android:text="" 
              android:id="@+id/UpdateCheckBox" 
              android:layout_width="wrap_content" 
              android:layout_height="wrap_content" 
              />
</LinearLayout>

And here's the class that extends the ListActivity. Obviously it's still in development so forgive the things that are missing or might be left laying around:

这是扩展 ListActivity 的类。显然它仍在开发中,所以请原谅缺少或可能留下的东西:

public class UpdateActivity extends ListActivity {

    AccountManager lookupDb;
    boolean allSelected;
    UpdateListAdapter list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lookupDb = new AccountManager(this);
        lookupDb.loadUpdates();

        setContentView(R.layout.update);
        allSelected = false;

        list = new UpdateListAdapter(this, R.layout.update_row, lookupDb.getUpdateItems());
        setListAdapter(list);

        Button btnEnterRegCode = (Button)findViewById(R.id.btnUpdateRegister);
        btnEnterRegCode.setVisibility(View.GONE);

        Button btnSelectAll = (Button)findViewById(R.id.btnSelectAll);
        btnSelectAll.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                allSelected = !allSelected;

                for(int i=0; i < lookupDb.getUpdateItems().size(); i++) {
                    lookupDb.getUpdateItem(i).setSelected(!lookupDb.getUpdateItem(i).isSelected());
                }

                list.notifyDataSetChanged();
                // loop through each UpdateItem and set the selected attribute to the inverse 

            } // end onClick
        }); // end setOnClickListener

        Button btnUpdate = (Button)findViewById(R.id.btnUpdate);
        btnUpdate.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
            } // end onClick
        }); // end setOnClickListener

        lookupDb.close();
    } // end onCreate


    @Override
    protected void onDestroy() {
        super.onDestroy();

        for (UpdateItem item : lookupDb.getUpdateItems()) {
            item.getDatabase().close();        
        }
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        UpdateItem item = lookupDb.getUpdateItem(position);

        if (item != null) {
            item.setSelected(!item.isSelected());
            list.notifyDataSetChanged();
        }
    }

    private class UpdateListAdapter extends ArrayAdapter<UpdateItem> {
        private List<UpdateItem> items;

        public UpdateListAdapter(Context context, int textViewResourceId, List<UpdateItem> items) {
            super(context, textViewResourceId, items);
            this.items = items;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View row = null;

            if (convertView == null) {
                LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                row = li.inflate(R.layout.update_row, null);
            } else {
                row = convertView;
            }

            UpdateItem item = items.get(position);

            if (item != null) {
                TextView upper = (TextView)row.findViewById(R.id.UpdateNameText);
                TextView lower = (TextView)row.findViewById(R.id.UpdateStatusText);
                CheckBox cb = (CheckBox)row.findViewById(R.id.UpdateCheckBox);

                upper.setText(item.getName());
                lower.setText(item.getStatusText());

                if (item.getStatusCode() == UpdateItem.UP_TO_DATE) {
                    cb.setVisibility(View.GONE);
                } else {
                    cb.setVisibility(View.VISIBLE);
                    cb.setChecked(item.isSelected());
                }

                ProgressBar pb = (ProgressBar)row.findViewById(R.id.UpdateProgress);
                pb.setVisibility(View.GONE);
            }
            return row;
        }

    } // end inner class UpdateListAdapter
}

edit: I'm still having this problem. I'm cheating and adding onClick handlers to the textviews but it seems extremely stupid that my onListItemClick() function is not being called at all when I am not clicking on my checkbox.

编辑:我仍然有这个问题。我在作弊并将 onClick 处理程序添加到文本视图中,但是当我没有点击我的复选框时,我的 onListItemClick() 函数根本没有被调用,这似乎非常愚蠢。

采纳答案by MattC

The issue is that Android doesn't allow you to select list items that have elements on them that are focusable. I modified the checkbox on the list item to have an attribute like so:

问题是 Android 不允许您选择具有可聚焦元素的列表项。我修改了列表项上的复选框,使其具有如下属性:

android:focusable="false"

Now my list items that contain checkboxes (works for buttons too) are "selectable" in the traditional sense (they light up, you can click anywhere in the list item and the "onListItemClick" handler will fire, etc).

现在,我的包含复选框的列表项(也适用于按钮)在传统意义上是“可选择的”(它们亮起,您可以单击列表项中的任意位置并且“onListItemClick”处理程序将触发等)。

EDIT: As an update, a commenter mentioned "Just a note, after changing the visibility of the button I had to programmatically disable the focus again."

编辑:作为更新,评论者提到“只是一个说明,在更改按钮的可见性后,我不得不再次以编程方式禁用焦点。”

回答by Andrew Burgess

I've had a similar issue occur and found that the CheckBox is rather finicky in a ListView. What happens is it imposes it's will on the entire ListItem, and sort of overrides the onListItemClick. You may want to implement a click handler for that, and set the text property for the CheckBox as well, instead of using the TextViews.

我遇到了类似的问题,发现 ListView 中的 CheckBox 相当挑剔。发生的事情是它将它的意志强加于整个 ListItem,并在某种程度上覆盖 onListItemClick。您可能希望为此实现一个点击处理程序,并为 CheckBox 设置 text 属性,而不是使用 TextViews。

I'd say look into this View object as well, it may work better than the CheckBox

我想说也看看这个 View 对象,它可能比 CheckBox 工作得更好

Checked Text View

选中的文本视图

回答by micnoy

In case you have ImageButton inside the list item you should set the descendantFocusabilityvalue to 'blocksDescendants' in the root list item element.

如果列表项中有 ImageButton,则应descendantFocusability在根列表项元素中将该值设置为 'blocksDescendants'。

android:descendantFocusability="blocksDescendants"

And the focusableInTouchModeflag to truein the ImageButtonview.

focusableInTouchMode标志true中的ImageButton视图。

android:focusableInTouchMode="true"

回答by Suresh kumar

use this line in the root view of the list item

在列表项的根视图中使用此行

android:descendantFocusability="blocksDescendants"

android:descendantFocusability="blocksDescendants"