TextView设置文字渐变色加描边,以及可能遇到handler处理setText文字重叠的问题

首先最近做到有文字是渐变色,并且有描边效果的需求……

网上有很多大佬关于文字描边和渐变色以及其他绚丽的效果的实现方式,但是合二为一的貌似没有
所以话不多说,所以我这里把大佬的方案整合一下,实现文字渐变并且有描边,下面上代码:

public class StrokeTextView extends android.support.v7.widget.AppCompatTextView {

    private TextView strokeText = null;///用于描边的TextView
    private int strokeColorRes = Color.WHITE;
    private int strokeWidth = 4;
    private boolean isGradient = false;
    private int startColor = Color.WHITE;
    private int endtColor = Color.BLACK;


    public StrokeTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public StrokeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        strokeText = new TextView(context, attrs, defStyleAttr);
        obtainStyledAttrs(context, attrs, defStyleAttr);
        init();
    }

    private void obtainStyledAttrs(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.StrokeTextView, defStyleAttr, 0);
        strokeColorRes = ta.hasValue(R.styleable.StrokeTextView_stroke_color)
                ? ta.getColor(R.styleable.StrokeTextView_stroke_color, Color.WHITE) : Color.WHITE;
        strokeWidth = ta.hasValue(R.styleable.StrokeTextView_stroke_width)
                ? ta.getDimensionPixelSize(R.styleable.StrokeTextView_stroke_width, 4) : 4;
        isGradient = ta.hasValue(R.styleable.StrokeTextView_is_Gradient)
                ? ta.getBoolean(R.styleable.StrokeTextView_is_Gradient, false) : false;
        startColor = ta.hasValue(R.styleable.StrokeTextView_start_color)
                ? ta.getColor(R.styleable.StrokeTextView_start_color, Color.WHITE) : Color.WHITE;
        endtColor = ta.hasValue(R.styleable.StrokeTextView_end_color)
                ? ta.getColor(R.styleable.StrokeTextView_end_color, Color.BLACK) : Color.BLACK;
    }

    public void init() {
        TextPaint tPaint = strokeText.getPaint();
        tPaint.setStrokeWidth(strokeWidth);//设置描边宽度
        tPaint.setStyle(Paint.Style.STROKE);//对文字只描边
        tPaint.setAntiAlias(true);//抗锯齿
        strokeText.setTextColor(strokeColorRes);  //设置描边颜色
        strokeText.setGravity(getGravity());
    }

    @Override
    public void setLayoutParams(ViewGroup.LayoutParams params) {
        super.setLayoutParams(params);
        strokeText.setLayoutParams(params);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        CharSequence tt = strokeText.getText();
        //两个TextView上的文字必须一致
        if (tt == null || !tt.equals(this.getText())) {
            strokeText.setText(getText());
            this.postInvalidate();
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        strokeText.measure(widthMeasureSpec, heightMeasureSpec);
    }

    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        strokeText.layout(left, top, right, bottom);
        if (isGradient) {
            if (changed) {
                //垂直由上往下
                getPaint().setShader(new LinearGradient(
                        0, 0, 0, getHeight(),
                        startColor, endtColor,
                        Shader.TileMode.CLAMP));
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        strokeText.draw(canvas);
        super.onDraw(canvas);
    }
}

对应的attrs.xml里的配置

    <!--描边TextView-->
    <declare-styleable name="StrokeTextView">
        <attr name="stroke_width" />
        <attr name="stroke_color" format="color"/>
        <attr name="is_Gradient" format="boolean"/>
        <attr name="start_color" format="color"/>
        <attr name="end_color" format="color"/>
    </declare-styleable>

不知是否有人疑问:为啥stroke_width这个属性,后面没有设置format
因为如果其他declare-styleable节点里声明里用到同名的属性,比如我这里在其他自定义view的配置里就有stroke_width这个同名属性,所以会导致冲突,报错,故而,将同名属性提到resources根节点下就没问题了,如下:

<attr name="stroke_width" format="dimension" />

然后布局xml里配置使用如下:

         <com.xx.StrokeTextView
                    android:id="@+id/kdCamp_main_token"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="30dp"
                    android:text="0423"
                    app:end_color="#E7A025"
                    app:is_Gradient="true"
                    app:start_color="#FBEDCC"
                    app:stroke_color="#724612"
                    app:stroke_width="1.5dp"/>

**然后,我遇到的坑是什么呢?**当然上面的设置是我最后的设置,是没问题的,然后我遇到的问题就是,xml里给StrokeTextView设置的初始值,在代码里,如果在activity的生命周期onCreate()内使用setText(xxx),会没有问题,但是在接口返回后handler里使用setText(xxx),就会出现 当前设置的值跟xml设置的默认值重叠的问题

后来查到问题的根源就是:我原本StrokeTextView的宽度是个确定值,包括自己layout_width设定死,或者父布局设定固定值,然后StrokeTextView的layout_width设置match_parent,总之StrokeTextView的宽度固定后就会有上面描述的问题,改成wrap_content就正常了,当前目前来看表面原因应该是当StrokeTextView的宽度因为某种形式是固定值的时候不能很好的触发界面的重绘和刷新,因为项目时间有限,具体原因还不明确,希望有研究的大佬不吝赐教!

你可能感兴趣的:(问题解决)