ListView:setItemChecked只适用于标准ArrayAdapter – 在使用自定义ArrayAdapter时不起作用?

这真的很奇怪。

当我使用标准的ArrayAdapter进行ListView调用时,setItemChecked工作正常

但是,当使用自定义的ArrayAdapter它不。

会是什么原因? 这是一个错误? 还是我错过了什么?

public class Test_Activity extends Activity { /** Called when the activity is first created. */ private List<Model> list; private ListView lView; public void onCreate(Bundle icicle) { super.onCreate(icicle); // Create an array of Strings, that will be put to our ListActivity setContentView(R.layout.main); lView = (ListView) findViewById(R.id.ListView01); lView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); list = getModel(); //with this adapter setItemChecked works OK lView.setAdapter(new ArrayAdapter<Model>(this, android.R.layout.simple_list_item_multiple_choice, list)); //************************** //PROBLEM: with this adapter it does not check any items on the screen // ArrayAdapter<Model> adapter = new Test_Class1(this, list); // lView.setAdapter(adapter); } private List<Model> getModel() { List<Model> list = new ArrayList<Model>(); list.add(get("0")); list.add(get("1")); list.add(get("2")); list.get(1).setSelected(true); Model m = list.get(1); list.add(get("3")); list.add(get("4")); list.add(get("5")); list.add(get("6")); list.add(get("7")); // Initially select one of the items return list; } private Model get(String s) { return new Model(s); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.results_screen_option_menu, menu); return true; } /** * @category OptionsMenu */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.select_all: { int size = lView.getAdapter().getCount(); for (int i = 0; i <= size; i++) { //************************** PROBLEM lView.setItemChecked(i, true); // selects the item only for standard ArrayAdapter Log.i("xxx", "looping " + i); } } return true; case R.id.select_none: return true; } return false; } } 

// ———————————————— ————

 public class Test_Class1 extends ArrayAdapter<Model> { private final List<Model> list; private final Activity context; public Test_Class1(Activity context, List<Model> list) { super(context, R.layout.rowbuttonlayout2, list); this.context = context; this.list = list; } static class ViewHolder { protected TextView text; protected CheckBox checkbox; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = null; Log.i("xxx", "-> getView " + position); if (convertView == null) { LayoutInflater inflator = context.getLayoutInflater(); view = inflator.inflate(R.layout.rowbuttonlayout, null); final ViewHolder viewHolder = new ViewHolder(); viewHolder.text = (TextView) view.findViewById(R.id.label); viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check); viewHolder.checkbox .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { Model element = (Model) viewHolder.checkbox .getTag(); Log.i("xxx", "-> onCheckedChanged"); element.setSelected(buttonView.isChecked()); Log.i("xxx", "<- onCheckedChanged"); } }); view.setTag(viewHolder); viewHolder.checkbox.setTag(list.get(position)); } else { view = convertView; ((ViewHolder) view.getTag()).checkbox.setTag(list.get(position)); } ViewHolder holder = (ViewHolder) view.getTag(); holder.text.setText(list.get(position).getName()); Log.i("xxx", "holder.checkbox.setChecked: " + position); holder.checkbox.setChecked(list.get(position).isSelected()); Log.i("xxx", "<- getView " + position); return view; } } 

您的行布局需要可setItemChecked()才能工作,在这种情况下,Android会在用户点击行时pipe理您的Checkable上的setChecked() 。 你不需要设置你自己的OnCheckedChangeListener

更多信息,请参阅:

当然,你必须为你的ListView设置select模式,例如:

 list.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 

但是,如果您还为列表项(R.layout.drawing_list_item)使用自定义布局,则必须确保您的布局实现了Checkable接口:

 public class CheckableRelativeLayout extends RelativeLayout implements Checkable { public CheckableRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); } private boolean isChecked = false; public boolean isChecked() { return isChecked; } public void setChecked(boolean isChecked) { this.isChecked = isChecked; changeColor(isChecked); } public void toggle() { this.isChecked = !this.isChecked; changeColor(this.isChecked); } private void changeColor(boolean isChecked){ if(isChecked){ setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light)); }else{ setBackgroundColor(getResources().getColor(android.R.color.transparent)); } } 

}

然后,您的可检查布局将被定义为以下示例:

 <?xml version="1.0" encoding="utf-8"?> 
 <ImageView android:id="@+id/agenzie_item_icon" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:background="@android:color/darker_gray" android:focusable="false" /> <TextView android:id="@+id/agenzie_item_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@+id/agenzie_item_icon" android:focusable="false" android:paddingLeft="10dp" android:text="item" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="#FFFFFF" /> 

Checkable是我现在不想采取的学习曲线。 您可以在“活动”的OnItemClickListener手动设置和取消设置checkbox。 在ArrayAdapter<MyObject>MyObject列表中维护一个boolean isChecked瞬态variables。

 public void onItemClick(AdapterView<?> av, View v, int position, long arg3) { final ListView listView = (ListView) findViewById(android.R.id.list); MyObject item = (MyObject) listView.getItemAtPosition(position); item.isChecked = !item.isChecked; if(item.isChecked) addItem(item); else removeItem(item); } 

为用户单击CheckBox本身; 在自定义数组适配器的getView实现中,在CheckBoxOnClickListener使用相同的addItem(item)/ removeItem(item)逻辑。

 public View getView(int position, View convertView, ViewGroup viewGroup) { CheckBox cb = null; if (convertView == null) { if(inflater == null) //cache to avoid reconstructing for each view inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView =inflater.inflate(R.layout.list_item_text_right_checkmark, null); CheckBox cb = (CheckBox) convertView.findViewById(R.id.check); cb.setChecked((list.get(position).isChecked)); cb.setTag(list.get(position); public void onClick(View v) { if(v instanceof CheckBox) { CheckBox cb = (CheckBox) v; if(cb.isChecked()) //verify boolean logic here!!! activityRef.get().addItem(cb.getTag()); //WeakReference to activity else activityRef.get().removeItem(cb.getTag()); } }); } else cb = (CheckBox) convertView.findViewById(R.id.check); cb.setChecked((list.get(position).isChecked)); ... } 

调用CheckBox :: setChecked()是这里的关键。
这似乎只是你的arrays适配器可以采取相同的行为,而你的arrays适配器可以在res / layout /中采用相同的列表项xml定义。

可检查列表项XML:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@+id/check" android:gravity="center_vertical" android:paddingLeft="8dp" android:textAppearance="?android:attr/textAppearanceMedium" /> <CheckBox android:id="@+id/check" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:focusable="false"/> </RelativeLayout> 

如果您最初需要检查一些CheckBox,只需在充气前将MyChecked成员设置在MyObject中。

没有任何回应为我工作。 我的问题是,只有从OnCreate / OnStart / OnPause最初调用ExpandableListView.setItemChecked没有工作,如果视图尚未完全初始化。 为了解决这个问题,我必须做到以下几点:

 _expandableListView.Post(() => { _expandableListView.SetItemChecked(fragmentPosition, true); });