2011-08-26 48 views
15

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

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

为什么在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); 
... 

编辑的:

直到找到一个更好的解决办法,我实现支票在活动:

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

我认为性能将是唯一的潜在问题,但我发现了另一个 - 更严重。该列表启用了文本过滤器(mListView.setTextFilterEnabled(true))。这里的故障情形:

  1. 我打开新的列表
  2. 进出口检验假设2-ND项目
  3. 我开始输入来过滤一些项目
  4. 当过滤完成后,2-第二项仍然检测,即使它不是我检查

我认为setItemChecked()标志检查,而我需要的东西,将标志着上的部份位置上的项目列表上的固定位置的一个 - 保持状态甚至当列表上的位置发生变化。

尽管性能问题可能会被忽略 - 这个新问题实际上阻止了我,所以我真的很感激任何帮助。

回答

28

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

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

另一种可能是使用ListView.CHOICE_MODE_NONE和自行管理的检查状态。

+0

我面临着同样的问题,当滚动列表视图时,我的选中的项目消失了。我已经尝试过你的代码块,但是当滚动列表视图时,我的选中项目正在消失 – salih

+0

谢谢,我不得不寻找一些有时间找到解决方案。 –

-1

退房步骤 第一项XML进行更改 复选框添加一行

`android:onClick="chatWithFriend"` 

所以当上cheackbox 点击然后创建活动名称的一个方法

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

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

holder.checkbox .setTag(位置);

现在你将获得复选框的位置

我希望这会对你有帮助。

+0

也许我没有说清楚。我对获得该物品的位置没有任何问题。所有“点击”操作都可以正常工作。不工作的是将所选项目(这些信息在传递给适配器的数据中)在新创建的列表视图中进行检查。 – Izydorr

+0

这可能有助于http://about-android.blogspot.com/2010/04/steps-to-implement-expandablelistview.html –

+0

对不起,但我不明白这可能对我有帮助:( – Izydorr

相关问题