2010-04-16 14 views
34

Widziałem przykład: com.example.android.apis.view.List11 z ApiDemos. W tym przykładzie każdy wiersz przyjmuje widok android.R.simple_list_item_multiple_choice. Każdy taki widok ma TextView i CheckBox.Lista wielokrotnego wyboru z widokiem niestandardowym?

Teraz chcę każdy widok mieć 2 TextView s i 1 CheckBox, nieco podobny do lista3 przykład. Próbowałem tworząc układ niestandardowy plik row.xml takiego:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
    <CheckBox 
     android:id="@+id/checkbox" 
     android:layout_alignParentRight="true" 
     android:layout_width="wrap_content" 
     android:layout_height="fill_parent" /> 
    <TextView 
     android:id="@+id/text_name" 
     android:textSize="13px" 
     android:textStyle="bold" 
     android:layout_toLeftOf="@id/checkbox" 
     android:layout_alignParentLeft="true" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" /> 
    <TextView 
     android:id="@+id/text_phone" 
     android:textSize="9px" 
     android:layout_toLeftOf="@id/checkbox" 
     android:layout_below="@id/text_name" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" /> 
</RelativeLayout> 

potem w Activity „s onCreate(), robię tak:

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // Query the contacts 
    mCursor = getContentResolver().query(Phones.CONTENT_URI, null, null, null, null); 
    startManagingCursor(mCursor); 

    ListAdapter adapter = new SimpleCursorAdapter(this, 
      R.layout.row, 
      mCursor, 
      new String[] { Phones.NAME, Phones.NUMBER}, 
      new int[] { R.id.text_name, R.id.text_phone }); 
    setListAdapter(adapter); 
    getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 
} 

Wynik niby wygląda to, co chcę, ale wygląda na to, że lista nie wie, który element jest wybrany. Ponadto muszę dokładnie kliknąć na CheckBox. W przykładzie List11 wystarczy kliknąć wiersz pozycji.

Co muszę zrobić, aby utworzyć listę wielokrotnego wyboru z moim widokiem niestandardowym dla każdego wiersza? Wielkie dzięki.

+0

Czy znalazłeś odpowiedź na to pytanie? może przykład? Mam to samo pytanie :) http://stackoverflow.com/questions/3858501/multiple-choice-list-without-checkboxes-on-a-custom-view –

+1

Więc czy było jakieś rozwiązanie? Utknąłem na tym samym problemie. – Pritam

Odpowiedz

5

Każdy taki widok ma pole wyboru TextView i CheckBox.

Nie, nie ma. Ma CheckedTextView.

Więc co muszę zrobić, aby dokonać wielokrotnego wyboru z listy niestandardowej moim zdaniem dla każdego wiersza?

spróbuj wartość CheckBoxandroid:id być "@android:id/text1" i zobacz, czy to pomaga. To jest identyfikator używany przez Androida dla CheckedTextView w simple_list_item_multiple_choice.

+1

Dzięki CommonsWare. Próbowałem tego i to nie działało dla mnie. Przy okazji, gdzie mam szukać implementacji android.R.simple_list_item_multiple_choice? Nie mogę znaleźć pliku xml o tej nazwie w ApiDemos. – Phil

+2

Nie ma go w ApiDemos, jest w SDK. Wszystkie zasoby SDK znajdują się w '$ ANDROID_SDK/platforms/$ VERSION/data/res', gdzie' $ ANDROID_SDK' jest wszędzie tam, gdzie zainstalowałeś SDK, a '$ VERSION' to tylko wersja Androida (np.' Android-2.1') . – CommonsWare

+1

Dzięki. Sprawdziłem zawartość simple_list_item_multiple_choice. To, co odkryłem, działa, jeśli widok dla każdego wiersza jest po prostu . Kiedy zawinę go w Układ, rzeczy nie będą już działać. Nie wiem, jak zapakować w jeszcze jeden widok, aby wyświetlić inny fragment tekstu. – Phil

1

Jest to możliwe przez jakiś podstęp

w swoim ListActivtyClass w metodzie

