Custom Checkable View which responds to Selector

雨燕双飞 提交于 2019-12-02 16:18:48

Adding the following code to a Checkable class allows Selectors to work:

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

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

@Override
public boolean performClick() {
    toggle();
    return super.performClick();
}

Here's a complete working example for a CheckableButton. It also works on Android 4.2.

public class CheckableButton extends Button implements Checkable {

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

    private boolean mChecked = false;

    public CheckableButton(Context context) {
        super(context);
    }

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

    public CheckableButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean isChecked() {
        return mChecked;
    }

    @Override
    public void setChecked(boolean checked) {
        mChecked = checked;
        refreshDrawableState();
    }

    @Override
    public void toggle() {
        mChecked = !mChecked;
        refreshDrawableState();
    }

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

Try using android:state_activated.

<item android:drawable="@color/HighlightColor"      android:state_activated="true"/> 

From the docs:

State value for StateListDrawable, set when a view or its parent has been "activated" meaning the user has currently marked it as being of interest.

vArDo

Try reordering tags in your selector_horizontal.xml These are evaluated top to bottom. It seems that in your case either android:state_pressed="false" or android:state_pressed="true" is applied and evaluation never reaches third line with android:state_checked="true" Try moving first line to last:

<item android:drawable="@color/HighlightColor" android:state_pressed="true"/>
<item android:drawable="@color/selected_color" android:state_checked="true"/>
<item android:drawable="@android:color/transparent" android:state_pressed="false"/>

In addition to Graeme's answer above do the following modification to toggle()

@Override
public void toggle() {
    mChecked = !mChecked;
    refreshDrawableState();
}

Graeme's solution doesn't worked from me under Android 4.0.3 (and I suppose it won't work under 4.0 too). Instead you can change state_checked to state_activated:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/activated_image" android:state_pressed="false" android:state_activated="true" />
    <item android:drawable="@drawable/not_activated_image" android:state_pressed="false" android:state_activated="false"/>

</selector>

and use setActivated inside your setChecked:

@Override
public void setChecked(boolean checked) {
    mChecked = checked;
    setActivated(checked);
}

and that is all. Implementing onCreateDrawableState isn't required here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!