Reputation: 97
I have created a CustomTextView
class that extends AppCompatTextView
and I did this to add stroke support to boring TextView
. The problem is, Paint.Style.STROKE
adds stroke on the inside of TextView
. There should be something which allows us to choose between outer-stroke and inner-stroke.
P.S: I can share the complete CustomTextView
class if needed, not a big deal.
This is the onDraw
method from our CustomTextView
which is used to add stroke to 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);
}
}
Upvotes: 2
Views: 829
Reputation: 62841
The following draws the outline of the characters in a TextView but takes care to clip out the characters themselves so they are not drawn over.
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();
}
}
Upvotes: 1