web-dev-qa-db-fra.com

Quelle est la différence entre les états sélectionnés, cochés et activés dans Android?

Je voudrais savoir ce qui diffère de ces états. Je n'ai trouvé aucune page Web clarifiant cela.

97
Louis

La différence entre Checked et Activated est en fait assez intéressante. Même la documentation de Google est désolée (soulignement ajouté ci-dessous): 

... Par exemple, dans une vue liste avec une ou plusieurs sélections activé, les vues du jeu de sélection actuel sont activées. (Euh, Oui, nous sommes profondément désolés de la terminologie utilisée ici.) The activé l'état est propagé aux enfants de la vue sur laquelle il est activé.

Alors voici la différence:

  1. Activé a été introduit dans Honeycomb, vous ne pouvez donc pas l'utiliser avant.
  2. Activé est maintenant une propriété de chaque vue. Il a des méthodes setActivated () et isActivated ()
  3. Activé se propage aux enfants de la vue sur laquelle il est défini
  4. Checked s'articule autour d'une vue mettant en œuvre l'interface Checkable. Méthodes setChecked (), isChecked (), toggle ()
  5. ListView (après Honeycomb) appelle setChecked () OR setActivated () selon la version Android 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 la trace des positions de votre liste qui sont coché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 ().

  6. Avant Honeycomb, nous devions implémenter 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 de la présentation (et les dispositions ne mettent pas en oeuvre Checkable) ... et ne se propagent PAS sans aide. Ces solutions de contournement étaient de la forme suivante: Étendre la mise en page racine pour implémenter Checkable. Dans son constructeur, trouve récursivement tous les enfants qui implémentent Checkable. Lorsque setChecked () etc ... sont appelés, transmettez l'appel à ces vues. Si ces vues implémentent des listes pouvant être dessinées (par exemple, une CheckBox) avec un dessin différent pour state_checked, l'état coché est reflété dans l'interface utilisateur.

  7. Pour créer un arrière-plan sympa pour un élément de la liste après Honeycomb, il vous suffit d'avoir une liste d'états pouvant être dessinée avec un dessin pour l'état activé par l'état (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"/>
    

  8. Pour créer un arrière-plan sympa pour un élément de la liste avant HoneyComb, effectuez une opération similaire à celle décrite ci-dessus pour state_checked et vous devez ÉGALEMENT étendre votre vue la plus haute pour implémenter l'interface Checkable. Dans ce cas, 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 changement d'état.

    <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 à implémenter Checkable associé à state_checked dans un RelativeLayout pourraient ê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/

169
Martin Harvey

Selon le doc :

  • Android: state_selected _ ​​Boolean. "true" si cet élément doit être utilisé lorsque l'objet est la sélection actuelle de l'utilisateur lors de la navigation avec un contrôle directionnel (par exemple, lors de la navigation dans une liste avec un pavé directionnel); "false" si cet élément doit être utilisé lorsque l'objet est non sélectionné. L'état sélectionné est utilisé lorsque focus .__ (Android: state_focused) n'est pas suffisant (par exemple, lorsque la vue liste a Focus et qu'un élément de celle-ci est sélectionné avec un pavé tactile).

  • Android: state_checked _ ​​Boolean. "true" si cet élément doit être utilisé lors de la vérification de l'objet; "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, __.as 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 dans API niveau 11.

Je pense que le doc est assez clair, alors quel est le problème?

18
AMerle

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;
    }
    }
});
0
jiahao