前言
根据Gcssloop所学习的自定义View整理与笔记。
一、自定义View流程
简化版
二、自定义View的代码超级基础框架
public class MyView extends View {
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
//TODO 各种初始化内容
private void initView() {
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//TODO 在这里进行绘图操作
}
// @Override
// protected void dispatchDraw(Canvas canvas) {
// super.dispatchDraw(canvas);
// }
}
onDraw、dispatchDraw区别
- onDraw()的意思是绘制视图自身
dispatchDraw()是绘制子视图
- 无论是View还是ViewGroup对它们俩的调用顺序都是onDraw()->dispatchDraw()
- 在绘制View控件时,需要重写onDraw()函数,在绘制ViewGroup时,需要重写dispatchDraw()函数。
三、绘制流程
1.** 初始化画笔**
//TODO 各种初始化内容
private void initView() {
paint = new Paint();
paint.setColor(Color.RED);//画笔颜色为红色
paint.setStyle(Paint.Style.STROKE);//画笔模式为描边
paint.setStrokeWidth(5f);//画笔宽度为5px
paint.setAntiAlias(true); //是否使用抗锯齿功能
}
2.绘制内容
@Overrideprotected
void onDraw(Canvas canvas) {
super.onDraw(canvas);
//TODO 在这里进行绘图操作
//绘制底色
canvas.drawColor(Color.BLACK);
//在坐标(200,500)的位置绘制一个点
canvas.drawPoint(200, 500, paint);
//在这些坐标位置绘制多个点
canvas.drawPoints(new float[]{
200, 200,
300, 300,
400, 400
}, paint);
//绘制一条起点为(10,10),终点为(100,600)的直线
canvas.drawLine(10, 10, 100, 600, paint);
//绘制一组线
canvas.drawLines(new float[]{
0, 0, 0, 400,
0, 0, 500, 0
}, paint);
//绘制矩形
//第一种方式
canvas.drawRect(315,115,345,145,paint);
//第二种方式
Rect rect = new Rect(360, 115, 390, 145);
canvas.drawRect(rect,paint);
//第三种方式
RectF rectF = new RectF( 335.5f, 160F,370.5f, 170.6f);
canvas.drawRect(rectF,paint);
}
效果图
四、 绘制一些其他形状
- 圆角矩形
// 第一种
RectF rectF = new RectF(100,100,800,400);
//drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint)
canvas.drawRoundRect(rectF,30,30,paint);
// 第二种,API21以上可用
canvas.drawRoundRect(100,100,800,400,30,30,paint);
** rx,ry的理解**
圆角矩形的角实际上不是一个正圆的圆弧,而是椭圆的圆弧,这里的两个参数实际上是椭圆的两个半径
在rx为宽度的一半,ry为高度的一半时,刚好是一个椭圆,通过上面我们分析的原理推算一下就能得到,而当rx大于宽度的一半,ry大于高度的一半时,实际上是无法计算出圆弧的,所以drawRoundRect对大于该数值的参数进行了限制(修正),凡是大于一半的参数均按照一半来处理
- 椭圆
// 第一种
RectF rectF = new RectF(100,100,800,400);
canvas.drawOval(rectF,paint);
// 第二种
canvas.drawOval(100,100,800,400,paint);
椭圆原理
- 圆
// 绘制一个圆心坐标在(500,500),半径为400 的圆。
canvas.drawCircle(500,500,400,paint);
- 圆弧
// 第一种
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint){}
// 第二种
public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint) {}
startAngle :开始角度
sweepAngle:扫过角度
useCenter:是否使用中心
demo来一个吧O(∩_∩)O~
RectF rectF = new RectF(100, 100, 400, 300);
// 绘制背景矩形
paint.setColor(Color.GRAY);
canvas.drawRect(rectF, paint);
// 绘制圆弧
paint.setColor(Color.BLUE);
canvas.drawArc(rectF, 0, 60, false, paint);
RectF rectF2 = new RectF(100, 400, 400, 600);
// 绘制背景矩形
paint.setColor(Color.GRAY);
canvas.drawRect(rectF2, paint);
// 绘制圆弧
paint.setColor(Color.BLUE);
canvas.drawArc(rectF2, 0, 60, true, paint);
效果图:
五、画个饼图
要点:不断改变startAngle和sweepAngle的值就OK啦,直接举栗子
饼图效果图
public class MyView extends View {
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
private Paint paint;
private int[] startAngle = new int[6];
private int[] color = {Color.BLACK, Color.BLUE, Color.CYAN, Color.GREEN, Color.MAGENTA};
//TODO 各种初始化内容
private void initView() {
paint=new Paint();
paint.setColor(Color.RED);//画笔颜色为红色
paint.setStyle(Paint.Style.FILL);//画笔模式为描边
paint.setStrokeWidth(5f);//画笔宽度为5px
paint.setAntiAlias(true); //是否使用抗锯齿功能
for (int i = 0; i < 5; i++) {
startAngle[i] = i * 60 + i;
}
startAngle[5] = 360;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//TODO 在这里进行绘图操作
//移动到屏幕(200,300)的位置,下一篇会具体讲解的
canvas.translate(200, 300);
RectF rect = new RectF(-100, -100, 200, 200);
for (int i = 0; i < 5; i++) {
paint.setColor(color[i]);
canvas.drawArc(rect, startAngle[i], startAngle[i+1]-startAngle[i], true, paint);
}
}}
六、canvas的各种方法
[之后会讲解的,这里只提一下O(∩_∩)O~]
drawColor, drawRGB, drawARGB //使用单一颜色填充整个画布
drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc//依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧
drawBitmap, drawPicture//绘制位图和图片
drawText, drawPosText, drawTextOnPath//依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字
drawPath//绘制路径,绘制贝塞尔曲线时也需要用到该函数
drawVertices, drawBitmapMesh//通过对顶点操作可以使图像形变,drawVertices直接对画布作用、 drawBitmapMesh只对绘制的Bitmap作用
clipPath, clipRect//画布剪裁,设置画布的显示区域
save, restore, saveLayerXxx, restoreToCount, getSaveCount//依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数
translate, scale, rotate, skew//画布变换,依次为 位移、缩放、 旋转、错切
getMatrix, setMatrix, concat//实际上画布的位移,缩放等操作的都是图像矩阵Matrix, 只不过Matrix比较难以理解和使用,故封装了一些常用的方法。