我有一组FrameLayout
我想要检查/选择,
也就是说,点击后我希望FrameLayout
显示为checked
- 再次按下时我希望它变为联合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”工作正常,但View本身没有被检查(不是通过调试发现的Checkable
代码被调用)。
答案 0 :(得分:25)
将以下代码添加到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();
}
答案 1 :(得分:3)
这是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;
}
}
答案 2 :(得分:0)
尝试使用android:state_activated
。
<item android:drawable="@color/HighlightColor" android:state_activated="true"/>
来自docs:
StateListDrawable的状态值,在视图或其父项具有时设置 已被“激活”,意味着用户当前已将其标记为 兴趣。
答案 3 :(得分:0)
尝试重新排序selector_horizontal.xml
中的标记。这些标记从上到下进行评估。在您的情况下,似乎应用android:state_pressed="false" or android:state_pressed="true"
并且评估永远不会到达android:state_checked="true"
的第三行尝试将第一行移到最后一行:
<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"/>
答案 4 :(得分:0)
除了Graeme的上述答案 对toggle()
进行以下修改@Override
public void toggle() {
mChecked = !mChecked;
refreshDrawableState();
}
答案 5 :(得分:0)
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
。