protected void onListItemClick(ListView l, View v, int position, long id) { 
//just set 
<your_model>.setSelected(true); 
} 

teraz w was zwyczaj Adapter

public View getView(int position, View convertView, ViewGroup parent) { 
     if (convertView == null) { 
      LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      convertView = inflater.inflate(textViewResourceId, parent, false); 
     }  
     if (<your_model>.isSelected()) { 
      convertView.setBackgroundColor(Color.BLUE); 
     } else { 
      convertView.setBackgroundColor(Color.BLACK); 
     } 
     return convertView; 
    } 

ten sposób można dostosować widok w adapterze, gdy pozycja jest zaznaczone na liście.

0

Masz rozwiązanie ... Możesz uzyskać kliknięcia na widokach (jak pola wyboru w niestandardowych układach wierszy), dodając detektor do każdego z nich w samym adapterze, podczas gdy zwrócisz przekonwertowany widok w getView(). Możliwe, że będziesz musiał przekazać referencję obiektu listy, jeśli masz zamiar uzyskać informacje o konkretnej liście. jak id rzędu.

7

Odpowiedź Rahul Garg jest dobra po raz pierwszy lista jest ładowana, jeśli chcesz, aby niektóre wiersze były sprawdzane w zależności od danych modelu, ale po tym musisz obsługiwać zaznacz/odznacz zdarzenia samemu.

można zastąpić onListItemCLick() z ListActivity aby zaznaczyć/odznaczyć wiersze

@Override 
protected void onListItemClick(ListView l, View v, int position, long id) { 
    super.onListItemClick(l, v, position, id); 
    ViewGroup row = (ViewGroup)v; 
CheckBox check = (CheckBox) row.findViewById(R.id.checkbox);    
    check.toggle(); 
} 

Jeśli to zrobisz, nie ustawić ListView do CHOICE_MODE_MULTIPLE, ponieważ sprawia, że ​​dziwne rzeczy podczas wywoływania funkcji.

Aby pobrać listę sprawdzanych wierszy, trzeba zaimplementować metody siebie, nazywając getCheckItemIds() na ListView nie działa:

ListView l = getListView(); 
int count = l.getCount(); 
for(int i=0; i<count; ++i) { 
    ViewGroup row = (ViewGroup)l.getChildAt(i); 
    CheckBox check = (Checked) row.findViewById(R.id.ck1); 
    if(check.isChecked()) { 
     // do something 
    } 
} 
+0

Dzięki @JVitela :) Działa dla mnie –

0

Chcę potwierdzić, że odpowiedź Pritam jest prawidłowa. Potrzebujesz pozycji onClickListener na każdym elemencie listy (zdefiniuj go w adapterze getView()).

Można utworzyć nowy onClickListener() dla każdej pozycji lub adapter implementować onClickListener() - w tym przypadku elementy muszą być oznaczone, aby słuchacz wiedział, na którym elemencie pracuje.

Poleganie na liście onItemClickListener() - jak ktoś doradził w innym wątku - nie zadziała, ponieważ CheckBox przechwyci zdarzenie click, więc lista go nie otrzyma.

I wreszcie @Rahul i JVitella:

Sytuacja jest taka, że ​​CheckBox na elemencie listy musi być klikalny i dostępne do kontroli niezależnie od samego elementu listy. Dlatego rozwiązanie jest takie, jak właśnie opisano powyżej.

17

Musisz zrobić własną RelativeLayout, która implementuje interfejs Checkable i mają odniesienie do CheckBox lub do CheckedTextView (lub listę, czy to w trybie wielokrotnego wyboru).

Spójrz na ten post: http://www.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/

+1

Rozwiązania związane z zamieszczonymi linkami występują również, gdy użytkownik bezpośrednio kliknął pole wyboru. – Rainbowbreeze

+3

Samouczek jest dobry, ale brakuje mu ważnej części: w jaki sposób można obsługiwać kliknięcia elementów listy w działaniu, które zawiera ListView, aby na przykład wyświetlać pasek działań kontekstowych? – Konsumierer

