如何让android listview项目select器使用state_checked

我的头发试图得到一个Android ListView做我想做的事情。

我想有一个ListView在单选模式下的自定义行布局,具有不同的背景颜色select,按下和检查(即select显示一个颜色,而不是一个复选标记 – 这是我通常所说的“select”,但select在android似乎线我要select之前,我按它)

我想过尝试一个背景select器,其中的三个状态。 它适用于state_selected和state_pressed,但不是state_checked。 所以我创build了一个CheckableRelativeLayout来扩展RelativeLayout并实现Checkable并用于每行的视图。

这里显示了一个简化的版本:

<my.package.CheckableRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/bkg_selector"> > <ImageView android:id="@+id/animage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" /> </my.package.CheckableRelativeLayout> 

bkg_selector看起来像

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/purple" /> <item android:state_checked="true" android:drawable="@drawable/red" /> <item android:state_selected="true" android:drawable="@drawable/darkpurple" /> <item android:drawable="@drawable/black" /> </selector> 

颜色在其他地方定义。

这仍然没有工作。 所以在自定义ListAdapter我跟踪“检查”行,并试图(在getView中)

if(position == checkedPosition)ret.getBackground()。setState(CHECKED_STATE_SET);

它仍然不起作用。 我怎样才能做到我想要的?

Solutions Collecting From Web of "如何让android listview项目select器使用state_checked"

你需要在你的CheckableRelativeLayout中覆盖onCreateDrawableState,并设置Clickable =“true”。 我的LinearLayout代码:

 public class CheckableLinearLayout extends LinearLayout implements Checkable { private boolean checked = false; public CheckableLinearLayout(Context context) { super(context, null); } public CheckableLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } private static final int[] CheckedStateSet = { R.attr.state_checked }; public void setChecked(boolean b) { checked = b; } public boolean isChecked() { return checked; } public void toggle() { checked = !checked; } @Override protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CheckedStateSet); } return drawableState; } @Override public boolean performClick() { toggle(); return super.performClick(); } 

比这更好,而不是设置clickable = true并覆盖CheckableLinearLayout的performClick(),保持Pavel的build议,覆盖onCreateDrawableState和取代CheckableLinearLayout的setChecked()由以下几点:

 private final List<Checkable> mCheckableViews = new ArrayList<Checkable>(); @Override protected void onFinishInflate() { super.onFinishInflate(); final int childCount = getChildCount(); findCheckableChildren(this); } private void findCheckableChildren(View v) { if (v instanceof Checkable && v instanceof ViewGroup) { mCheckableViews.add((Checkable) v); } if (v instanceof ViewGroup) { final ViewGroup vg = (ViewGroup) v; final int childCount = vg.getChildCount(); for (int i = 0; i < childCount; ++i) { findCheckableChildren(vg.getChildAt(i)); } } } @Override public void setChecked(boolean checked) { mChecked = checked; for (Checkable c : mCheckableViews) { c.setChecked(checked); } refreshDrawableState(); } 

它会避免点击和长按callback的问题。

恕我直言,使用自定义适配器更容易:

 class CustomAdapter extends ArrayAdapter<CustomRowItem> { Context context; public CustomAdapter(Context context, int resourceId, List<CustomRowItem> items) { super(context, resourceId, items); this.context = context; } private class ViewHolder { TextView txt; View layout; } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; CustomRowItem rowItem = getItem(position); LayoutInflater mInflater = (LayoutInflater) context .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); if (convertView == null) { convertView = mInflater.inflate(R.layout.сustom_list, null); holder = new ViewHolder(); holder.txt = (TextView) convertView.findViewById(R.id.сustom_list_txt); holder.layout = convertView.findViewById(R.id.сustom_list_layout); convertView.setTag(holder); } else holder = (ViewHolder) convertView.getTag(); holder.txt.setText(rowItem.getText()); if(rowItem.isChecked()) holder.layout.setBackgroundColor(-16720999); //color for checked else holder.layout.setBackgroundColor(0); //color for unchecked return convertView; } } class CustomRowItem { private boolean value; private String text; public CustomRowItem(String text, boolean value) { this.text = text; this.value = value; } public boolean isChecked() { return value; } public void setChecked(boolean checked) { value = checked; } public String getText() { return text; } void setText(String text) { this.text = text; } } 

сustom_list.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="fill_parent" android:padding="10dp" android:id="@+id/сustom_list_layout" android:orientation="vertical" > <TextView android:id="@+id/сustom_list_txt" android:textSize="20sp" android:layout_width="fill_parent" android:layout_height="fill_parent"/> </LinearLayout> 

如何使用:

 public class ExampleAct extends Activity { final List<CustomRowItem> list = new ArrayList<CustomRowItem>(); CustomAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.example); ListView listView=(ListView)findViewById(R.id.listView); adapter = new CustomAdapter(this, R.layout.сustom_list, list); listView.setAdapter(adapter); list.add(new CustomRowItem("unchecked item",false)); list.add(new CustomRowItem("checked item",true)); adapter.notifyDataSetChanged(); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { //unchecked on click @Override public void onItemClick(AdapterView<?> parent, View itemClicked, int index, long id) { if(list.get(index).isChecked()) { list.get(index).setChecked(false); //uncheck adapter.notifyDataSetChanged(); } else { // other actions } }); listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { //checked on long click @Override public boolean onItemLongClick(AdapterView<?> parent, View itemClicked, int index, long id) { list.get(index).setChecked(true); //check adapter.notifyDataSetChanged(); return true; // or false for calling context menu } }); }