TextView添加描边——视频字幕

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.widget.TextView;

import java.lang.reflect.Field;

public class WrapTextView extends TextView {

    private int mBorderColor = Color.GRAY;
    private int mInnerColor = Color.WHITE;
    private boolean mBorderText = true;
    private TextPaint mTextPaint;

    public WrapTextView(Context context) {
        this(context, null);
    }

    public WrapTextView(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.textViewStyle);
    }

    public WrapTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mTextPaint = this.getPaint();
        mInnerColor = getCurrentTextColor();
    }

    /**
     * onDraw  draw border first
     */
    @Override
    protected void onDraw(Canvas canvas) {
        if (mBorderText) {
            // 描外层
            setTextColorUseReflection(mBorderColor);
            int width = 1;
            mTextPaint.setStrokeWidth(width); // 描边宽度
            mTextPaint.setStyle(Paint.Style.STROKE); // 画笔空心
            mTextPaint.setFakeBoldText(true); // 外层text采用粗体
            super.onDraw(canvas);

            // 描内层,恢复原先的画笔
            setTextColorUseReflection(mInnerColor);
            mTextPaint.setStrokeWidth(0);
            mTextPaint.setStyle(Paint.Style.FILL);
            mTextPaint.setFakeBoldText(false);
        }
        super.onDraw(canvas);
    }

    /**
     * 使用反射的方法进行字体颜色的设置
     * 其实就是 this.setTextColor(); 但是这个系统方法里会调用invalidate(); 最终的效果导致这段代码无限循环
     * 反射部分:
     * 1. Class.getDeclaredField(String name); 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段(包括私有成员)
     * 2. 获取私有属性的时候必须先设置Accessible为true,然后才能获取
     * 3. 通过Field.get(Object obj)获取属性的值,通过Field.set(Object obj,value)重新设置新的属性值
     */
    private void setTextColorUseReflection(int color) {
        Field textColorField;
        try {
            textColorField = TextView.class.getDeclaredField("mCurTextColor");
            textColorField.setAccessible(true);
            textColorField.set(this, color);
            textColorField.setAccessible(false);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        mTextPaint.setColor(color);
    }
}

转载于:https://www.cnblogs.com/cheneasternsun/p/5402632.html

实现 TextView 字体描边的方法有多种,以下是一种常见的方法: 1. 在 res/values 文件夹下新建一个名为 attrs.xml 的文件,添加以下代码: ``` <resources> <attr name="strokeWidth" format="dimension"/> <attr name="strokeColor" format="color"/> </resources> ``` 2. 在 TextView 标签中添加以下属性: ``` <com.example.myapp.MyTextView android:id="@+id/myTextView" android:text="Hello World!" android:textSize="24sp" app:strokeWidth="2dp" app:strokeColor="#000000" android:textColor="#ffffff"/> ``` 其中,MyTextView 是自定义的 TextView 类,继承自 android.widget.TextView。 3. 在 MyTextView 类中重写 onDraw 方法,实现字体描边的效果: ``` public class MyTextView extends TextView { private float strokeWidth; private int strokeColor; public MyTextView(Context context) { super(context); } public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyTextView); strokeWidth = a.getDimension(R.styleable.MyTextView_strokeWidth, 0); strokeColor = a.getColor(R.styleable.MyTextView_strokeColor, Color.BLACK); a.recycle(); } @Override protected void onDraw(Canvas canvas) { TextPaint paint = getPaint(); // 设置描边效果 paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(strokeWidth); paint.setColor(strokeColor); // 画出描边效果 super.onDraw(canvas); // 恢复原有的颜色和样式 paint.setStyle(Paint.Style.FILL); paint.setColor(getCurrentTextColor()); super.onDraw(canvas); } } ``` 注意,在重写 onDraw 方法时,需要先设置描边效果,再调用父类的 onDraw 方法画出描边效果,最后恢复原有的颜色和样式再次调用父类的 onDraw 方法,以保证正常显示字体。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值