Android - activated state vs selected state

  Android's documentation isn't clear in terms of using activated and selected state drawable resources for a view. Both activated and selected state is passed down to child views,

    public void setActivated(boolean activated) {
            ...
            dispatchSetActivated(activated);
        }
    }

    /**
     * Dispatch setActivated to all of this View's children.
     */
    protected void dispatchSetActivated(boolean activated) {
    }

    public void setSelected(boolean selected) {
            ...
            dispatchSetSelected(selected);
        }
    }

    /**
     * Dispatch setSelected to all of this View's children.
     */
    protected void dispatchSetSelected(boolean selected) {
    }

So does it matter as to what state is associated with a drawable for child views in a list item? As per the documentation, the state info is passed down the view hierarchy and refreshDrawableState() should take care of updating the drawable resources. So lets put this to a test, the adapter has a simple logic to inflate a LinearLayout with an icon and couple of text views.

            LayoutInflater inflater = ( LayoutInflater ) getSystemService( LAYOUT_INFLATER_SERVICE );
            View listItem = inflater.inflate(R.layout.activity_my, parent, false );

            ImageView icon = ( ImageView ) listItem.findViewById(R.id.icon_view);
            icon.setImageResource( R.drawable.ic_launcher );

            TextView subject = ( TextView ) listItem.findViewById(R.id.subject);
            subject.setText("Subject");
            subject.setBackgroundResource( R.drawable.list_selector );

            TextView content = ( TextView ) listItem.findViewById(R.id.content);
            content.setText( "Content" );
            content.setBackgroundResource(R.drawable.list_selector);

            icon.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int choiceMode = mListView.getChoiceMode();
                    if ( choiceMode == AbsListView.CHOICE_MODE_MULTIPLE ) {
                        choiceMode = AbsListView.CHOICE_MODE_NONE;
                    } else {
                        choiceMode = AbsListView.CHOICE_MODE_MULTIPLE;
                    }
                    mListView.setChoiceMode( choiceMode );
                }
            });

            return listItem;

   The list item is similar to that of the gmail app, selecting the icon puts the list view in a choice mode to enable multiple selection. Clicking the icon toggles the list view's choice mode.

First, lets try with the following state list drawable,

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@drawable/selected_color" />
</selector>

   Selecting the icon does put the list view in selection mode. However, selecting an item from there on doesn't actually apply the selected_color drawable resource on the text views. However, this is not the case when the selector is updated to specify an activated state drawable resource,

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_activated="true" android:drawable="@drawable/activated_color">
</selector>

 In this case, selecting an item after setting the choice mode does indeed apply the activated resource on the text views of the list item. The reason as to why this happens is because of a logic in ListView,

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

The activated state is set explicitly on the list item by the list view and it rolls over to the child views picking up appropriate resources.

No comments: