前言
最近项目用到了文字的描边效果,本来以为是个很简单的东西,从网上搜了不少实现,但实际做出来的效果却很难达到要求,这里简单记录自己的实现方法。
实现接口
Android二维绘制的Paint画笔工具有一个重要的方法setStyle方法,里面可以传递三种实现方式,它们决定了绘制的时候是否直接填充还是包含描边功能。
public enum Style {
// 填充模式
FILL (0),
// 描边模式
STROKE (1),
// 填充和描边模式
FILL_AND_STROKE (2);
Style(int nativeInt) {
this.nativeInt = nativeInt;
}
final int nativeInt;
}
现在通过在自定义的TextView中设置Paint.setStyle属性查看它们具体实现的差别。
public class StrokeTextView1 extends AppCompatTextView {
private int mStrokeColor = Color.WHITE;
private float mStrokeWidth = 0;
public StrokeTextView1(Context context) {
this(context, null);
}
public StrokeTextView1(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public StrokeTextView1(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StrokeTextView);
mStrokeColor = a.getColor(R.styleable.StrokeTextView_strokeColor, Color.WHITE);
mStrokeWidth = a.getDimension(R.styleable.StrokeTextView_strokeWidth, 0f);
a.recycle();
}
setTextColor(mStrokeColor);
}
@Override
protected void onDraw(Canvas canvas) {
// 只有描边
TextPaint paint = getPaint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(mStrokeWidth);
super.onDraw(canvas);
}
}
// 有描边和填充
@Override
protected void onDraw(Canvas canvas) {
TextPaint paint = getPaint();
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeWidth(mStrokeWidth);
super.onDraw(canvas);
}
// 只有填充
@Override
protected void onDraw(Canvas canvas) {
TextPaint paint = getPaint();
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(mStrokeWidth);
super.onDraw(canvas);
}
从上面的实现效果来看,填充和描边占据的位置不会出现重叠现象,描边使用的是靠着填充外部的区域,所以在既有填充又有描边的情况下比只有填充的内容看起来更粗一些。
描边实现
可以使用FrameLayout内部放置两个大小完全一样而且内容位置也重合的TextView,上面的TextView只展示描边处理,下面的TextView只展示填充处理,这样就能够简单实现不错的描边效果。
<FrameLayout
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:textSize="100sp"
android:textStyle="bold"
android:textColor="@color/colorAccent"
android:text="5"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.example.misc2.widget.StrokeTextView1
android:textSize="100sp"
android:textStyle="bold"
android:textColor="@color/colorAccent"
android:text="5"
android:gravity="center"
app:strokeColor="@color/colorPrimary"
app:strokeWidth="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>