Was ist der Unterschied zwischen den in Android ausgewählten, überprüften und aktivierten Status?

114

Ich würde gerne wissen, was diese Zustände unterscheidet. Ich habe keine Webseite gefunden, die dies klarstellt.

Louis
quelle
4
Die Zustände einer Ansicht (zum Beispiel eines ListView-Elements) developer.android.com/guide/topics/resources/…
Louis
stackoverflow.com/questions/13634259/… ist eine ähnliche Frage, die mir geholfen hat, dies besser zu verstehen. Probieren Sie es aus, wenn Sie mehr erfahren möchten.
Acsor

Antworten:

182

Der Unterschied zwischen Aktiviert und Aktiviert ist eigentlich sehr interessant. Sogar die Google-Dokumentation ist entschuldigend (Hervorhebung unten hinzugefügt):

... In einer Listenansicht mit aktivierter Einzel- oder Mehrfachauswahl werden beispielsweise die Ansichten im aktuellen Auswahlsatz aktiviert. (Ähm, ja, die Terminologie hier tut uns sehr leid.) Der aktivierte Status wird an Kinder der Ansicht weitergegeben, auf die er eingestellt ist.

Hier ist also der Unterschied:

  1. Activated wurde in Honeycomb eingeführt, sodass Sie es vorher nicht verwenden können
  2. Aktiviert ist jetzt eine Eigenschaft jeder Ansicht. Es hat Methoden setActivated () und isActivated ()
  3. Aktiviert wird an untergeordnete Elemente der Ansicht weitergegeben, für die es festgelegt ist
  4. Checked dreht sich um eine Ansicht, die die Checkable-Schnittstelle implementiert. Methoden setChecked (), isChecked (), toggle ()
  5. ListView (nach Honeycomb) ruft setChecked () ODER setActivated () auf, abhängig von der folgenden Android-Version (aus dem Android-Quellcode):

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

    Beachten Sie die Variable mCheckStates. Es verfolgt, welche Positionen in Ihrer Liste aktiviert / aktiviert sind. Auf diese kann beispielsweise über getCheckedItemPositions () zugegriffen werden. Beachten Sie auch, dass ein Aufruf von ListView.setItemChecked () das Obige aufruft. Mit anderen Worten könnte es auch setItemActivated () heißen.

  6. Vor Honeycomb mussten wir Problemumgehungen implementieren, um state_checked in unseren Listenelementen wiederzugeben. Dies liegt daran, dass ListView setChecked () NUR in der obersten Ansicht des Layouts aufruft (und Layouts nicht überprüfbar implementieren) ... und sich NICHT ohne Hilfe verbreitet. Diese Problemumgehungen hatten die folgende Form: Erweitern Sie das Root-Layout, um Checkable zu implementieren. Suchen Sie in seinem Konstruktor rekursiv alle untergeordneten Elemente, die Checkable implementieren. Wenn setChecked () etc ... aufgerufen wird, leiten Sie den Aufruf an diese Ansichten weiter. Wenn diese Ansichten Statuslisten-Drawables (z. B. ein Kontrollkästchen) mit einem anderen Drawable für state_checked implementieren, wird der überprüfte Status in der Benutzeroberfläche angezeigt.

  7. Um einen schönen Hintergrund für ein Listenelement nach Honeycomb zu erstellen, müssen Sie lediglich eine Statusliste mit einer Zeichnungsliste für den Status state_activated wie folgt erstellen (und natürlich setItemChecked () verwenden):

    <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. Um einen schönen Hintergrund für ein Listenelement vor HoneyComb zu erstellen, müssen Sie für state_checked Folgendes tun, und Sie müssen AUCH Ihre oberste Ansicht erweitern, um die Checkable-Schnittstelle zu implementieren. Innerhalb dessen müssen Sie Android dann mitteilen, ob der von Ihnen implementierte Status wahr oder falsch ist, indem Sie onCreateDrawableState () implementieren und refreshDrawableState () aufrufen, wenn sich der Status ändert.

    <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"/>

... und der Code zum Implementieren von Checkable in Kombination mit state_checked in einem RelativeLayout könnte sein:

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

Vielen Dank an:

http://sriramramani.wordpress.com/2012/11/17/custom-states/

Stackoverflow: So fügen Sie einen benutzerdefinierten Schaltflächenstatus hinzu

