Android TextView 字体描边(修复动态设置无效问题)

如题,最近业务需求字体增加描边。兴高采烈的从网上copy下来demo运行之后发现在TextView完成onMeasure之后setText出来显示的问题就不带描边效果了,是代码出现问题了嘛?还是我copy错了?

分析了一波源码发现,网上常见的demo都只考虑了界面初始化阶段。也就是你如果在xml文件中或者在TextView绘制成功之前设置了文本,则渲染正常,但一旦如果文案发生变化,想再去更改时,发现描边效果不见了。

怎么解决?
思路:只要文字变化的时候,重新执行onMeasure里的逻辑不就好了?

行动:
然后我简单扒了下TextView的源码,发现每次setText之后都会触发

    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        if (mTextHelper != null && !PLATFORM_SUPPORTS_AUTOSIZE && mTextHelper.isAutoSizeEnabled()) {
            mTextHelper.autoSizeText();
        }
    }

解决:
不卖关子了,晒源码吧


/**
 * Title:带描边的TextView
 * Describe:
 * Remark:与网上常见的不同,我重写了 {@link #onTextChanged(CharSequence, int, int, int)},这样就支持动态修改了
 * 

* Created by milo * E-Mail : [email protected] * 2020/7/16 */ public class StrokeTextView extends AppCompatTextView { private static final String TAG = "StrokeTextView"; private TextView borderText = null;///用于描边的TextView private int mStrokeWidth = 3; private int mStrokeColor = R.color.module_magic_border_text; public StrokeTextView(Context context) { super(context); borderText = new TextView(context); init(); } public StrokeTextView(Context context, AttributeSet attrs) { super(context, attrs); borderText = new TextView(context, attrs); init(); } public StrokeTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); borderText = new TextView(context, attrs, defStyle); init(); } @Override public void setLayoutParams(ViewGroup.LayoutParams params) { super.setLayoutParams(params); borderText.setLayoutParams(params); } @Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); if (borderText != null) { FZLogger.d(TAG, "onTextChanged .. borderText == " + borderText.getText().toString() + ", text == " + text.toString()); CharSequence borderChar = borderText.getText(); //两个TextView上的文字必须一致 if (borderChar == null || !borderChar.equals(this.getText())) { borderText.setText(getText()); this.postInvalidate(); } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); CharSequence borderChar = borderText.getText(); //两个TextView上的文字必须一致 if (borderChar == null || !borderChar.equals(this.getText())) { borderText.setText(getText()); this.postInvalidate(); } borderText.measure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); borderText.layout(left, top, right, bottom); } @Override protected void onDraw(Canvas canvas) { borderText.draw(canvas); super.onDraw(canvas); } public void init() { TextPaint tp1 = borderText.getPaint(); tp1.setStrokeWidth(mStrokeWidth); //设置描边宽度 tp1.setStyle(Paint.Style.STROKE); //对文字只描边 borderText.setTextColor(getResources().getColor(mStrokeColor)); //设置描边颜色 borderText.setGravity(getGravity()); } private void setStrokeWidth(int strokeWidth) { this.mStrokeWidth = strokeWidth; init(); invalidate(); } private void setStrokeColor(@ColorRes int strokeColor) { this.mStrokeColor = strokeColor; init(); invalidate(); } }

再到代码中尝试一下,是不是任意时刻调用 setText 都可以正确显示描边了呢。

你可能感兴趣的:(Android TextView 字体描边(修复动态设置无效问题))