项目中用到的自定义 view 还是有限的,所有有些知识点也是遗漏,这次做一个稍微全面点的总结,复习一下。
自定义 view 需要至少重写两个构造函数
1 | public MyView(Context context) { |
而且大部分时候只需重写两个函数:onMeasure()、onDraw()。onMeasure() 方法负责对当前 view 的尺寸进行测量,onDraw()方法负责把当前这个 view 绘制出来。
onMeasure
1 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) |
在 onMeasure 方法中,参数 widthMeasureSpec 与 heightMeasureSpec 包含了尺寸的测量模式和尺寸大小。我们知道 int 类型数据占用 32 个 bit,这个参数数值将 int 数据的前两个 bit 用于区分不同的布局模式,后面 30 个 bit 用于存放尺寸的数据。Android 内置类 MeasureSpec 可以帮助计算测量模式与尺寸:
1 | int widthMode = MeasureSpec.getMode(widthMeasureSpec); |
请注意,这里的尺寸大小并不是最终我们的 View 的尺寸大小,而是父 view 提供的参考大小。至于测量模式,表示了 view 与父 view 直接的关系,测量模式有三种:
测量模式 | 表示意思 |
---|---|
UNSPECIFIED | 父容器没有对当前View有任何限制,当前View可以任意取尺寸 |
EXACTLY | 当前的尺寸就是当前View应该取的尺寸 |
AT_MOST | 当前尺寸是当前View能取的最大尺寸 |
测量模式与布局时 wrap_content、match_parent 以及写成固定尺寸对应关系:
match_parent –> EXACTLY。match_parent 要利用父 View 给子 View 提供的剩余空间,而父 View 的剩余空间是确定的,也就是这个测量模式对应的数值锁存放的尺寸。
wrap_content –> AT_MOST。就是我们想要将大小设置为包裹我们的 View 内容,那么尺寸就是父 View 给我们作为参考的尺寸,是要不超过这个尺寸就可以,具体尺寸可以根据我们的需求去设定。
固定尺寸 –>EXACTLY。用户自己制定尺寸的大小。
重新 onMeasure 方法
1 | private int getMySize(int defaultSize, int measureSpec) { |
重写 onDraw 方法
1 | protected void onDraw(Canvas canvas) { |
自定义布局属性
- 首先需要再 res/values/styles.xml 文件(如果没有需要自己创建)里面生命一个需要自定义的属性;
1 | <resources> |
在布局文件中使用自定义的属性;
注意:需要再根标签中设定命名空间,命名空间的名称可以自己定义,命名空间的值为固定:“http://schemas.android.com/apk/res-auto”。
在自定义 View 里面通过参数 AttributeSet 把定义的属性取出。
1 | private int defalutSize; |
sh