打赏

android 文字描边

描边 首先的想法就是俩个textview  这样是不是一下子就理解了  感觉很简单实现了?

 

1.在res下的values里面的colors.xml 新增一个描边颜色 我用的是白色

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="border_text" >#ffffff</color>
</resources>

2.新增自定义textview

复制代码
package com.example.myapplication1.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint.Style;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.appcompat.widget.AppCompatTextView;
import com.example.myapplication1.R;

/**
 * @ClassName StrokeTextView
 * @Description TODO
 * @Author ZhangXueTao
 * @Date 2020/9/10 11:10
 * @Version 1.0 模板 解救兔子图文版 描边文字
 */
public class StrokeTextView extends AppCompatTextView {

    private TextView borderText = null;///用于描边的TextView

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

    public void init(){
        TextPaint tp1 = borderText.getPaint();
        tp1.setStrokeWidth(4);                                  //设置描边宽度
        tp1.setStyle(Style.STROKE);                             //对文字只描边
        borderText.setTextColor(getResources().getColor(R.color.border_text));  //设置描边颜色
        borderText.setGravity(getGravity());
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        CharSequence tt = borderText.getText();

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

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

}
复制代码

3.使用

复制代码
<com.example.myapplication1.widget.StrokeTextView
                android:id="@+id/tv_yaoshi3"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintVertical_bias="0.85"
                app:layout_constraintHorizontal_bias="0.9"
                android:gravity="center"
                android:layout_width="wrap_content"
                android:layout_height="24dp"
                android:textSize="16dp"
                android:textColor="#FF0000"
                />
复制代码

 

 

当然还有其他的方法 例如采用两个TextView在一个layout中进行实现,但细想了下,如果我在一个TextView中让其以不同的方式进行两次描绘不就能够达到效果了吗?由于网上没有看到和我类似的方法,故发出来和大家分享,由于只需要重写protected void onDraw(Canvas canvas);方法即可:

复制代码
  private boolean m_bDrawSideLine = false; // 默认不采用描边  
       /* (non-Javadoc) 
 * @see android.widget.TextView#onDraw(android.graphics.Canvas) 
 */  
@Override  
protected void onDraw(Canvas canvas) {  
    if (m_bDrawSideLine) {  
                       // 描外层  
                       //super.setTextColor(Color.BLUE); // 不能直接这么设,如此会导致递归  
                       setTextColorUseReflection(Color.BLUE);  
                       m_TextPaint.setStrokeWidth(3);  // 描边宽度  
                       m_TextPaint.setStyle(Style.FILL_AND_STROKE); //描边种类  
                       m_TextPaint.setFakeBoldText(true); // 外层text采用粗体  
                       m_TextPaint.setShadowLayer(1, 0, 0, 0); //字体的阴影效果,可以忽略  
        super.onDraw(canvas);  
                         
  
                       // 描内层,恢复原先的画笔  
  
                       //super.setTextColor(Color.BLUE); // 不能直接这么设,如此会导致递归    
                       setTextColorUseReflection(Color.RED);  
                       m_TextPaint.setStrokeWidth(0);                           
                       m_TextPaint.setStyle(Style.FILL_AND_STROKE);                           
                       m_TextPaint.setFakeBoldText(false);                          
                       m_TextPaint.setShadowLayer(0, 0, 0, 0);                           
              }  
              super.onDraw(canvas);  
       }  
         
       private void setTextColorUseReflection(int color) {  
           Field textColorField;  
    try {  
    textColorField = TextView.class.getDeclaredField("mCurTextColor");  
    textColorField.setAccessible(true);  
    textColorField.set(color);  
    textColorField.setAccessible(false);  
    } catch (NoSuchFieldException e) {  
    e.printStackTrace();  
    } catch (IllegalArgumentException e) {  
    e.printStackTrace();  
    } catch (IllegalAccessException e) {  
    e.printStackTrace();  
    }  
           m_TextPaint.setColor(color);  
       }  
复制代码

 

 

或者

复制代码
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.util.AttributeSet;
import android.widget.TextView;

public class StrokeText extends TextView {

private float mBigFontBottom;
private float mBigFontHeight;

private String text;
private Paint mPaint;
private int strokeSize = 1;

public StrokeText(Context context) {
super(context);
init();
}

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

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

private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextSize(getTextSize());
mPaint.setColor(getResources().getColor(R.color.font_paint_color));
FontMetrics fm = mPaint.getFontMetrics();
mBigFontBottom = fm.bottom;
mBigFontHeight = fm.bottom - fm.top;
}

@Override
protected void onDraw(Canvas canvas) {
if (strokeSize > 0 && strokeSize < 4) {
float y = getPaddingTop() + mBigFontHeight - mBigFontBottom;
canvas.drawText(text, 0, y - strokeSize, mPaint);
canvas.drawText(text, 0, y + strokeSize, mPaint);
canvas.drawText(text, 0 + strokeSize, y, mPaint);
canvas.drawText(text, 0 + strokeSize, y + strokeSize, mPaint);
canvas.drawText(text, 0 + strokeSize, y - strokeSize, mPaint);
canvas.drawText(text, 0 - strokeSize, y, mPaint);
canvas.drawText(text, 0 - strokeSize, y + strokeSize, mPaint);
canvas.drawText(text, 0 - strokeSize, y - strokeSize, mPaint);
}

super.onDraw(canvas);
}

@Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
this.text = text.toString();
invalidate();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (strokeSize > 0 && strokeSize < 4) {
setMeasuredDimension(getMeasuredWidth() + strokeSize, getMeasuredHeight());
}
}

}
复制代码

 

posted @   YY2000  阅读(1368)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示