2011-08-26 18 views
15

Mam ListView, który wyświetla 2 rodzaje przedmiotów. Jeden z tych rodzajów zawiera CheckedTextView. Jako adapter używam niestandardowego adaptera rozszerzającego ArrayAdapter o strukturę danych zawierającego informacje o zaznaczonych/niezeznaczonych stanach wewnątrz.Ustawienie elementu ListView zaznaczone z adaptera

Niektóre pozycje są zaznaczone jako wybrane (w mojej strukturze danych), więc oczywiście chciałbym zaznaczyć pola wyboru przy tworzeniu ListView. Próbowałem zrobić to za pomocą metody getView() w adapterze za pomocą metody setChecked() CheckedTextView, ale nie działa. Znalazłem informację, że powinno to być zrobione na poziomie ListView za pomocą metody setItemChecked() i działa, ale nie ma to dla mnie sensu, ponieważ aby to działało, musiałbym zapętlić wszystkie elementy w działaniu onCreate() wywołania setItemChecked() dla wybranych. Lista przedmiotów może być bardzo długa, z wybranymi tylko kilkoma, więc jest to marnotrawstwo.

Dlaczego wywołanie metody setChecked() w funkcji getView() nie działa? Czy jest lepszy sposób to zrobić (jestem początkującym Androidem).

Poniżej znajduje się mój układ sprawdzonych elementów i adapter.

Układ:

<?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" 
/> 

Adapter:

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]; 
      } 
     }; 
} 
} 

i kawałek aktywności za onCreate()

...  
mAdapter = new MultiListAdapter(this, R.id.head, mItems); 
setListAdapter(mAdapter); 

final ListView listView = getListView(); 
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 
listView.setItemsCanFocus(false); 
... 

Edit:

Do znalezienia lepszego rozwiązania zaimplementowałem rachunek w Działaniu:

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

Pomyślałem, że występ będzie jedynym potencjalnym problemem, ale znalazłem inny - o wiele poważniejszy. Lista zawiera filtr tekstu (mListView.setTextFilterEnabled (true)). Oto scenariusz awarii:

  1. jestem otwierając nową listę
  2. Im sprawdzanie powiedzmy artykuł 2-gi
  3. zacznę pisać, aby filtrować niektóre elementy
  4. gdy filtrowanie jest zrobione, 2- nd pozycja jest nadal sprawdzana, mimo że nie jest to jeden Sprawdziłem

Zakładam, że setItemChecked() oznacza stałą pozycję na liście sprawdzane, a ja potrzebuję czegoś, co będzie oznaczać produkt dniach pozycji ths - utrzymywanie stanu nawet kiedy zmieni się pozycja na liście.

Podczas gdy problem z wydajnością może być (do pewnego stopnia) ignorowany - ten nowy problem naprawdę mnie blokuje, więc byłbym wdzięczny za jakąkolwiek pomoc.

Odpowiedz

28

Jeśli użyjesz ListView.CHOICE_MODE_MULTIPLE lub CHOICE_MODE_SINGLE, stany kontrolne pozycji zostaną nadpisane przez ListView po wywołaniu getView. Trzeba stosować następujące konstrukt:

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

Kolejna możliwo jest użycie ListView.CHOICE_MODE_NONE i zarządzać Zjednoczone Sprawdź sam.

+0

Mam do czynienia z tym samym problemem.Moje zaznaczone elementy znikają podczas przewijania listview.Spróbowałem twój kod blok wewnątrz mojego adaptera, ale nadal moje zaznaczone elementy znikają podczas przewijania listview – salih

+0

Dzięki, musiałem szukać całkiem sporo czas znaleźć rozwiązanie. –

-1

Sprawdź kroki najpierw w punkcie xml sprawiają zmiany dodać pojedynczy wiersz w polu wyboru

`android:onClick="chatWithFriend"` 

więc gdy kliknięcie cheackbox następnie utworzyć jedną metodę w imieniu działalności

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

Teraz dodaj linię w getView przed powrotem przekonwertuj widok

właściciel.checkbox .setTag (pozycja);

Teraz u dostanie pozycję pola wyboru

Mam nadzieję, że pomoże.

+0

Może nie wyjaśniłem się. Nie mam żadnego problemu z uzyskaniem pozycji przedmiotu. Wszystkie "kliknięcia" działają dobrze. To, co nie działa, powoduje, że zaznaczone elementy (ta informacja jest w danych przekazanych do adaptera) sprawdzone w nowo utworzonym widoku listy. – Izydorr

+0

może to pomóc http://about-android.blogspot.com/2010/04/steps-to-implement-expandablelistview.html –

+0

Przykro mi, ale nie widzę, jak mogłoby to być pomocne dla mnie :( – Izydorr

Powiązane problemy