Mi piacerebbe sapere cosa differenzia questi stati. Non ho trovato nessuna pagina web che lo chiarisca.
Mi piacerebbe sapere cosa differenzia questi stati. Non ho trovato nessuna pagina web che lo chiarisca.
Risposte:
La differenza tra Checked e Activated è in realtà piuttosto interessante. Anche la documentazione di Google si scusa (enfasi sotto aggiunta):
... Ad esempio, in una visualizzazione elenco con selezione singola o multipla abilitata, vengono attivate le visualizzazioni nel gruppo di selezione corrente. (Ehm, sì, siamo profondamente dispiaciuti per la terminologia qui.) Lo stato attivato viene propagato ai figli della vista su cui è impostato.
Quindi ecco la differenza:
ListView (dopo Honeycomb) chiama setChecked () OR setActivated () a seconda della versione di Android come di seguito (preso dal codice sorgente di Android):
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));
}
}
Notare la variabile mCheckStates. Tiene traccia di quali posizioni nell'elenco sono controllate / attivate. Questi sono accessibili tramite, ad esempio, getCheckedItemPositions (). Notare anche che una chiamata a ListView.setItemChecked () richiama quanto sopra. In altre parole, potrebbe essere ugualmente chiamato setItemActivated ().
Prima di Honeycomb dovevamo implementare soluzioni alternative per riflettere state_checked nelle voci dell'elenco. Questo perché ListView chiama setChecked () SOLO sulla vista più in alto nel layout (ei layout non implementano il checkable) ... e NON si propaga senza aiuto. Queste soluzioni alternative erano del seguente formato: Estendere il layout principale per implementare Checkable. Nel suo costruttore, trova ricorsivamente tutti i figli che implementano Checkable. Quando vengono chiamati setChecked () ecc ..., passare la chiamata a quelle viste. Se queste viste implementano i drawable dell'elenco di stato (ad esempio un CheckBox) con un drawable diverso per state_checked, lo stato selezionato si riflette nell'interfaccia utente.
Per fare uno sfondo piacevole a una voce di elenco dopo Honeycomb, tutto ciò che devi fare è avere un elenco di stati disegnabile con un disegnabile per lo stato state_activated in questo modo (e usa setItemChecked () ovviamente):
<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"/>
Per fare uno sfondo piacevole a un elemento dell'elenco prima di HoneyComb, dovresti fare qualcosa di simile a quanto sopra per state_checked e devi INOLTRE estendere la tua vista superiore per implementare l'interfaccia Checkable. All'interno di ciò devi quindi dire ad Android se lo stato che stai implementando è vero o falso implementando onCreateDrawableState () e chiamando refreshDrawableState () ogni volta che lo stato cambia.
<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"/>
... e il codice per implementare Checkable combinato con state_checked in un RelativeLayout potrebbe essere:
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);
}
}
Grazie a quanto segue:
http://sriramramani.wordpress.com/2012/11/17/custom-states/
Stackoverflow: come aggiungere uno stato del pulsante personalizzato
Stackoverflow: visualizzazione controllabile personalizzata che risponde al selettore
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.)
fonte
setItemChecked()
e quindi utilizzando un selettore con proprietàandroid:state_activated="true"
Secondo il doc :
android: state_selected Boolean . " true
" se questo elemento deve essere utilizzato quando l'oggetto è la selezione corrente dell'utente durante la navigazione con un controllo direzionale (come quando si naviga in un elenco con un tasto direzionale); " false
" se questo elemento deve essere utilizzato quando l'oggetto non è selezionato. Lo stato selezionato viene utilizzato quando lo stato attivo (android: state_focused) non è sufficiente (ad esempio quando la visualizzazione elenco ha lo stato attivo e un elemento al suo interno viene selezionato con una croce direzionale).
android: state_checked Boolean . " true
" se questo elemento deve essere utilizzato quando l'oggetto viene controllato; " false
" se deve essere utilizzato quando l'oggetto è deselezionato.
android: state_activated Boolean . " true
" se questo elemento deve essere utilizzato quando l'oggetto è attivato come selezione persistente (come per "evidenziare" l'elemento dell'elenco precedentemente selezionato in una vista di navigazione persistente); " false
" se deve essere utilizzato quando l'oggetto non è attivato. Introdotto nel livello API 11 .
Penso che il documento sia abbastanza chiaro, quindi qual è il problema?
Ecco un'altra soluzione per questo problema: https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/android/customizedlistview/MainActivity.java
Ho sovrascritto il metodo setOnItemClickListener e controllato diversi casi nel codice. Ma in definitiva la soluzione di Marvin è decisamente migliore.
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;
}
}
});