在 Android 中单击项目的自定义 ListView 问题

所以我有一个自定义 ListView 对象。列表项有两个文本视图叠加在一起,加上一个水平进度条,我想保持隐藏,直到我真正做了一些事情。最右边是一个复选框,我只想在用户需要下载数据库更新时显示它。当我通过将可见性设置为 Visibility.GONE 来禁用复选框时,我可以单击列表项。当复选框可见时,除了复选框之外,我无法单击列表中的任何内容。我做了一些调查,但没有找到任何与我目前的处境相关的东西。我找到了 这个问题,但是我正在使用一个被覆盖的 ArrayAdapter,因为我正在使用 ArrayList 在内部包含数据库列表。我是否只需要获取 LinearLayout 视图并像 Tom 那样添加一个 onClickListener?我不确定。

下面是 listview 行布局 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>

这是扩展 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 处理程序,但是当我没有单击复选框时,根本没有调用 onListItemClick ()函数,这看起来非常愚蠢。

80731 次浏览

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.

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

Checked Text View

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: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).

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."

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

android:descendantFocusability="blocksDescendants"

And the focusableInTouchMode flag to true in the ImageButton view.

android:focusableInTouchMode="true"

use this line in the root view of the list item

android:descendantFocusability="blocksDescendants"