Stackoverflow: Benutzerdefinierte überprüfbare Ansicht, die auf Selector reagiert

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/

Martin Harvey
quelle
4
Diese Antwort ist von unschätzbarem Wert. Ich wünschte, ich würde es lesen, bevor ich herausfinden würde, wie ein überprüfbares Layout usw. implementiert werden kann. Vielen Dank.
Blake Mumford
12
Gute Antwort, spricht aber nicht "ausgewählte" Elemente an. Ich fand die Antwort in den Sätzen RECHTS VOR dem, den Sie zitiert haben: 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
woojoo666
Meine benutzerdefinierte Hintergrundfarbe wird nur hinter ausgewählten / fokussierten Elementen angezeigt, nicht hinter setItemChecked()android:state_activated="true"
aktivierten
1
Vielen Dank, ich habe 3 Tage damit verbracht, dies herauszufinden, bis ich mich schließlich entschied, mich zu fragen: "Was ist der Unterschied zwischen aktiviert, ausgewählt und aktiviert?". Es ist scheiße, dass der Umgang mit etwas so Einfachem wie einem Menü so kompliziert und überentwickelt sein muss Von den Genies von Google scheint es fast ein Hindernis zu sein, das dieses Unternehmen absichtlich gesetzt hat, um andere zu bremsen.
Gubatron
20

Laut dem Dokument :

  • android: state_selected Boolean . " true" wenn dieses Element verwendet werden soll, wenn das Objekt die aktuelle Benutzerauswahl ist, wenn Sie mit einem Richtungssteuerelement navigieren (z. B. wenn Sie mit einem Steuerkreuz durch eine Liste navigieren); " false" wenn dieses Element verwendet werden soll, wenn das Objekt nicht ausgewählt ist. Der ausgewählte Status wird verwendet, wenn der Fokus (android: state_focused) nicht ausreicht (z. B. wenn die Listenansicht den Fokus hat und ein Element darin mit einem Steuerkreuz ausgewählt wird).

  • android: state_checked Boolean . " true" wenn dieses Element verwendet werden soll, wenn das Objekt überprüft wird; " false" wenn es verwendet werden soll, wenn das Objekt deaktiviert ist.

  • android: state_activated Boolean . " true" wenn dieses Element verwendet werden soll, wenn das Objekt als dauerhafte Auswahl aktiviert ist (z. B. um das zuvor ausgewählte Listenelement in einer dauerhaften Navigationsansicht "hervorzuheben"); " false" wenn es verwendet werden soll, wenn das Objekt nicht aktiviert ist. Eingeführt in API Level 11 .

Ich denke, das Dokument ist ziemlich klar. Wo liegt also das Problem?

AMerle
quelle
5
Können Sie auf Android näher eingehen: state_selected. Unter welchen Umständen wird es auf true gesetzt?
Anderson
@Anderson hängt von der von Ihnen verwendeten ViewGroup ab - ListView, RecyclerView (wahrscheinlich die LayoutManager), GridView hat möglicherweise unterschiedliche Implementierungen: ListView-Aufrufe setFocused, wobei GridView beispielsweise setSelected aufruft. Möglicherweise müssen Sie Ihre App nur auf verschiedenen Plattformversionen überprüfen.
Ataulm
1
@Anderson: Wenn Sie eine Liste haben und der Benutzer Pfeiltasten hat, ist eine "ausgewählt", und wenn sie nach oben / unten pfeilen, bewegt sich die Auswahl nach oben / unten. Wenn sie die Taste "Aktivieren" drücken, wird das Steuerelement "aktiviert", die Auswahl wird als vage dem Mouseover ähnlich angesehen, und das Aktivieren / Aktivieren wird als vage dem Klicken ähnlich angesehen.
Mooing Duck
Ich habe mich gefragt, ob ich aktiviert verwenden werde, um ein Element in einer Listenansicht hervorzuheben, aber setzt es die Aktivierung für andere Listenelemente auf falsch ... wenn nicht, tun Sie dies, damit ich es nicht finden muss das andere aktivierte untergeordnete Element und setzen Sie die Aktivierung auf false?
Lion789
0

Hier ist eine andere Lösung für dieses Problem: https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/android/customizedlistview/MainActivity.java

Ich habe die Methode setOnItemClickListener überschrieben und verschiedene Fälle im Code überprüft. Aber definitiv ist die Lösung von Marvin viel besser.

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