2011-01-20 14 views
17

Mi pregunta es cómo agregar una sombra al texto cuando se selecciona TextView o Ver que TextView está seleccionado. Por ejemplo, tengo un CheckedTextView que cambia el fondo según el tipo de selección. También hice un selector de texto que cambia de color en diferentes estados. Ahora me gustaría agregar una sombra cuando, por ejemplo, se selecciona View. Por lo tanto, cambia el color de fondo, el color del texto y crea una sombra. Este es mi selector de texto:Cómo agregar sombra a TextView en la selección/enfoque

<selector 
xmlns:android="http://schemas.android.com/apk/res/android"> 

<item 
    android:state_focused="true" 
    android:state_pressed="false"  
    android:color="@android:color/white" 
    style="@style/DarkShadow"/> 

<item 
    android:state_focused="true" 
    android:state_pressed="true"    
    android:color="@android:color/white" 
    style="@style/DarkShadow"/> 

<item 
    android:state_focused="false" 
    android:state_pressed="true" 
    android:color="@android:color/white" 
    style="@style/DarkShadow"/> 

<item 
    android:color="@color/primary_text_light_disable_only"/> 

y estilo:

<style name="DarkShadow"> 
    <item name="android:shadowColor">#BB000000</item> 
    <item name="android:shadowRadius">2.75</item> 
</style> 

Ahora el texto se bien evidenciado pero parece que no hay sombras. Alguien sabe cómo resolver esto?

+0

que sabía de la lista Color Estado y la lista Disponibles Estado, pero la sombra parece ser una propiedad particular de Vista de Texto. Probablemente los atributos de sombras simplemente sean ignorados. Hubiera usado algún método onStateChange para las vistas, definiendo dinámicamente la sombra, pero acabo de buscarlo y, sorprendentemente, ¡solo existe para los dibujables! Entonces preguntaría: ¿es posible obtener un cambio de estado de vista? – bigstones

Respuesta

3

Sí, me encontré con el mismo problema, puede cambiar el color del texto usando un selector en xml, pero no el color de la sombra. Así que con el fin de resolver el problema, puede que tenga que extender CheckedTextView o cualquier visión que necesita, y luego anular onDraw(Canvas canvas) según el estado de la Vista Por lo tanto, es necesario utilizar public void setShadowLayer (float radius, float dx, float dy, int color) definido en here

por ejemplo, :

@Override 
protected void onDraw(Canvas canvas) { 
    if(isPressed()){ 
     setShadowLayer(1, 0, 1, Color.RED); 
    }else{ 
     if(isFocused()){ 
      setShadowLayer(1, 0, 1, Color.WHITE); 
     }else{ 
      setShadowLayer(1, 0, 1, Color.BLACK); 
     } 
    } 
    super.onDraw(canvas); 
} 

espero que funciona

+1

Este código tal como está escrito no funciona sentido setShadowLayer termina redibujando para que termine en un bucle infinito. Pero puede colocarlo en FocoChanged o establecer un OnFocusChangeListener en una instancia. – miguel

+0

@miguel estuvo de acuerdo. Las llamadas setShadowLayer invalidan. – nmw

+0

¿cómo lo resolvió entonces? – r4jiv007

21

Ésta es una limitación actual del SDK de Android. extendí TextView para que funcione, se puede usar libremente:

CustomTextView.java:

import android.widget.TextView; 
import android.util.AttributeSet; 
import android.content.res.TypedArray; 
import android.content.Context; 

import com.client.R; 


public class CustomTextView extends TextView 
{ 

    private static String TAG = "CustomTextView"; 

    private ColorStateList mShadowColors; 
    private float mShadowDx; 
    private float mShadowDy; 
    private float mShadowRadius; 


    public CustomTextView(Context context) 
    { 
     super(context); 
    } 


    public CustomTextView(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
     init(context, attrs); 
    } 


