web-dev-qa-db-ja.com

セレクターに応答するカスタムチェック可能ビュー

チェック可能/選択可能にしたいFrameLayoutのグループがあります。

つまり、クリックした後、FrameLayoutcheckedとして表示します。もう一度押すと、un checkedになります。さらに、<selector>を使用して、この視覚的なキューを通常どおりに説明する必要があります。

私はこれを機能させることができないようです-私は何が欠けているのかわかりません:

public class CheckableFrameLayout extends FrameLayout implements Checkable {
    private boolean mChecked = false;
    public CheckableFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    public boolean isChecked() {
        return mChecked;
    }

    public void toggle() {
        setChecked(!mChecked);
    }
}

CheckableFrameLayoutのレイアウト:

<com.test.view.CheckableFrameLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@drawable/selector_horizontal"
    Android:clickable="true" >

それを支えるセレクター(selector_horizo​​ntal.xml):

<item Android:drawable="@drawable/selector_vertical_selected" Android:state_pressed="false" Android:state_checked="true"/>  
<item Android:drawable="@drawable/selector_vertical_pressed" Android:state_pressed="true" Android:state_checked="false"/>
<item Android:drawable="@drawable/selector_vertical_normal" Android:state_pressed="false" Android:state_checked="false"/>

上記のコードを使用すると、「state_pressed」は正常に機能しますが、ビュー自体はチェックされません(デバッグで検出されたCheckableコードは呼び出されません)。

23
Graeme

次のコードをCheckableクラスに追加すると、セレクターが機能します。

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();
}
27
Graeme

これは、CheckableButtonの完全な実例です。 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;
    }
}
4
Ridcully

GraemeのソリューションはAndroid 4.0.3では機能しません(4.0では機能しないと思います)。代わりにstate_checkedstate_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>

setActivated内でsetCheckedを使用します。

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

そしてそれがすべてです。ここでは、onCreateDrawableStateを実装する必要はありません。

0
Dmitry Zaytsev

Android:state_activatedを使用してみてください。

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

docs から:

StateListDrawableの状態値。ビューまたはその親が「アクティブ化」されたときに設定されます。これは、ユーザーが現在、ビューを対象としてマークしていることを意味します。

0
Barak

上記のGraemeの回答に加えて、toggle()に次の変更を加えます。

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

selector_horizontal.xmlのタグを並べ替えてみてください。これらは上から下に評価されます。あなたの場合、Android:state_pressed="false" or Android:state_pressed="true"が適用され、評価がAndroid:state_checked="true"で3行目に達することはないようです。最初の行を最後に移動してみてください。

<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
vArDo