Me gustaría saber qué diferencia a esos estados. No encontré ninguna página web que aclare esto.
Me gustaría saber qué diferencia a esos estados. No encontré ninguna página web que aclare esto.
Respuestas:
La diferencia entre Checked y Activated es bastante interesante. Incluso la documentación de Google se disculpa (el énfasis se agrega a continuación):
... Por ejemplo, en una vista de lista con selección única o múltiple habilitada, se activan las vistas en el conjunto de selección actual. (Um, sí, lamentamos profundamente la terminología aquí.) El estado activado se propaga a los hijos de la vista en la que está establecido.
Entonces aquí está la diferencia:
ListView (después de Honeycomb) llama a setChecked () O setActivated () dependiendo de la versión de Android como se muestra a continuación (tomado del código fuente de 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));
}
}
Tenga en cuenta la variable mCheckStates. Realiza un seguimiento de las posiciones en su lista que están marcadas / activadas. Se puede acceder a ellos mediante, por ejemplo, getCheckedItemPositions (). Tenga en cuenta también que una llamada a ListView.setItemChecked () invoca lo anterior. En otras palabras, también podría llamarse setItemActivated ().
Antes de Honeycomb, tuvimos que implementar soluciones para reflejar state_checked en los elementos de nuestra lista. Esto se debe a que ListView llama a setChecked () SÓLO en la Vista superior del diseño (y los diseños no se implementan como comprobables) ... y NO se propaga sin ayuda. Estas soluciones alternativas fueron de la siguiente forma: Extienda el diseño raíz para implementar Checkable. En su constructor, busque de forma recursiva todos los elementos secundarios que implementen Checkable. Cuando se llama a setChecked () etc ..., pase la llamada a esas Vistas. Si esas vistas implementan elementos de diseño de lista de estado (por ejemplo, un CheckBox) con un elemento de diseño diferente para state_checked, el estado marcado se refleja en la interfaz de usuario.
Para hacer un fondo agradable para un elemento de la lista después de Honeycomb, todo lo que necesita hacer es tener una lista de estados dibujable con un elemento de dibujo para el estado state_activated como este (y usar setItemChecked () por supuesto):
<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"/>
Para hacer un fondo agradable para un elemento de la lista antes de HoneyComb, haría algo como lo anterior para state_checked y TAMBIÉN necesita extender su vista superior para implementar la interfaz Checkable. Dentro de eso, debe decirle a Android si el estado que está implementando es verdadero o falso al implementar onCreateDrawableState () y llamar a refreshDrawableState () siempre que el estado cambie.
<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"/>
... y el código para implementar Checkable combinado con state_checked en un RelativeLayout podría ser:
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);
}
}
Gracias a lo siguiente:
http://sriramramani.wordpress.com/2012/11/17/custom-states/
Stackoverflow: Cómo agregar un estado de botón personalizado
Stackoverflow: Vista comprobable personalizada que responde al selector
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.)
fuente
setItemChecked()
y luego usar un selector con propiedadandroid:state_activated="true"
Según el doc :
android: state_selected booleano . " true
" si este elemento debe usarse cuando el objeto es la selección actual del usuario cuando se navega con un control direccional (como cuando se navega a través de una lista con un d-pad); " false
" si este elemento se debe utilizar cuando el objeto no está seleccionado. El estado seleccionado se usa cuando el enfoque (android: state_focused) no es suficiente (como cuando la vista de lista tiene el enfoque y un elemento dentro de él se selecciona con un d-pad).
android: state_checked booleano . " true
" si este elemento debe usarse cuando el objeto está marcado; " false
" si debe usarse cuando el objeto no está marcado.
android: state_activated booleano . " true
" si este elemento debe usarse cuando el objeto está activado como la selección persistente (como para "resaltar" el elemento de la lista previamente seleccionado en una vista de navegación persistente); " false
" si se debe utilizar cuando el objeto no está activado. Introducido en API nivel 11 .
Creo que el documento es bastante claro, entonces, ¿cuál es el problema?
Aquí hay otra solución para este problema: https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/android/customizedlistview/MainActivity.java
He anulado el método setOnItemClickListener y verifico diferentes casos en el código. Pero definitivamente la solución de Marvin es mucho mejor.
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;
}
}
});