自定义view
1. 自定义绘制
- 方式:重写绘制方法(最常用: onDraw()
- 绘制的关键: Canvas
- Canvas的绘制类方法: drawXXX()(关键参数: Paint)
- Canvas的辅助类方法:范围裁切( clipXXX(()和几何变换( Matrix))
- 使用不同的绘制方法来控制遮盖关系
1.1 Canvas对绘制的辅助
- 范围裁切
- clipRect()和 clipPath()
- 几何变换
- Canvas.translate/rotate/scale/skew()
- Matrix.pre/postTranslate/Rotate/Scae/Skew()及自定义变换
- Camera.rotate() Camera.setLocation():三维变换
2. 属性动画
2.1 ViewPropertyAnimator
- View.animate()
- 配合上translationX() translationY() alpha() rotation() scaleX() 等方法
2.2 ObjectAnimator
使用方式:
- 给自定义View添加 setter/ getter方法
- ObjectAnimator.ofXXX()
- ObjectAnimator.start()
- ObjectAnimator.ofXXX()创建Animator对象(自定义View别忘了添加setter / getter方法)
- start()执行动画
2.3 功能
- setDuration():设置时长
- setInterpolator():设置速度模型
- 设置监听器
3. 布局onMeasure()和onLayout()
onMeasure()和onLayout()
方式:重写布局过程的相关方法
- 1.测量过程: onMeasure()
- 2.布局过程: onLayout()
具体:
- 1.重写 onMeasure()来修改已有的View的尺寸
- 2.重写 onMeasure()来全新计算自定义View的尺寸
-
- 重写onMeasure()和onLayout()来全新计算自定义ViewGroup的内部布局
如,自定义一个方形imageview 可以这样写:
重写onMeasure()修改尺寸
- 重写onMeasure(),并调用super.onMeasure()触发原先的测量
- 用getMeasuredWidth()和getMeasuredHeight()取到之前测得的尺寸, 利用这两个尺寸来计算出最终尺寸
- 使用setMeasuredDimension()保存尺寸
4. 全薪定义view的尺寸
1.重写onMeasure()把尺寸计算出来
2.把计算的结果用resolveSize()过滤一遍后保存
5. 定制layout的内部布局
1.重写onMeasure()来计算内部布局
- 计算子View的尺寸
- 调用每个子View的measure(),让子View自我测量
- 结合开发者的要求(layout_ xxx)和自己的可用空间(自己的尺寸,上限一已用尺寸)
- 根据子View给出的尺寸,得出子View的位置,并保存它们的位置和尺寸
- 根据子View的位置和尺寸计算出自己的尺寸,并用setMeasuredDimension()保存
2.重写onLayout()来摆放子View
可用空间的判断方法
根据自己的MeasureSpec中的mode的不同:
- EXACTLY / AT_MOST:
可用空间: MeasureSpec 6 size - UNSPECIFIED:
可用空间:无限大
关于保存子View位置的两点说明
- 不是所有的Layout都需要保存子View的位置(因为有的Layout可以在布局阶段实时推导出子View的位置,例如LinearLayout)
- 有时候对某些子View需要重复测量两次或多次才能得到正确的尺寸和位置
6. 触摸反馈的核心原理及机制
自定义触摸反馈
- 重写onTouchEvent(),写入触摸反馈算法,并返回true;
- 如果是ViewGroup并且可能与子View产生触摸判别冲突,还需要重写onInterceptTouchEvent(),在合适的时候返回false来拦截事件流;
- 如果需要临时阻止父View的拦截,可以用requestDisallowInterceptTouchEvent(),这是一个非持久的方法,仅对当前事件流有效。