自定义控件(一)

这几天公司的项目静态页也写的差不多了,其中也写了两个简单的自定义控件,
1.自定义下划线的textView
2.斜线切割的textView

一、自定义下划线的textView

textView本身就是可以就能自带下划线,如以下的代码。

1
2
tvTest.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG); //下划线
tvTest.getPaint().setAntiAlias(true);//抗锯齿

但是不能定制,下划线的距文字的高度,下划线的宽度都不能改,所以就自定义了一个,比较简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class UnderLineTextView extends AppCompatTextView {
private Paint mPaint;
private float underlineWidth;
private int underlineColor;
private float underlinePaddingBottom;
private float underlinePaddingLeft;
private float underlinePaddingRight;
public UnderLineTextView(Context context) {
this(context, null);
}
public UnderLineTextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public UnderLineTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (isInEditMode())
return;
if (null == attrs) {
throw new IllegalArgumentException("Attributes should be provided to this view,");
}
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.UnderLineTextView);
//下划线的高度
underlineWidth = typedArray.getDimension(R.styleable.UnderLineTextView_underlineWidth, getResources().getDimension(R.dimen.dp_1));
//下划线的颜色
underlineColor = typedArray.getColor(R.styleable.UnderLineTextView_underlineColor, Color.RED);
//下划线距离文字的高度
underlinePaddingBottom = typedArray.getDimension(R.styleable.UnderLineTextView_underlinePaddingBottom, getResources().getDimension(R.dimen.dp_1));
//下划线离左边的距离
underlinePaddingLeft = typedArray.getDimension(R.styleable.UnderLineTextView_underlinePaddingLeft, getResources().getDimension(R.dimen.dp_1));
//下划线离右边的距离
underlinePaddingRight = typedArray.getDimension(R.styleable.UnderLineTextView_underlinePaddingRight, getResources().getDimension(R.dimen.dp_1));
typedArray.recycle();
//创建画笔
mPaint = new Paint();
//设置抗锯齿
mPaint.setAntiAlias(true);
//设置画笔的粗细
mPaint.setStrokeWidth(underlineWidth);
//设置画笔颜色
mPaint.setColor(underlineColor);
//设置文本内容的padding
this.setPadding((int) underlinePaddingLeft, 0, (int) underlinePaddingRight, (int) underlinePaddingBottom);
}
/**
* 画出下划线
*
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画出下滑线
canvas.drawLine(0, this.getHeight(), this.getWidth(), this.getHeight(), mPaint);
}
}
以下便是自定义的属性
<!--下划线的textview-->
<declare-styleable name="UnderLineTextView">
<attr name="underlineWidth" format="dimension"/>
<attr name="underlineColor" format="color"/>
<attr name="underlinePaddingBottom" format="dimension"/>
<attr name="underlinePaddingLeft" format="dimension"/>
<attr name="underlinePaddingRight" format="dimension"/>
</declare-styleable>

如下图所示的下划线
underlineTextView

二、斜线切割的textView

斜线切割
如上图所示,主要用到了Mask遮盖效果,首先是底层的textView显示数字,然后用一个透明的三角切割掉重叠部分,之后再画上一条斜线。

首先来看上图就是mask的几种不同效果,那么我们用到的就是DstOut,代码如下

1
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
1
2
3
4
5
6
7
private void init(Context context, AttributeSet attrs) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //创建画笔
mPaint.setAntiAlias(true); //设置抗锯齿
mPaint.setColor(Color.WHITE); //设置画笔颜色
mPaint.setStyle(Paint.Style.FILL); //设置实心
this.setPadding(0, 0, 10, 0);
}

首先在初始化方法中,创建画笔及颜色,设置画笔类型为实心,设置右边有一点点的padding,是为了让斜线看上去更长一点,初始化完成后,就是在onDraw中利用画布来画我们的三角形和斜线了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Override
protected void onDraw(Canvas canvas) {
//1.保存现有层,特别注意这一步必须要有,否则无论如何出不来正常效果,起码我试了很久没有成功
int save = canvas.saveLayer(0, 0, this.getWidth(), this.getHeight(), null, Canvas.ALL_SAVE_FLAG);
super.onDraw(canvas);
//2.绘制三角形的线
Path path = new Path(); //创建路线
path.moveTo(this.getWidth(), 20);
path.lineTo(this.getWidth(), this.getHeight());
path.lineTo(10, this.getHeight());
path.close();
//3.设置笔触的Xfermode为new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
//4.使用笔触绘制三角形,进行遮盖
canvas.drawPath(path, mPaint);
//5.恢复之前保存的层
canvas.restoreToCount(save);
//6.取消笔触的Xfermode
mPaint.setXfermode(null);
//7.重新绘制一条斜线
canvas.drawLine(this.getWidth(), 20, 10, this.getHeight(), mPaint);
}

1.保存现有层,这个现有层就是我们显示的数字,这个方法一定要在super方法之前调用,如果在之后调用,没有效果,但是如果你两个遮盖的图形都是画出来的,那么就可以在super之后调用。
2.使用path来绘制三角形,moveTo是起点,lineTo是另外连接线的终点,再调用close()方法就能画出一个三角写了。
3.设置我们的遮盖类型为DST_OUT。
4.用画布绘制三角形,因为这时候的画笔设置了Xfermode模式,所以画出来的去掉三角形后的部分。
5.切割完后,调用restoreToCount()方法恢复之前保存的层。
6.取消画笔的xfermode模式。
7.在三角形的斜边上画一条白色的斜线,大功告成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class SlashMaskTextView extends AppCompatTextView {
private Paint mPaint;
public SlashMaskTextView(Context context) {
this(context, null);
}
public SlashMaskTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlashMaskTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //创建画笔
mPaint.setAntiAlias(true); //设置抗锯齿
mPaint.setColor(Color.WHITE); //设置画笔颜色
mPaint.setStyle(Paint.Style.FILL); //设置实心
this.setPadding(0, 0, 10, 0);
}
@Override
protected void onDraw(Canvas canvas) {
//1.保存现有层,特别注意这一步必须要有,否则无论如何出不来正常效果,起码我试了很久没有成功
int save = canvas.saveLayer(0, 0, this.getWidth(), this.getHeight(), null, Canvas.ALL_SAVE_FLAG);
super.onDraw(canvas);
//2.绘制三角形的线
Path path = new Path(); //创建路线
path.moveTo(this.getWidth(), 20);
path.lineTo(this.getWidth(), this.getHeight());
path.lineTo(10, this.getHeight());
path.close();
//3.设置笔触的Xfermode为new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
//4.使用笔触绘制三角形,进行遮盖
canvas.drawPath(path, mPaint);
//5.恢复之前保存的层
canvas.restoreToCount(save);
//6.取消笔触的Xfermode
mPaint.setXfermode(null);
//7.重新绘制一条斜线
canvas.drawLine(this.getWidth(), 20, 10, this.getHeight(), mPaint);
}
}