Custom Checkable View which responds to Selector

前端 未结 6 474
生来不讨喜
生来不讨喜 2021-01-30 23:11

I have a group of FrameLayout which I want to be checkable/selectable,

That is, after a click I would like the FrameLayout to display as

相关标签:
6条回答
  • 2021-01-30 23:43

    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();
    }
    
    0 讨论(0)
  • 2021-01-30 23:46

    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"/>
    
    0 讨论(0)
  • 2021-01-30 23:52

    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.

    0 讨论(0)
  • 2021-01-30 23:52

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

    @Override
    public void toggle() {
        mChecked = !mChecked;
        refreshDrawableState();
    }
    
    0 讨论(0)
  • 2021-01-30 23:53

    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;
        }
    }
    
    0 讨论(0)
  • 2021-01-30 23:57

    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.

    0 讨论(0)
提交回复
热议问题