0

I am using the following selector to change the appearance of text in a listView item:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true"
          android:color="#FFFFFFFF" /> <!-- checked -->
    <item android:state_activated="true"
          android:color="#FFFFFFFF" /> <!-- activated -->
    <item android:state_pressed="true"
          android:color="#FFFFFFFF" /> <!-- pressed -->
    <item android:state_focused="true"
          android:color="#FFFFFFFF" /> <!-- focused -->
    <item android:color="#FF000000" /> <!-- default -->
</selector>

The entire selector works fine on later versions of Android (ICS, JB), but on Gingerbread, while the pressed_state item is being applied correctly, when I call setItemChecked on the listView, the state_checked item isn't applied.

The code I am using to set the item is as follows:

@Override
protected void onResume()
{
    super.onResume();

    getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    for (int index = 0; index < measureList.size(); index++)
    {
        if (measureList.get(index).getId() == appContext.getMeasureId())
        {
            getListView().setItemChecked(index, true);
        }
    }
}

and the xml used to set the selector is this:

<TextView
        android:id="@+id/item_text"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:layout_marginTop="8dp"
        android:layout_marginLeft="8dp"
        android:paddingRight="10dp"
        android:ellipsize="end"
        android:layout_toRightOf="@id/item_thumb"
        android:maxLines="1"
        android:scrollHorizontally="true"
        android:textStyle="bold"
        android:textSize="16sp"
        android:textColor="@color/selected_text_selector"
        />

Does anyone know why this happens? I haven't yet tested it out on versions of Android between GB and ICS, but will edit this post as soon as I do.

head in the codes
  • 1,159
  • 12
  • 24

1 Answers1

7

After a little searching, it seems to me the reason that the state_checked isn't expressed pre-Honeycomb is the fact that the setActive method on View is not available before API level 11. This means that the checked state is not propagated to the child views of my layout.

THE KEY:

  1. Swap the TextView for a CheckedTextView
  2. Propagate the checked state from the parent view to the children

1) Was a simple switch in the XML, and for 2) I modified the code in the answer linked to by Voicu to give the following:

public class CheckableRelativeLayout extends RelativeLayout implements Checkable
{
    private boolean checked = false;

    public CheckableRelativeLayout(Context context) {
        super(context, null);
    }

    public CheckableRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    private static final int[] CheckedStateSet = {
            R.attr.state_checked
    };

    @Override
    protected void dispatchSetPressed(boolean pressed)
    {
        super.dispatchSetPressed(pressed);
        setChecked(pressed);
    }

    @Override
    public void setChecked(boolean checked) {
        this.checked = checked;
        for (int index = 0; index < getChildCount(); index++)
        {
            View view = getChildAt(index);
            if (view.getClass().toString().equals(CheckedTextView.class.toString()))
            {
                CheckedTextView checkable = (CheckedTextView)view;
                checkable.setChecked(checked);
                checkable.refreshDrawableState();
            }
        }
        refreshDrawableState();
    }

    public boolean isChecked() {
        return checked;
    }

    public void toggle() {
        checked = !checked;
        refreshDrawableState();
    }

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        if (isChecked()) {
            mergeDrawableStates(drawableState, CheckedStateSet);
        }
        return drawableState;
    }

    @Override
    public boolean performClick() {
        return super.performClick();
    }
}
head in the codes
  • 1,159
  • 12
  • 24
  • 1
    Where is R.attr.state_checked defined? Should it be in my own package or is it really the android.R.attr.state_checked attribute? It would be helpful to see your imports or perhaps your associated attr.xml file if it needs to be in my own package. – Baron Apr 17 '14 at 17:21
  • 1
    @Baron: I'm afraid that since it's been a long time since asking this, I can no longer remember where this code was used and can't find the imports or xml files for you, but I'm almost certain I'm referring to android.R.attr.state_checked as you thought. Good point on the imports though. I'll be sure to include them in future questions! – head in the codes Apr 23 '14 at 17:51
  • @sleeke for future questions: yes, the attribute used is "android.R.attr state_checked.". Tested and worked perfectly. Thank you! – Taynã Bonaldo May 22 '14 at 14:01