2012-07-02 11 views
20

que tienen un grupo de FrameLayout la que yo quiero ser comprobable/seleccionable,personalizada comprobable Ver que responde al selector

Es decir, después de un clic que le gustaría que el FrameLayout para mostrar como checked - cuando se pulsa de nuevo lo haría me gusta convertirse en un checked. Lo que es más, quiero que este visual que se describa como de costumbre a través del uso de un <selector>.

Me parece que no puede conseguir este trabajo - no estoy seguro de lo que me falta:

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 de la 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 de respaldo que (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"/> 

Utilizando el código por encima de la "state_pressed" está trabajando muy bien, pero la Vista en sí misma no se está verificando (no se llama al código Checkable como descubierto a través de la depuración).

Respuesta

23

añadiendo el siguiente código para una clase Checkable permite selectores para trabajar:

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

'onCreateDrawableState' no se llama desde LinearLayout por algún motivo. ¿Alguna idea de por qué? –

+1

si alguien quiere obtener una solución completa, consulte este repositorio: https://github.com/shamanland/AndroidLayoutSelector, se puede hacer clic/verificable '' 'LinearLayout''' como' '' ToggleButton''' –

0

Intente utilizar android:state_activated.

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

Desde el docs:

valor de Estado para StateListDrawable, establece cuando una vista o su matriz ha sido "activado" significa que el usuario ha marcado la actualidad y que son de interés .

+0

¿Dónde debería poner esa etiqueta? No está disponible para ''. – Graeme

+0

Es como cualquier otro estado. He agregado un ejemplo a mi respuesta. – Barak

+0

'state_activated' no hace ninguna diferencia en absoluto (también es API 11) – Graeme

0

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

<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

No hace ninguna diferencia: me aseguré de que cada elemento estuviera implícito (contiene tanto state_pressed como state_checked) para que no se confundan. – Graeme

0

Además de la respuesta de Graeme anterior hacer la siguiente modificación para cambiar()

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

Tengo incluido esto en la respuesta original – Graeme

+0

, la única adición aquí es que necesitamos llamar también a refreshDrawableState() en toggle(). – sujith

+1

duplicación innecesaria de código. – Graeme

0

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

y utilizar setActivated dentro de su setChecked:

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

y eso es todo. No es necesario implementar onCreateDrawableState aquí.

+0

Ver el [documento] (http://developer.android.com/reference/android/graphics/drawable/StateListDrawable.html#attr_android%3astate_activated) - "Esta es una representación alternativa de state_checked para cuando el estado debe ser propagado por la jerarquía de vista. ", Sonidos como este solo son útiles si también desea que los niños de su vista respondan' verdadero' si su padre está marcado. – Graeme

+0

Aunque es bueno saberlo. – Graeme

+0

La solución de Graeme funciona para mí para un botón seleccionable (también agregué refreshDrawableState() para setChecked() y toggle() como lo sugiere sujith. – Ridcully

4

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; 
    } 
} 
Cuestiones relacionadas