J'aimerais savoir ce qui diffère de ces états. Je n'ai trouvé aucune page Web clarifiant cela.
J'aimerais savoir ce qui diffère de ces états. Je n'ai trouvé aucune page Web clarifiant cela.
Réponses:
La différence entre Vérifié et Activé est en fait assez intéressante. Même la documentation Google s'excuse (soulignement ci-dessous ajouté):
... Par exemple, dans une vue de liste avec sélection unique ou multiple activée, les vues du jeu de sélection actuel sont activées. (Euh, oui, nous sommes profondément désolés pour la terminologie ici.) L'état activé est propagé aux enfants de la vue sur laquelle il est défini.
Voici donc la différence:
ListView (après Honeycomb) appelle setChecked () OU setActivated () selon la version Android comme ci-dessous (extrait du code source 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. Il garde une trace des positions de votre liste qui sont vérifiées / activées. Ceux-ci sont accessibles via, par exemple, getCheckedItemPositions (). Notez également qu'un appel à ListView.setItemChecked () appelle ce qui précède. En d'autres termes, il pourrait également être appelé setItemActivated ().
Avant Honeycomb, nous devions implémenter des solutions de contournement pour refléter state_checked dans nos éléments de liste. Ceci est dû au fait que ListView appelle setChecked () UNIQUEMENT sur la vue la plus haute de la mise en page (et les mises en page n'implémentent pas checkable) ... et il ne se propage PAS sans aide. Ces solutions de contournement étaient de la forme suivante: Étendez la disposition racine pour implémenter Checkable. Dans son constructeur, recherchez récursivement tous les enfants qui implémentent Checkable. Lorsque setChecked () etc ... sont appelés, passez l'appel à ces vues. Si ces vues implémentent des listes d'états dessinables (par exemple une CheckBox) avec un dessin différent pour state_checked alors l'état vérifié est reflété dans l'interface utilisateur.
Pour faire un joli arrière-plan à un élément de liste après Honeycomb, tout ce que vous devez faire est d'avoir une liste d'états dessinable avec un dessinable pour l'état state_activated comme ceci (et utilisez bien sûr 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"/>
Pour créer un joli arrière-plan sur un élément de liste avant HoneyComb, vous feriez quelque chose comme ci-dessus pour state_checked et vous devez ÉGALEMENT étendre votre vue supérieure pour implémenter l'interface Checkable. Dans ce contexte, 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 à ce qui suit:
http://sriramramani.wordpress.com/2012/11/17/custom-states/
Stackoverflow: comment ajouter un état de bouton personnalisé
Stackoverflow: vue vérifiable personnalisée qui répond au 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/
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.)
source
setItemChecked()
puis utilisation d'un sélecteur avec une propriétéandroid:state_activated="true"
D'après le doc :
android: booléen state_selected . " true
" si cet élément doit être utilisé lorsque l'objet est la sélection actuelle de l'utilisateur lors de la navigation avec une commande directionnelle (comme lors de la navigation dans une liste avec un pavé directionnel); " false
" si cet élément doit être utilisé lorsque l'objet n'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 de liste a le focus et qu'un élément qu'il contient est sélectionné avec un d-pad).
android: booléen state_checked . " true
" si cet élément doit être utilisé lorsque l'objet est vérifié; " false
" s'il doit être utilisé lorsque l'objet n'est pas coché.
android: state_activated Boolean . " true
" si cet élément doit être utilisé lorsque l'objet est activé en tant que sélection persistante (par exemple pour "mettre en surbrillance" l'élément de liste précédemment sélectionné dans une vue de navigation persistante); " false
" s'il doit être utilisé lorsque l'objet n'est pas activé. Introduit au niveau d'API 11 .
Je pense que la doc est assez claire, alors quel est le problème?
Voici une autre solution à ce problème: https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/android/customizedlistview/MainActivity.java
J'ai remplacé la méthode setOnItemClickListener et vérifié les 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;
}
}
});