2011-08-26 47 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

相關問題