如何在 TextView 外部添加描边
How to add stroke on outside of TextView
欢迎任何想法、代码片段!
我创建了一个扩展 AppCompatTextView
的 CustomTextView
class,我这样做是为了添加 stroke 对无聊 TextView
的支持].问题是,Paint.Style.STROKE
在 TextView
的内侧添加了笔画。应该有一些东西可以让我们在外划和内划之间进行选择。
P.S:如果需要,我可以分享完整的 CustomTextView
class,没什么大不了的。
- 我们目前拥有的:
- 我们想要实现的目标:
这是我们 CustomTextView
中的 onDraw
方法,用于向 textView 添加描边。
@Override
protected void onDraw(Canvas canvas) {
if(_strokeWidth > 0) {
//set paint to fill mode
Paint p = getPaint();
p.setStyle(Paint.Style.FILL);
//draw the fill part of text
super.onDraw(canvas);
//save the text color
int currentTextColor = getCurrentTextColor();
//set paint to stroke mode and specify
//stroke color and width
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(_strokeWidth);
setTextColor(_strokeColor);
//draw text stroke
super.onDraw(canvas);
//revert the color back to the one
//initially specified
setTextColor(currentTextColor);
} else {
super.onDraw(canvas);
}
}
下面在 TextView 中绘制了字符的轮廓,但注意将字符本身剪掉,以免被覆盖。
OutlineTextView.java
public class OutlineTextView extends androidx.appcompat.widget.AppCompatTextView {
private final Paint mOutlinePaint = new Paint();
private final Path mOutlinePath = new Path();
private float mStrokeWidth = 0f;
public OutlineTextView(Context context) {
super(context);
init();
}
public OutlineTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public OutlineTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mOutlinePaint.setStrokeWidth(0f);
mOutlinePaint.setStyle(Paint.Style.STROKE);
mOutlinePaint.setColor(Color.RED);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
float xOffset = getLayout().getLineLeft(0) + getPaddingLeft();
float baseline = getLayout().getLineBaseline(0) + getPaddingTop();
getPaint().getTextPath(getText().toString(), 0, getText().length(), xOffset, baseline, mOutlinePath);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mStrokeWidth > 0) {
canvas.save();
// The following insures that we don't draw inside the characters.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
canvas.clipPath(mOutlinePath, Region.Op.DIFFERENCE);
} else {
canvas.clipOutPath(mOutlinePath);
}
canvas.drawPath(mOutlinePath, mOutlinePaint);
canvas.restore();
}
}
public void setStrokeWidth(Float strokeWidth) {
mStrokeWidth = strokeWidth;
mOutlinePaint.setStrokeWidth(strokeWidth);
invalidate();
}
}
欢迎任何想法、代码片段!
我创建了一个扩展 AppCompatTextView
的 CustomTextView
class,我这样做是为了添加 stroke 对无聊 TextView
的支持].问题是,Paint.Style.STROKE
在 TextView
的内侧添加了笔画。应该有一些东西可以让我们在外划和内划之间进行选择。
P.S:如果需要,我可以分享完整的 CustomTextView
class,没什么大不了的。
- 我们目前拥有的:
- 我们想要实现的目标:
这是我们 CustomTextView
中的 onDraw
方法,用于向 textView 添加描边。
@Override
protected void onDraw(Canvas canvas) {
if(_strokeWidth > 0) {
//set paint to fill mode
Paint p = getPaint();
p.setStyle(Paint.Style.FILL);
//draw the fill part of text
super.onDraw(canvas);
//save the text color
int currentTextColor = getCurrentTextColor();
//set paint to stroke mode and specify
//stroke color and width
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(_strokeWidth);
setTextColor(_strokeColor);
//draw text stroke
super.onDraw(canvas);
//revert the color back to the one
//initially specified
setTextColor(currentTextColor);
} else {
super.onDraw(canvas);
}
}
下面在 TextView 中绘制了字符的轮廓,但注意将字符本身剪掉,以免被覆盖。
OutlineTextView.java
public class OutlineTextView extends androidx.appcompat.widget.AppCompatTextView {
private final Paint mOutlinePaint = new Paint();
private final Path mOutlinePath = new Path();
private float mStrokeWidth = 0f;
public OutlineTextView(Context context) {
super(context);
init();
}
public OutlineTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public OutlineTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mOutlinePaint.setStrokeWidth(0f);
mOutlinePaint.setStyle(Paint.Style.STROKE);
mOutlinePaint.setColor(Color.RED);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
float xOffset = getLayout().getLineLeft(0) + getPaddingLeft();
float baseline = getLayout().getLineBaseline(0) + getPaddingTop();
getPaint().getTextPath(getText().toString(), 0, getText().length(), xOffset, baseline, mOutlinePath);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mStrokeWidth > 0) {
canvas.save();
// The following insures that we don't draw inside the characters.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
canvas.clipPath(mOutlinePath, Region.Op.DIFFERENCE);
} else {
canvas.clipOutPath(mOutlinePath);
}
canvas.drawPath(mOutlinePath, mOutlinePaint);
canvas.restore();
}
}
public void setStrokeWidth(Float strokeWidth) {
mStrokeWidth = strokeWidth;
mOutlinePaint.setStrokeWidth(strokeWidth);
invalidate();
}
}