+0

@ ferdy182 Post, do którego się odwołujesz, nie jest już dostępny. Czy możesz podać kopię artykułu (lub przynajmniej kod)? Dzięki –

1

Prosty przykład jak dostać niestandardowy układ do pracy w charakterze niestandardowym wyboru:

private class FriendsAdapter extends ArrayAdapter<WordsterUser> { 
    private Context context; 

    public FriendsAdapter(Context context) { 
     super(context, R.layout.listitem_oneline); 

     this.context = context; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     final int pos = position; 

     LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

     View rv = inflater.inflate(R.layout.listitem_oneline, parent, false); 
     rv.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       boolean checked = friendsListView.isItemChecked(pos); 
       friendsListView.setItemChecked(pos, !checked); 
      } 
     }); 

     WordsterUser u = getItem(position); 

     TextView itw = (TextView) rv.findViewById(R.id.ItemTextView); 
     itw.setText(u.userName + " (" + u.loginName + ")"); 

     ImageView iv = (ImageView) rv.findViewById(R.id.SelectButton); 

     if (friendsListView.isItemChecked(position)) { 
      iv.setImageResource(R.drawable.downbutton); 
     } else { 
      iv.setImageResource(R.drawable.upbutton); 
     } 

     return rv; 
    } 
} 
+0

W twoim przykładzie, jak instancja 'FriendsAdapter' wie, do czego odwołuje się' friendListView'? –

5

Rozwiązaniem jest stworzenie własnego poglądu, że implementuje interfejs klikalne.

public class OneLineCheckableListItem extends LinearLayout implements Checkable { 

    public OneLineCheckableListItem(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    private boolean checked; 


    @Override 
    public boolean isChecked() { 
     return checked; 
    } 

    @Override 
    public void setChecked(boolean checked) { 
     this.checked = checked; 

     ImageView iv = (ImageView) findViewById(R.id.SelectImageView); 
     iv.setImageResource(checked ? R.drawable.button_up : R.drawable.button_down); 
    } 

    @Override 
    public void toggle() { 
     this.checked = !this.checked; 
    } 
} 

Utwórz niestandardowy układ elementów listy za pomocą nowego widżetu.

<?xml version="1.0" encoding="utf-8"?> 
<ax.wordster.OneLineCheckableListItem xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:layout_marginBottom="4dp" 
    android:background="@drawable/selector_listitem" 
    android:orientation="horizontal" > 

    <ImageView 
     android:id="@+id/SelectImageView" 
     android:layout_width="60dp" 
     android:layout_height="60dp" 
     android:src="@drawable/button_friends_down" /> 

    <TextView 
     android:id="@+id/ItemTextView" 
     android:layout_width="fill_parent" 
     android:layout_height="60dp" 
     android:gravity="center" 
     android:text="@string/___" 
     android:textAppearance="?android:attr/textAppearanceLarge" 
     android:textColor="@color/text_item" /> 

</ax.wordster.OneLineCheckableListItem> 

Następnie utwórz nowy niestandardowy adapter, korzystając z powyższego układu.

+0

Czy możesz mi pomóc: jak dokonać wyboru wielokrotnego nie po kliknięciu elementu, ale w widoku ImageView w itemView iw onItemClick mogę wykonać inne działanie? – DavyJonesUA

+1

proste i poprawne rozwiązania .. – Ann

+0

mój stan jest dziwny, setChecked nie jest w ogóle wywoływany, ale AbsListView.MultiChoiceModeListener # onItemCheckedStateChanged nazywa się – HendraWD

1
+0

Alvin Alexander's CheckableRelativeLayout sprawia, że ​​widok najwyższego poziomu sprawdza się w rzędzie, w tym właściwy losowy stan android.R .attr.state_checked. Rysunki dzieci, takie jak Checkbox, mogą korzystać z tego stanu, jeśli przekażesz im stan. Musisz zastosować android: duplicateParentState = "true" do każdego dziecka z CheckableRelativeLayout, w tym Checkbox. – dschulten

Powiązane problemy