studio linearlayout example custom create control android view custom-view

android - linearlayout - Vista personalizable verificable que responde al Selector



draw view android (6)

Tengo un grupo de FrameLayout que quiero ser seleccionable,

Es decir, después de un clic, me gustaría que el FrameLayout mostrara como checked - cuando se presione nuevamente, me gustaría que se checked . Además, quiero que esta cola visual se describa como de costumbre a través del uso de un <selector> .

Parece que no consigo que esto funcione, no estoy seguro de lo que me estoy perdiendo:

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); } }

El diseño del CheckableFrameLayout :

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

El selector que lo respalda (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"/>

Al usar el código anterior, "state_pressed" funciona bien, pero la vista en sí misma no se está verificando (no se llama al código de verificación como se descubrió a través de la depuración).


Además de la respuesta de Graeme anterior, haga la siguiente modificación en toggle ()

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


Agregar el siguiente código a una clase de Checkable permite que los selectores funcionen:

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


Aquí hay un ejemplo de trabajo completo para un CheckableButton. También funciona en 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; } }


Intente reordenar las etiquetas en su selector_horizontal.xml Estas se evalúan de arriba a abajo. Parece que en tu caso se android:state_pressed="false" or android:state_pressed="true" y la evaluación nunca llega a la tercera línea con android:state_checked="true" Intenta mover la primera línea para que dure:

<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"/>


La solución de Graeme no me funcionó bajo Android 4.0.3 (y supongo que tampoco funcionará bajo 4.0). En su lugar, puede cambiar state_checked a 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>

y use setActivated dentro de su setChecked :

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

y eso es todo. Implementar onCreateDrawableState no es necesario aquí.


Trate de usar android:state_activated .

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

De la docs :

Valor de estado para StateListDrawable, establecido cuando una vista o su principal se ha "activado", lo que significa que el usuario lo ha marcado como de interés.