Android中项目的自定义ListView点击问题
Posted
技术标签:
【中文标题】Android中项目的自定义ListView点击问题【英文标题】:Custom ListView click issue on items in Android 【发布时间】:2010-11-10 09:48:07 【问题描述】:所以我有一个自定义 ListView 对象。列表项有两个堆叠在一起的文本视图,加上一个水平进度条,我想在我真正做某事之前一直隐藏它。最右边是一个复选框,我只想在用户需要将更新下载到他们的数据库时显示。当我通过将可见性设置为 Visibility.GONE 来禁用复选框时,我可以单击列表项。当复选框可见时,除了复选框之外,我无法单击列表中的任何内容。我已经进行了一些搜索,但没有找到与我当前情况相关的任何内容。我找到了this question,但我使用的是重写的 ArrayAdapter,因为我使用 ArrayLists 在内部包含数据库列表。我只需要像 Tom 那样获取 LinearLayout 视图并添加一个 onClickListener 吗?我不确定。
这是列表视图行布局 XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:padding="6dip">
<LinearLayout
android:orientation="vertical"
android:layout_
android:layout_weight="1"
android:layout_>
<TextView
android:id="@+id/UpdateNameText"
android:layout_
android:layout_
android:layout_weight="1"
android:textSize="18sp"
android:gravity="center_vertical"
/>
<TextView
android:layout_
android:layout_
android:layout_weight="1"
android:id="@+id/UpdateStatusText"
android:singleLine="true"
android:ellipsize="marquee"
/>
<ProgressBar android:id="@+id/UpdateProgress"
android:layout_
android:layout_
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_
android:layout_
/>
</LinearLayout>
这是扩展 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
编辑:我仍然有这个问题。我在作弊并将 onClick 处理程序添加到 textviews 但是当我不点击我的复选框时根本没有调用我的 onListItemClick() 函数似乎非常愚蠢。
【问题讨论】:
【参考方案1】:问题在于 Android 不允许您选择具有可聚焦元素的列表项。我修改了列表项上的复选框,使其具有如下属性:
android:focusable="false"
现在我的包含复选框的列表项(也适用于按钮)在传统意义上是“可选择的”(它们会亮起,您可以单击列表项中的任意位置,“onListItemClick”处理程序将触发,等等)。
编辑:作为更新,评论者提到“只是一个注释,在更改按钮的可见性后,我不得不再次以编程方式禁用焦点。”
【讨论】:
在列表项中使用 ImageButton 时出现此解决方案不起作用。 :( 好的,但是如果我希望我的复选框和我的列表视图单击是互斥的呢?如果我选择 ListView 项,我不一定要选中复选框。这个解决方案有可能吗? @Mike 是的,此解决方案仍然需要明确单击复选框才能与之交互。它只是重新启用 ListView 中的功能,当您的列表项布局中有可聚焦元素时,神秘地会被绕过。 很好的答案谢谢,也适用于 ImageButtons。请注意,在更改按钮的可见性后,我不得不再次以编程方式禁用焦点。 你可能还需要设置android:clickable="false"【参考方案2】:如果列表项中有 ImageButton,则应在根列表项元素中将 descendantFocusability
值设置为“blocksDescendants”。
android:descendantFocusability="blocksDescendants"
以及ImageButton
视图中true
的focusableInTouchMode
标志。
android:focusableInTouchMode="true"
【讨论】:
这非常适用于具有图像按钮的列表项。 But this might work except ImageButton【参考方案3】:我遇到过类似的问题,发现 CheckBox 在 ListView 中相当挑剔。发生的事情是它将它的意志强加于整个 ListItem,并在某种程度上覆盖了 onListItemClick。您可能希望为此实现一个单击处理程序,并为 CheckBox 设置 text 属性,而不是使用 TextViews。
我想说看看这个 View 对象,它可能比 CheckBox 更好用
Checked Text View
【讨论】:
我发现如果将列表中可聚焦项目的“focusable”设置为false,您可以再次使用onListItemClick函数。 但是复选框像列表项一样变成橙色。有人知道解决方案吗?【参考方案4】:在列表项的根视图中使用这一行
android:descendantFocusability="blocksDescendants"
【讨论】:
以上是关于Android中项目的自定义ListView点击问题的主要内容,如果未能解决你的问题,请参考以下文章
Android ListView 和带有 ViewHolder 的自定义适配器
ArrayIndexOutOfBoundsException 与 ListView 中的多个视图的自定义 Android 适配器
Android ListView ClickEvent 不起作用