チェック可能/選択可能にしたいFrameLayout
のグループがあります。
つまり、クリックした後、FrameLayout
をchecked
として表示します。もう一度押すと、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_horizontal.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
コードは呼び出されません)。
次のコードを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();
}
これは、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;
}
}
GraemeのソリューションはAndroid 4.0.3では機能しません(4.0では機能しないと思います)。代わりにstate_checked
を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>
setActivated
内でsetChecked
を使用します。
@Override
public void setChecked(boolean checked) {
mChecked = checked;
setActivated(checked);
}
そしてそれがすべてです。ここでは、onCreateDrawableState
を実装する必要はありません。
Android:state_activated
を使用してみてください。
<item Android:drawable="@color/HighlightColor" Android:state_activated="true"/>
docs から:
StateListDrawableの状態値。ビューまたはその親が「アクティブ化」されたときに設定されます。これは、ユーザーが現在、ビューを対象としてマークしていることを意味します。
上記のGraemeの回答に加えて、toggle()に次の変更を加えます。
@Override
public void toggle() {
mChecked = !mChecked;
refreshDrawableState();
}
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"/>