什么是自定义控件
自定义控件有三个点,布局绘制和触摸反馈。接下来的章节我们先说绘制,绘制就是在控件上显示需要我们用代码控制绘制细节,显示系统自带控件显示不出的内容,不管是多复杂的显示我们能够通过自定义控件绘制出来。
android的绘制跟我们平常的画画一样,我们在画画的时候需要笔和纸。android开发中笔就是Paint类,Canvas就是纸。凡是一些设置画笔的粗细、画笔颜色、透明度都是在Paint类中设置的,凡是能画出某种物体比如绘制圆形、矩形、文字都是在canvas里进行完成。
自定义绘制非常容易只需要重写onDraw方法,将创建好Paint对象传入canvas中,这里需要注意的是onDraw方法需要super.onDraw方法,而且android中的坐标系是左上角为(0,0)原点。
private Paint paint = new Paint();
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(10, 10, 100, 100, paint);
}
Paint相关方法
1.setColor
public void setColor(@ColorInt int color)
设置画笔的颜色,向下边这样。
paint.setColor(Color.YELLOW);
canvas.drawRect(10, 10, 100, 100, paint);
黄色的矩形.jpg
2.setAntiAlias
public void setAntiAlias(boolean aa)
一些不规则的图形例如文字,圆形需要打开抗锯齿功能让边缘更平滑。我们可以通过setAntiAlias方法可以设置是否使用抗锯齿,也可以在Paint构造函数中传入ANTI_ALIAS_FLAG
。
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setAntiAlias(true);
下边绘制一个圆形放大一下可以看到效果
开锯齿.jpg
抗锯齿依赖算法实现的,通过修改边缘处的颜色,让图形有了平滑的感觉。
3.setStyle
public void setStyle(Style style)
setStyle方法设置填充样式,对文字以及图形都有效。样式一共有三种,Paint.Style.FILL填充模式,Paint.Style.STROKE描边模式,以及Paint.Style.FILL_AND_STROKE两个模式一起使用,默认情况下是FILL填充模式。
4.setStrokeWidth
设置描边的宽度,在画笔在STROKE和FILL_AND_STROKE时使用。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(20);
canvas.drawCircle(200, 200, 50, paint);
setStrokeWidth.jpg
Canvas基础
1.画布颜色设置
canvas可以实现画布的颜色设置,通过以下方法实现。
public void drawColor(@ColorInt int color)
public void drawARGB(int a, int r, int g, int b)
public void drawRGB(int r, int g, int b)
根据drawColor方法可以知道,我们需要传入8位的颜色值,drawARGB传入A、R、G、B的颜色取值0~255范围。drawRGB函数只传入R、G、B,Alpha默认是255。
canvas.drawColor(Color.parseColor("#FF0000"));
canvas.drawRGB(255,0,0);
canvas.drawARGB(255,255,0,0);
画布设置.png
2.绘制点
public void drawPoint(float x, float y, @NonNull Paint paint)
drawPoint方法x,y分别是设置点的坐标,点的大小可以用setStrokeWidth方法设置大小。
paint.setStrokeWidth(80);
canvas.drawPoint(120, 120, paint);
点.jpg
多点绘制可以通过drawPoints方法来实现。
public void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
@NonNull Paint paint)
public void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint)
这里pts是设置点的坐标,设置为{x1,y1,x2,y2...},offset是跳过数值的个数(一个点有两个数)。count代表绘制数字的个数。
paint.setColor(Color.RED);
paint.setStrokeWidth(80);
float[] pts = {50, 50, 100, 100, 200, 200, 300, 300};
canvas.drawPoints(pts, 2/* 跳过两个数,即前两个 0 */, 6/* 一共绘制 6 个数(3 个点) */, paint);
drawPoints.jpg
3.绘制直线
public void drawLine(float startX, float startY, float stopX, float stopY,
@NonNull Paint paint)
startX、startY、stopX、stopY分别代表坐标的起始位置以及终止位置。
绘制多条直线
public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
@NonNull Paint paint)
public void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint)
直线.png
与多点绘制相似,可以利用drawLines方法绘制多条线段。
4.绘制矩形
public void drawRect(@NonNull RectF rect, @NonNull Paint paint)
public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)
利用drawRect方法可以绘制矩形我们可以通过矩形的四个点传值也可以通过RectF、Rect传值。
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(100, 100, 200, 200, paint);
矩形.jpg
5.绘制圆角矩形
public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint)
利用drawRoundRect方法可以绘制出带有圆角的矩形参数RectF设置绘制的矩形,rx、ry分别代表x轴和y轴的半径。
6.绘制圆形
public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
cx和cy分别设置圆心点的坐标,radius设置圆形半径。
canvas.drawCircle(100, 100, 30, paint);
圆形.png
7.绘制椭圆
public void drawOval(@NonNull RectF oval, @NonNull Paint paint)
drawOval是绘制椭圆的方法,根据矩形oval区域绘制出椭圆。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
paint2.setStyle(Paint.Style.STROKE);
paint2.setColor(Color.RED);
paint2.setStrokeWidth(5);
RectF rect = new RectF(100, 100, 400, 300);
canvas.drawOval(rect, paint);
canvas.drawRect(rect, paint2);
椭圆.png
另外绘制椭圆还有其他重载方法,drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)根据边界点绘制椭圆。
8.绘制弧形
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
@NonNull Paint paint)
弧是椭圆的一部分,椭圆又是根据矩形生成的,所以弧形也是根据矩形而来。
这里oval是矩形区域,startAngle是弧形的起始弧度,sweepAngle是弧形划过的角度;useCenter 表示是否连接到圆心,如果不连接到圆心,就是弧形,如果连接到圆心,就是扇形。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
paint2.setStyle(Paint.Style.STROKE);
paint2.setColor(Color.RED);
paint2.setStrokeWidth(5);
RectF rect = new RectF(100, 100, 400, 300);
canvas.drawArc(rect, 0, 90, true, paint);
canvas.drawArc(rect, 90, 180, false, paint2);
弧线.png
Path路径
在android开发中通过canvas绘制路径
void drawPath(Path path, Paint paint)
接下来看看path下有哪些方法。
1.直线路径
画直线一般需要三个函数
public void moveTo(float x, float y)
x,y设置起始点的位置。由当前位置 (0, 0) 移动致 (x, y)
public void lineTo(float x, float y)
lineTo方法是根据起始点设置终点。
public void close()
如果前边的划线没有形成闭环那么调用close方法可以首尾连接起来。当需要填充图形时(即 Paint.Style 为 FILL 或 FILL_AND_STROKE),Path 会自动封闭子图形。后边会有介绍。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
Path path = new Path();
path.moveTo(150, 150);//移动到(150,150)初始化为原点
path.lineTo(50, 250);//第一条线
path.lineTo(250, 250);//第二条线
path.close();
canvas.drawPath(path, paint);
close方法调用后形成一个闭环形成一个三角形。
2.弧线路径
public void arcTo(@NonNull RectF oval, float startAngle, float sweepAngle,
boolean forceMoveTo)
这个方法和 Canvas.drawArc() 比起来,少了一个参数 useCenter,而多了一个参数 forceMoveTo,forceMoveTo是否连线到弧形起点。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
RectF rect = new RectF(200, 200, 300, 300);
Path path = new Path();
path.moveTo(100, 100);
path.lineTo(150, 150);
path.arcTo(rect, -90, 90, true);
canvas.drawPath(path, paint);
forceMoveTo为true.png
path.arcTo(rect, -90, 90, false);
forceMoveTo为false.png.png
3.addXXX系列方法
添加圆形
public void addCircle(float x, float y, float radius, @NonNull Direction dir)
Direction是指路径方向CW顺时针,CCW逆时针。无论是顺时针逆时针,仅仅是方向不同,这里后边会介绍,其他addxxx方法也类似。
添加椭圆
public void addOval(@NonNull RectF oval, @NonNull Direction dir)
添加矩形
public void addRect(@NonNull RectF rect, @NonNull Direction dir)
添加圆角矩形
public void addRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Direction dir)
4.填充方式
public void setFillType(@NonNull FillType ft)
- WINDING (默认值)显示方向相交的内容
- EVEN_ODD 相交的地方填充
- INVERSE_WINDING
- INVERSE_EVEN_ODD
path.setFillType(Path.FillType.WINDING);
path.addCircle(200, 200, 100, Path.Direction.CW);
path.addCircle(290, 200, 100, Path.Direction.CW);
canvas.drawPath(path, paint);
WINDING相同方向.jpg
path.setFillType(Path.FillType.WINDING);
path.addCircle(200, 200, 100, Path.Direction.CW);
path.addCircle(290, 200, 100, Path.Direction.CCW);
canvas.drawPath(path, paint);
WINDING不同同方向.png
WINDING方式如果两个图形的path方向相同,即方向不想交,则可以全部显示,若方向不同,就产生了相交区域。
EVEN_ODD与WINDING不同同方向效果一致。
INVERSE_WINDING与INVERSE_EVEN_ODD与刚刚介绍的两个相反。
5.重置路径
当我们需要绘制一条全新的路径的时候,可以重置路径的对象,这样我们就可以不需要重新定义路径的对象了。
void reset()
void rewind()
reset会保留当前的数据结构,会清除FillType,rewind会清除数据空间,但不会清除FillType。
网友评论