Chciałbym wiedzieć, co różni te stany. Nie znalazłem żadnej strony, która wyjaśniałaby to.
Chciałbym wiedzieć, co różni te stany. Nie znalazłem żadnej strony, która wyjaśniałaby to.
Odpowiedzi:
Różnica między Checked i Activated jest w rzeczywistości dość interesująca. Nawet dokumentacja Google jest przepraszająca (podkreślenie poniżej dodane):
... Na przykład w widoku listy z włączonym pojedynczym lub wielokrotnym wyborem widoki w bieżącym zbiorze wskazań są aktywowane. (Hm, tak, bardzo nam przykro z powodu tej terminologii.) Stan aktywacji jest propagowany do dzieci widoku, na którym jest ustawiony.
Oto różnica:
ListView (po Honeycomb) wywołuje setChecked () LUB setActivated () w zależności od wersji Androida, jak poniżej (pobrane z kodu źródłowego Androida):
if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
if (child instanceof Checkable) {
((Checkable) child).setChecked(mCheckStates.get(position));
} else if (getContext().getApplicationInfo().targetSdkVersion
>= android.os.Build.VERSION_CODES.HONEYCOMB) {
child.setActivated(mCheckStates.get(position));
}
}
Zwróć uwagę na zmienną mCheckStates. Śledzi, które pozycje na Twojej liście są zaznaczone / aktywowane. Są one dostępne na przykład poprzez getCheckedItemPositions (). Należy również zauważyć, że wywołanie ListView.setItemChecked () wywołuje powyższe. Innymi słowy, można go również nazwać setItemActivated ().
Przed wprowadzeniem Honeycomb musieliśmy wdrożyć obejścia, aby odzwierciedlić state_checked na naszej liście. Dzieje się tak, ponieważ ListView wywołuje setChecked () TYLKO na najwyższym widoku w układzie (a układy nie implementują możliwości sprawdzania) ... i NIE propaguje się bez pomocy. Te obejścia miały następującą postać: Rozszerz układ główny, aby zaimplementować opcję Checkable. W swoim konstruktorze, rekurencyjnie znajdź wszystkie elementy potomne, które implementują Checkable. Gdy wywoływana jest metoda setChecked () etc ..., przekaż wywołanie do tych widoków. Jeśli te widoki implementują elementy rysunkowe z listy stanów (np. CheckBox) z innym drawable dla state_checked, wówczas stan zaznaczenia jest odzwierciedlany w interfejsie użytkownika.
Aby stworzyć ładne tło dla elementu listy po Honeycomb, wszystko, co musisz zrobić, to mieć listę stanów z możliwością rysowania dla stanu state_activated w ten sposób (i oczywiście użyj setItemChecked ()):
<item android:state_pressed="true"
android:drawable="@drawable/list_item_bg_pressed"/>
<item android:state_activated="true"
android:drawable="@drawable/list_item_bg_activated"/>
<item android:drawable="@drawable/list_item_bg_normal"/>
Aby zrobić ładne tło dla elementu listy przed HoneyComb, zrobiłbyś coś takiego jak powyżej dla state_checked i musisz RÓWNIEŻ rozszerzyć swój najwyższy widok, aby zaimplementować interfejs Checkable. W ramach tego musisz następnie powiedzieć systemowi Android, czy implementowany stan jest prawdziwy, czy fałszywy, implementując onCreateDrawableState () i wywołując refreshDrawableState () za każdym razem, gdy stan się zmienia.
<item android:state_pressed="true"
android:drawable="@drawable/list_item_bg_pressed"/>
<item android:state_checked="true"
android:drawable="@drawable/list_item_bg_checked"/>
<item android:drawable="@drawable/list_item_bg_normal"/>
... a kod do implementacji Checkable w połączeniu z state_checked w RelativeLayout mógłby wyglądać następująco:
public class RelativeLayoutCheckable extends RelativeLayout implements Checkable {
public RelativeLayoutCheckable(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RelativeLayoutCheckable(Context context) {
super(context);
}
private boolean mChecked = false;
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
@Override
public boolean isChecked() {
return mChecked;
}
@Override
public void setChecked(boolean checked) {
mChecked = checked;
refreshDrawableState();
}
private static final int[] mCheckedStateSet = {
android.R.attr.state_checked,
};
@Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, mCheckedStateSet);
}
return drawableState;
}
@Override
public void toggle() {
setChecked(!mChecked);
}
}
Podziękowania dla:
http://sriramramani.wordpress.com/2012/11/17/custom-states/
Stackoverflow: jak dodać stan przycisku niestandardowego
Stackoverflow : niestandardowy widok z możliwością zaznaczania, który reaguje na selektor
http://www.charlesharley.com/2012/programming/custom-drawable-states-in-android/
http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList
http://blog.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/
Selection is a transient property, representing the view (hierarchy) the user is currently interacting with. Activation is a longer-term state that the user can move views in and out of. For example, in a list view with single or multiple selection enabled, the views in the current selection set are activated. (Um, yeah, we are deeply sorry about the terminology here.)
setItemChecked()
a następnie użycie selektora z właściwościąandroid:state_activated="true"
Według doc :
android: state_selected Boolean . " true
" jeśli ta pozycja ma być używana, gdy obiekt jest aktualnie wybranym przez użytkownika podczas nawigacji za pomocą kontrolki kierunkowej (na przykład podczas nawigacji po liście za pomocą pada kierunkowego); „ false
”, jeśli ten element ma być używany, gdy obiekt nie jest wybrany. Wybrany stan jest używany, gdy fokus (android: state_focused) nie jest wystarczający (na przykład gdy widok listy ma fokus, a element w nim jest zaznaczony za pomocą pada kierunkowego).
android: state_checked Boolean . " true
" jeśli ta pozycja ma być używana, gdy obiekt jest zaznaczony; „ false
” jeśli ma być używane, gdy obiekt jest odznaczony.
android: state_activated Boolean . " true
" jeśli ta pozycja ma być używana, gdy obiekt jest aktywowany jako trwały wybór (np. w celu "podświetlenia" poprzednio wybranej pozycji listy w stałym widoku nawigacji); " false
" jeśli ma być używany, gdy obiekt nie jest aktywowany. Wprowadzono na poziomie API 11 .
Myślę, że dokument jest całkiem jasny, więc w czym problem?
Oto inne rozwiązanie tego problemu: https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/android/customizedlistview/MainActivity.java
Zastąpiłem metodę setOnItemClickListener i sprawdziłem różne przypadki w kodzie. Ale ostatecznie rozwiązanie Marvina jest znacznie lepsze.
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position,
long id) {
CheckedTextView checkedTextView =
(CheckedTextView)view.findViewById(R.id.checkedTextView);
// Save the actual selected row data
boolean checked = checkedTextView.isChecked();
int choiceMode = listView.getChoiceMode();
switch (choiceMode) {
// Not choosing anything
case (ListView.CHOICE_MODE_NONE):
// Clear all selected data
clearSelection();
//printCheckedElements();
break;
// Single choice
case (ListView.CHOICE_MODE_SINGLE):
// Clear all the selected data
// Revert the actual row data
clearSelection();
toggle(checked, checkedTextView, position);
//printCheckedElements();
break;
// Multiple choice
case (ListView.CHOICE_MODE_MULTIPLE):
case (ListView.CHOICE_MODE_MULTIPLE_MODAL):
// Revert the actual selected row data
toggle(checked, checkedTextView, position);
//printCheckedElements();
break;
}
}
});