    public CustomTextView(Context context, AttributeSet attrs, int defStyle) 
    { 
     super(context, attrs, defStyle); 
     init(context, attrs); 
    } 


    /** 
    * Initialization process 
    * 
    * @param context 
    * @param attrs 
    * @param defStyle 
    */ 
    private void init(Context context, AttributeSet attrs, int defStyle) 
    { 
     TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView, defStyle, 0); 

     final int attributeCount = a.getIndexCount(); 
     for (int i = 0; i < attributeCount; i++) { 
      int curAttr = a.getIndex(i); 

      switch (curAttr) {     
       case R.styleable.CustomTextView_shadowColors: 
        mShadowColors = a.getColorStateList(curAttr); 
        break; 

       case R.styleable.CustomTextView_android_shadowDx: 
        mShadowDx = a.getFloat(curAttr, 0); 
        break; 

       case R.styleable.CustomTextView_android_shadowDy: 
        mShadowDy = a.getFloat(curAttr, 0); 
        break; 

       case R.styleable.CustomTextView_android_shadowRadius: 
        mShadowRadius = a.getFloat(curAttr, 0); 
        break; 

       default: 
       break; 
     } 
    } 

     a.recycle(); 

     updateShadowColor(); 
    } 

    private void updateShadowColor() 
    { 
     if (mShadowColors != null) { 
      setShadowLayer(mShadowRadius, mShadowDx, mShadowDy, mShadowColors.getColorForState(getDrawableState(), 0)); 
      invalidate(); 
     } 
    } 

    @Override 
    protected void drawableStateChanged() 
    { 
     super.drawableStateChanged(); 
     updateShadowColor(); 
    } 
} 

También es necesario agregar esto a su attr.xml (o crear uno): attr .xml:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <declare-styleable name="Theme"> 
     <attr format="reference" name="CustomTextView"/> 
    </declare-styleable> 

    <declare-styleable name="CustomTextView"> 
     <attr name="shadowColors" format="color|reference"/> 
     <attr name="android:shadowDx"/> 
     <attr name="android:shadowDy"/> 
     <attr name="android:shadowRadius"/> 

    </declare-styleable> 
</resources> 

Así que, finalmente, usted será capaz de utilizarlo en sus XMLs, así:

<com.client.ui.textviews.CustomTextView 
xmlns:client="http://schemas.android.com/apk/res/com.client" 
     android:id="@+id/join_text" 
     android:shadowDx="1" 
     android:shadowDy="1" 
     android:shadowRadius="1" 
     client:shadowColors="@color/btn_green_shadow_color"/> 

Dónde @color/btn_green_shadow_color apunta a un selector de tal esto:

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 

    <item android:state_enabled="false" android:color="@android:color/white"/> 
    <item android:state_pressed="true" android:color="@color/BzDarkGray"/> 
    <item android:color="@android:color/black"/> 

</selector> 

Si usted no está familiarizado con el uso de atributos personalizados (con el espacio de nombres XML personalizado utilicé), por favor refiérase a this good StackOverFlow question.

+0

Debí haber leído mal tu publicación, probablemente confundirla con otra. Pensé que habías creado nuevos atributos para shadowDx/Dy/Radius. He borrado el comentario. Gracias. – nmw

+0

@Gilbert Estoy obteniendo un error de archivo XML binario inflando la clase customtextview. ¿Alguna idea de por qué? –

+0

@AshleyStaggs Creo que necesito un poco más de información sobre lo que estás tratando de hacer y sobre el error que estás recibiendo. – Gilbert

2

Esto es lo que terminé haciendo:

@Override 
protected void drawableStateChanged() { 
    super.drawableStateChanged(); 
    if(isPressed()) { 
     setShadowLayer(15, 0, 0, getTextColors().getDefaultColor()); 
    } else { 
     setShadowLayer(0, 0, 0, Color.TRANSPARENT); 
    } 
} 
Cuestiones relacionadas