目录
一、前言
自定义控件一直是Android很重要的一部分,但是大部分时间我们都在处理业务逻辑而很少自己去写控件。因为现在开源的控件比较多,自定义写起来也比较麻烦。但是当我们需要的时候可能就忘了,所以菜鸟作者就买了本书打算系统的学习一遍。这一篇也算是《Android 自定义控件开发入门与实战》读后感。边学边工作也花了一个多月写过几篇笔记,不过后面的隐藏掉了。感觉有点啰嗦所以就凑成这一篇总结。
不管感兴趣与不感兴趣可以浏览一遍,积累一下基础。如果要深入学习这里也推荐两位大神博客
https://www.jianshu.com/p/146e5cec4863
https://blog.csdn.net/harvic880925 启舰《Android 自定义控件开发入门与实战》
二、基础代码
《 自定义控件开发入门与实战》这本书我这里主要分成两部分总结:1.自定义View 2.动画
这里主要根据练习时候写的Demo来进行基础的回顾。先从自定义View开始
(1)自定义View基础流程
- 1.继承View,或者继承ViewGroup,以及View/ViewGroup的派生类
- 2.测量 :onMeasure(),用来控制自定义View的宽高
- 3.位置:onLayout(),在继承ViewGroup的时候需要重写该方法,用来控制子View摆放的位置。
- 4.绘图:onDraw(),自定义View的主要方法,需要重载或重写该方法来绘制所需要的控件。
先从简单的开始讲起:
(2)onDraw()方法
为什么先说这方法呢 ? 因为前面两个方法不说。我们也可以通过这个方法来简单的实现自定义控件。
先上菜(代码),在介绍这道菜的好处
fun initPaint(){
//创建画笔
paint = Paint()
//设置画笔颜色
paint?.setColor(Color.WHITE)
//设置填充样式 1.Paint.Style.FILL仅填充内部 2.Paint.Style.FILL_AND_STROKE填充内部和描边 3.Paint.Style.STROKE仅描边
paint?.setStyle(Paint.Style.STROKE)
//设置画笔宽度 注:画笔样式为Paint.Style.FILL时不显示效果
paint?.setStrokeWidth(5f)
paint1 = Paint()
//设置画笔颜色
paint1?.setColor(Color.GREEN)
//设置填充样式 1.Paint.Style.FILL仅填充内部 2.Paint.Style.FILL_AND_STROKE填充内部和描边 3.Paint.Style.STROKE仅描边
paint1?.setStyle(Paint.Style.STROKE)
//设置画笔宽度 注:画笔样式为Paint.Style.FILL时不显示效果
paint1?.setStrokeWidth(5f)
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
//平移画布 起始点起始点从(X:0,Y:0)变成(X:100,Y:100)
canvas?.translate(0f, 100f)
//裁剪画布 构造方法很多 都是以clip开头
canvas?.clipRect(0, 0, 500, 500)
//设置画布颜色
canvas?.drawColor(Color.BLACK)
// canvas.drawARGB(0,0,0,255);
// canvas.drawRGB(0,0,255);
// 绘制直线 startX/startY:起始点X/Y坐标 stopX/stopY:终点X/Y坐标
canvas?.drawLine(100f, 50f, 450f, 50f, paint)
//绘制点
canvas?.drawPoint(50f, 50f, paint)
//绘制矩形====== >
val rect = Rect(50, 100, 450, 450)//创建矩形工具类
//绘制矩形方法
canvas?.drawRect(rect, paint)//第一种构造方法
// Rect/RectF用来保存int/float类型数值的矩形结构
// RectF rectf = new RectF(200,200,400,400);
// canvas.drawRect(rectf);第二种构造方法
// canvas.drawRect(200,200,400,400,paint);第三种构造方法
// <====== 绘制矩形方法
// 起始点变成(X:50,Y:100)
canvas?.translate(50f, 100f)
//绘制路径 ====== >
val path = Path()
//设置起始点
path.moveTo(100f, 50f)
//第一条直线的终点也是第二条直线的起点
path.lineTo(50f, 200f)
path.lineTo(150f, 100f)
path.lineTo(50f, 100f)
path.lineTo(150f, 200f)
// path.lineTo(100, 50);
//闭环
path.close()
//绘制路径方法
canvas?.drawPath(path, paint)
// < ======绘制路径
//绘制弧线 ===== >
val path1 = Path()
val rect1 = RectF(200f, 50f, 350f, 200f)
//弧线主要方法 oval 生成椭圆的矩形,startAngle 弧开始角度, sweepAngle 持续角度
path1.arcTo(rect1, 180f, 180f, false)
canvas?.drawPath(path1, paint)
// < ===== 绘制弧线
// 起始点变成(X:50,Y:100)
canvas?.translate(50f, 250f)
//绘制区域 ==== >
val region = Region(0, 0, 200, 50)
val region1 = Region(150, -50, 300, 50)
drawRegion(canvas, region, paint)
drawRegion(canvas, region1, paint1)
//区域操作
// (1)Op.DIFFERENCE:显示region与region1不同区域
// (2)Op.INTERSECT:显示region与region1相交区域
// (3)Op.UNION:显示region与region1组合在一起区域
// (4)Op.XOR:显示region与region1相交之外区域
// (5)Op.REVERSE_DIFFERENCE:显示region1与region不同区域
// (6)Op.REPLACE:显示region1区域
region.op(region1, Region.Op.INTERSECT)
paint1?.setColor(Color.GRAY)
drawRegion(canvas, region, paint1)
// < ==== 绘制区域
//保存当前画布状态
canvas?.save()
//恢复到上一层保存的状态
// canvas.restore();
}
fun drawRegion(canvas : Canvas?,region : Region,paint: Paint?){
var iter = RegionIterator(region)
var r = Rect()
while (iter.next(r)){
canvas?.drawRect(r,paint)
}
}
看完代码我们知道,绘图的前提是先准备好一只画笔(paint),要准备一只怎样的画笔呢。这时候我们可以根据Paint 类提供的API来定义画笔样式。
画笔准备好之后,我们就要考虑绘制什么样的图形呢,要绘制在什么地方。这时候我们需要一张画布,用来显示绘制的图形。
而onDraw(canvas: Canvas?)方法刚好提供了一个画布,并且通过Canvas类提供的API,我们可以绘制各式各样的图形。当然常用的绘图方法就看上面的代码。都用详细的注释。
总结