126

I'd like to know what differs those states. I didn't find any webpage clarifying this.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Louis
  • 2,140
  • 4
  • 19
  • 18
  • 4
    The states of a view (for example a ListView item) http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList – Louis Jul 16 '12 at 13:03
  • http://stackoverflow.com/questions/13634259/explanation-of-state-activated-state-selected-state-pressed-state-focused-for is a similar question which helped me better understanding this. Check it out if you want to learn more. – Acsor Apr 21 '14 at 16:58

3 Answers3

191

The difference between Checked and Activated is actually quite interesting. Even the Google documentation is apologetic (emphasis below added):

... 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.) The activated state is propagated down to children of the view it is set on.

So here is the difference:

  1. Activated was introduced in Honeycomb so you can't use it before that
  2. Activated is now a property of every View. It has methods setActivated() and isActivated()
  3. Activated propagates to children of the View on which it is set
  4. Checked revolves around a View implementing the Checkable interface. Methods setChecked(), isChecked(), toggle()
  5. ListView (after Honeycomb) calls setChecked() OR setActivated() depending on Android version as below (taken from Android source code):

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

    Note the mCheckStates variable. It keeps track of which positions in your list are checked / activated. These are accessible via, for example, getCheckedItemPositions(). Note also that a call to ListView.setItemChecked() invokes the above. In other words, it could equally be called setItemActivated().

  6. Prior to Honeycomb we had to implement workarounds to reflect state_checked in our list items. This is because ListView calls setChecked() ONLY on the topmost View in the layout (and layouts do not implement checkable) ... and it does NOT propagate without help. These workarounds were of the following form: Extend the root layout to implement Checkable. In its constructor, recursively find all the children that implement Checkable. When setChecked() etc... are called, pass the call on to those Views. If those views implement state list drawables (eg a CheckBox) with a different drawable for state_checked then the checked state is reflected in the UI.

  7. To do a nice background to a list item after Honeycomb all you need do is have a state list drawable with a drawable for the state state_activated like this (and use setItemChecked() of course):

    <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. To do a nice background to a list item prior to HoneyComb you would do something like the above for state_checked and you ALSO need to extend your topmost view to implement the Checkable interface. Within that you then need to tell Android whether the state you are implementing is true or false by implementing onCreateDrawableState() and calling refreshDrawableState() whenever the state changes.

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

... and the code to implement Checkable combined with state_checked in a RelativeLayout could be:

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

Thanks to the following:

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

Stackoverflow: How to add a custom button state

Stackoverflow: Custom Checkable View which responds to 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/

Community
  • 1
  • 1
Martin Harvey
  • 2,008
  • 1
  • 13
  • 9
  • 4
    this answer is priceless. I wish I'd read it before trying to work out how to implement a Checkable layout, etc. Thank-you very much. – Blake Mumford Jan 05 '14 at 04:50
  • 14
    great answer, but doesn't address "selected" items. I found the answer in the sentences RIGHT BEFORE the one you quoted: `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](http://developer.android.com/reference/android/view/View.html#setActivated(boolean)) – woojoo666 Aug 05 '14 at 23:06
  • my custom background color only appears behind selected/focused items, not checked items, when using the post-Honeycomb method you posted above: calling `setItemChecked()` and then using a selector with property `android:state_activated="true"` – woojoo666 Aug 06 '14 at 01:55
  • 1
    Thank you so much, I wasted 3 days trying to figure this out until I finally decided to ask myself "what's the difference between checked, selected and activated", sucks that dealing with something so simple as a menu has to be this complicated, overengineering by the geniuses of Google, almost seems like an obstacle set on purpose by this company to slow down others. – Gubatron Oct 13 '15 at 01:42
19

According to the doc:

  • android:state_selected Boolean. "true" if this item should be used when the object is the current user selection when navigating with a directional control (such as when navigating through a list with a d-pad); "false" if this item should be used when the object is not selected. The selected state is used when focus (android:state_focused) is not sufficient (such as when list view has focus and an item within it is selected with a d-pad).

  • android:state_checked Boolean. "true" if this item should be used when the object is checked; "false" if it should be used when the object is un-checked.

  • android:state_activated Boolean. "true" if this item should be used when the object is activated as the persistent selection (such as to "highlight" the previously selected list item in a persistent navigation view); "false" if it should be used when the object is not activated. Introduced in API level 11.

I think the doc is pretty clear, so what's the problem ?

AMerle
  • 4,354
  • 1
  • 28
  • 43
  • 5
    Can you elaborate on android:state_selected. What are the circumstances when it is set to true? – Anderson Sep 17 '13 at 11:58
  • @Anderson it will depend on the ViewGroup you're using - ListView, RecyclerView (probably its LayoutManagers), GridView may have differing implementations: ListView calls setFocused where GridView calls setSelected for example. It may just be a case of checking your app on different platform versions. – ataulm May 24 '15 at 11:35
  • 1
    @Anderson: If you have a list, and the user has arrow keys, one is "selected", and when they arrow up/down, the selection moves up/down. When they press the "activate" key, it "activates" the control, think of it selection as vaguely akin to mouseover, and check/activation as vaguely akin to clicking. – Mooing Duck Jul 20 '15 at 23:22
  • I was wondering, I am going to be using activated for highlighting one item in a list view, but does it set the activate for other list items to false ... if not do either of these do that so I do not have to find the other activated child item and set activation to false? – Lion789 Mar 20 '16 at 17:51
0

Here is other solution for this problem: https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/android/customizedlistview/MainActivity.java

I have overrided the method setOnItemClickListener and check differente cases in the code. But definitively the solution of Marvin is much better.

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
  • 3,373
  • 2
  • 35
  • 36