设置从适配器检查的ListView项目

我有一个ListView显示2种项目。 其中一种包含CheckedTextView。 作为一个适配器,我正在使用自定义适配器扩展ArrayAdapter的数据结构,其中包含有关内部选中/未选中状态的信息。

有些项目被标记为选中(在我的数据结构中),所以当然我希望在创buildListView时标记checkbox。 我试图用CheckedTextView的setChecked()方法在适配器中的getView()方法,但它不起作用。 我发现它应该在ListView级别上使用setItemChecked()完成的信息,它确实工作,但它对我来说没有意义,因为要使它工作,我将不得不循环activity的onCreate()中的所有项目调用setItemChecked()为那些select。 项目列表可能很长,只有less数select,所以这是一个浪费。

为什么在getView()中调用setChecked()不起作用? 有没有更好的方式做到这一点(我是一个Android新手)。

下面你有我的检查项目布局和适配器。

布局:

<?xml version="1.0" encoding="utf-8"?> <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="fill_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:gravity="center_vertical" android:textAppearance="@style/listViewItemText" android:checkMark="?android:attr/listChoiceIndicatorMultiple" android:paddingLeft="6dp" android:paddingRight="6dp" /> 

适配器:

 package com.melog.re.droid.search; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.CheckedTextView; import android.widget.TextView; import com.melog.re.droid.core.R; import com.melog.re.droid.search.MultiCriterionValue.MultiCriterionSingleValue; import com.melog.re.droid.search.MultiListAdapter.MultiChoiceItem; public class MultiListAdapter extends ArrayAdapter<MultiChoiceItem> { private static final int VIEW_TYPES_COUNT = 2; public static final int VIEW_TYPE_GROUP = 0; public static final int VIEW_TYPE_ITEM = 1; private LayoutInflater mInflater; public MultiListAdapter(Context context, int textViewResourceId, List<MultiChoiceItem> objects) { super(context, textViewResourceId, objects); mInflater = LayoutInflater.from(context); } @Override public int getItemViewType(int position) { MultiChoiceItem item = getItem(position); return (item.children.size() == 0) ? VIEW_TYPE_ITEM : VIEW_TYPE_GROUP; } @Override public int getViewTypeCount() { return VIEW_TYPES_COUNT; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO: optymalizacja ViewHolder MultiChoiceItem item = getItem(position); int viewType = getItemViewType(position); switch (viewType) { case VIEW_TYPE_GROUP: if (convertView == null) { convertView = mInflater.inflate(R.layout.multi_choice_group_item, parent, false); } TextView groupLabel = (TextView) convertView.findViewById(android.R.id.text1); groupLabel.setText(item.toString()); break; case VIEW_TYPE_ITEM: if (convertView == null) { convertView = mInflater.inflate(R.layout.multi_choice_child_item, parent, false); } CheckedTextView itemLabel = (CheckedTextView) convertView.findViewById(android.R.id.text1); itemLabel.setText(item.toString()); itemLabel.setChecked(item.selected); break; } return convertView; } public static class MultiChoiceItem implements Parcelable { public static final int CONTENTS_DESCR = 1; public String label; public String value; public boolean selected = false; public ArrayList<MultiChoiceItem> children = new ArrayList<MultiChoiceItem>(); public MultiChoiceItem(String l, String v, boolean sel) { label = l; value = v; selected = sel; } public MultiChoiceItem(MultiCriterionSingleValue v) { label = v.toString(); value = v.value; } public MultiChoiceItem(Parcel in) { label = in.readString(); value = in.readString(); selected = (in.readInt() == 1); } @Override public String toString() { return label; } @Override public int describeContents() { return CONTENTS_DESCR; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(label); dest.writeString(value); dest.writeInt(selected ? 1 : 0); } public static final Parcelable.Creator<MultiChoiceItem> CREATOR = new Parcelable.Creator<MultiChoiceItem>() { public MultiChoiceItem createFromParcel(Parcel in) { return new MultiChoiceItem(in); } public MultiChoiceItem[] newArray(int size) { return new MultiChoiceItem[size]; } }; } } 

和一个活动的onCreate()

 ... mAdapter = new MultiListAdapter(this, R.id.head, mItems); setListAdapter(mAdapter); final ListView listView = getListView(); listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); listView.setItemsCanFocus(false); ... 

编辑:

在find更好的解决scheme之前,我在Activity中实现了检查:

 ... int len = mListView.getCount(); for (int i = 0; i < len; i++) { if (((MultiChoiceItem) mListView.getItemAtPosition(i)).selected) { mListView.setItemChecked(i, true); } } ... 

我认为performance将是唯一的潜在问题,但我发现了另一个 – 更严重。 该列表启用了文本filter(mListView.setTextFilterEnabled(true))。 这是故障情况:

  1. 我正在打开新的列表
  2. 我检查让我们说第二项
  3. 我开始input来过滤一些项目
  4. 当过滤完成后,第二项仍然被检查,即使它不是我检查的那个

我假设setItemChecked()在被选中的列表上标记了一个固定的位置,而我需要的东西将会标记保存在这个位置上的Item – 即使列表上的位置发生变化,也保持这个状态。

虽然性能问题可能(到某种程度上)被忽视 – 这个新问题真的阻止了我,所以我真的很感激任何帮助。

Solutions Collecting From Web of "设置从适配器检查的ListView项目"

如果使用ListView.CHOICE_MODE_MULTIPLECHOICE_MODE_SINGLEgetView被调用后,项目的检查状态将被ListView覆盖。 你必须使用下面的结构:

 @Override public View getView(int position, View convertView, ViewGroup parent) { ((ListView)parent).setItemChecked(position, true); } 

另一种可能是使用ListView.CHOICE_MODE_NONE并自行pipe理检查状态。

检查步骤首先在项目xml中使更改添加单行checkbox

 `android:onClick="chatWithFriend"` 

所以当点击cheackbox然后在活动名称中创build一个方法

  public void chatWithFriend(View view){} here you will get the view of check box, 

现在在返回转换视图之前在getView中添加行

holder.checkbox.setTag(位置);

现在你将得到checkbox的位置

我希望这能帮到您。