J'aimerais savoir ce qui différencie ces États. I
Réponses
Trop de publicités?La différence entre Vérifié et Activé est en fait assez intéressante. Même la documentation de Google s'en excuse (nous soulignons ci-dessous) :
... Par exemple, dans une vue de liste avec une sélection unique ou multiple activée, les vues du jeu de sélection actuel sont activées. (Hum, oui, nous sommes profondément désolés pour la terminologie utilisée ici). L'état activé est propagé aux enfants de la vue sur laquelle il est activé.
Voici donc la différence :
-
L'activation a été introduite dans Honeycomb, vous ne pouvez donc pas l'utiliser avant cela.
-
Activé est maintenant une propriété de chaque vue. Elle possède les méthodes setActivated() et isActivated().
-
Activé se propage aux enfants de la vue sur laquelle il est défini
-
Checked tourne autour d'une vue implémentant l'interface Checkable. Méthodes setChecked(), isChecked(), toggle()
-
ListView (après Honeycomb) appelle setChecked() OU setActivated() selon la version d'Android comme ci-dessous (extrait du code source d'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)); } }
Notez la variable mCheckStates. Elle garde la trace des positions de votre liste qui sont cochées/activées. Elles sont accessibles via, par exemple, getCheckedItemPositions(). Notez également qu'un appel à ListView.setItemChecked() invoque ce qui précède. En d'autres termes, on pourrait également l'appeler setItemActivated().
-
Avant Honeycomb, nous devions mettre en œuvre des solutions de contournement pour refléter state_checked dans nos éléments de liste. En effet, ListView appelle setChecked() UNIQUEMENT sur la vue la plus haute du layout (et les layouts n'implémentent pas checkable) ... et cela ne se propage PAS sans aide. Ces solutions de contournement étaient de la forme suivante : Étendre le layout Root pour implémenter Checkable. Dans son constructeur, trouver récursivement tous les enfants qui implémentent Checkable. Lorsque setChecked() etc... sont appelés, passer l'appel à ces vues. Si ces vues implémentent des drawables de liste d'état (par exemple une CheckBox) avec un drawable différent pour state_checked, alors l'état vérifié est reflété dans l'interface utilisateur.
-
Pour faire un joli arrière-plan sur un élément de liste après Honeycomb, tout ce que vous avez à faire est d'avoir une drawable pour la liste d'état avec une drawable pour l'état state_activated comme ceci (et utiliser setItemChecked() bien sûr) :
<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"/>
-
Pour faire un joli arrière-plan à un élément de liste avant HoneyComb, vous feriez quelque chose comme ce qui précède pour state_checked et vous devez AUSSI étendre votre vue la plus haute pour implémenter l'interface Checkable. À l'intérieur de celle-ci, vous devez ensuite indiquer à Android si l'état que vous implémentez est vrai ou faux en implémentant onCreateDrawableState() et en appelant refreshDrawableState() à chaque fois que l'état change.
<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"/>
... et le code pour implémenter Checkable combiné avec state_checked dans un RelativeLayout pourrait être :
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);
}
}
Merci aux personnes suivantes :
http://sriramramani.wordpress.com/2012/11/17/custom-states/
Stackoverflow : Android : comment ajouter l'état d'un bouton personnalisé
Stackoverflow : Vue vérifiable personnalisée qui répond à un sélecteur
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/
Selon le doc :
-
Android:état_sélectionné Booléen . "
true
"si cet élément doit être utilisé lorsque l'objet est la sélection courante de l'utilisateur lors de la navigation avec une commande directionnelle (par exemple, lors de la navigation dans une liste avec un d-pad) ; "false
"si cet élément doit être utilisé lorsque l'objet est pas sélectionné. L'état sélectionné est utilisé lorsque le focus (Android:state_focused) n'est pas suffisant (par exemple lorsque la vue en liste a le et qu'un élément de cette liste est sélectionné avec le d-pad). -
Android:state_checked Booléen . "
true
" si cet élément doit être utilisé lorsque l'objet est contrôlé ; "false
"si elle doit être utilisée lorsque l'objet objet n'est pas vérifié. -
Android:état_activé Booléen . "
true
"si cet élément doit être utilisé lorsque l'objet est activé en tant que sélection persistante (par ex. pour "mettre en évidence" l'élément de liste précédemment sélectionné dans une vue de de navigation persistante) ; "false
"si elle doit être utilisée lorsque l'objet n'est pas activé. activé. Introduit dans Niveau 11 de l'API .
Je pense que le docteur est assez clair, alors quel est le problème ?
Voici une autre solution pour ce problème : https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/Android/customizedlistview/MainActivity.java
J'ai surchargé la méthode setOnItemClickListener et vérifié différents cas dans le code. Mais définitivement, la solution de Marvin est bien meilleure.
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;
}
}
});