How to add shadow to TextView on selection/focus

后端 未结 3 1116
情书的邮戳
情书的邮戳 2020-12-23 22:54

My question is how to add a shadow to text when TextView is selected or View that TextView is in gets selected. For example I have a CheckedTextView which changes background

相关标签:
3条回答
  • 2020-12-23 23:05

    Yeah, I ran into the same problem, you can change the text color using a selector in xml, but not the shadowcolor. So in order to solve the problem, you might have to extend CheckedTextView or whatever View you need, and then override onDraw(Canvas canvas) according to the state of the View Thus, you need to use public void setShadowLayer (float radius, float dx, float dy, int color) defined in here

    for example:

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

    I hope that works

    0 讨论(0)
  • 2020-12-23 23:15

    This is a current limitation of the Android SDK. I extended TextView for it to work, you can use it freely:

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

    You also need to add this to your attr.xml (or create one): 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>
    

    So finally you'll be able to use it in your xmls, like this:

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

    Where @color/btn_green_shadow_color points to a selector such a this:

    <?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>
    

    If you are not familiar with how to use custom attributes (with the custom xml namespace I used), please refer to this good StackOverFlow question.

    0 讨论(0)
  • 2020-12-23 23:19

    This is what I ended up doing:

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        if(isPressed()) {
            setShadowLayer(15, 0, 0, getTextColors().getDefaultColor());
        } else {
            setShadowLayer(0, 0, 0, Color.TRANSPARENT);
        }
    }
    
    0 讨论(0)
提交回复
热议问题