View基础调用和接口记录
基础
API
构造方法
- new 创建的构造方法
public CanvasTestView(Context context) {
super(context);
}
- XML 内构造方法-自定义属性 - attrs
public CanvasTestView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
AttributeSet attrs
是指自定义参数
- XML 内 新增设置Style - defStyleAttr
public CanvasTestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
- Theme 内设置的Style - defStyleRes
public CanvasTestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
用途
尺寸测量,通过参数决定我们的自定义View用的宽和高是多少
参数
int widthMeasureSpec
int heightMeasureSpec
google实现的是:
int类型的32位二进制位中,31-30这两位表示模式,0~29这三十位表示宽和高的实际值
取出的方法已经被封装好,直接调用即可,
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
布局模式
-
UNSPECIFIED
二进制表示:00
父容器没有对当前View有任何限制,当前View可以任意取尺寸 -
EXACTLY
二进制表示:01
当前的尺寸就是当前View应该取的尺寸 -
AT_MOST
二进制表示:10
当前尺寸是当前View能取的最大尺寸
对应数值
import static android.view.View.MeasureSpec.AT_MOST;
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.UNSPECIFIED;
UNSPECIFIED ===0
EXACTLY ===1073741824
AT_MOST ===-2147483648
经过测试发现:EXACTLY
对应match_parent
和定值(100dp),无论XML设置值的大小
AT_MOST
对应wrap_content
宽和高的实际值
宽和高的实际值,单位是px
宽和高的实际值 = XML内尺寸(dp)* 屏幕密度
有的车机在XML内部直接使用的就是px,实际尺寸就会等于XML内尺寸
屏幕密度:
DisplayMetrics displayMetrics =getResources().getDisplayMetrics();
LogUtils.i(TAG, "displayMetrics.density ===" + displayMetrics.density);
void onDraw(Canvas canvas)
核心
View绘制的核心,需要绘制的内容都会绘制在Canvas
上
super.onDraw(canvas)
法来实现基本的绘制功能(绘制背景颜色、背景图片),
要想在这基础上进行实现自己的逻辑,可以在方法的前后添加代码,
在方法前添加的,就是绘制在原生 TextView 的底层,
在方法后添加的,就是绘制在原生 TextView 的上层
void onLayout(boolean changed, int left, int top, int right, int bottom)
用途
为View树计算实际的位置;当这个view和其子view被分配一个大小和位置时,被layout触发
参数
boolean changed
:当前View的大小和位置改变了
int left
:相较于父布局的原点,左部位置
int top
:相较于父布局的原点,顶部位置
int right
:相较于父布局的原点,右部位置
int bottom
:相较于父布局的原点,下部位置
void onFinishInflate()
从XML加载组件后回调
void onSizeChanged(int w, int h, int oldw, int oldh)
调用顺序
onMeasure
-->
onLayout
-->
onDraw
-->
API - 方法
void invalidate()
用途:
UI线程中使用
请求重绘( onDraw
),同步方法,如果视图的大小发生了变化,还会调用 layout()
方法,
关于 layout()
方法的触发时机是在:void invalidate(boolean invalidateCache)
-->
-->
void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,boolean fullInvalidate)
-->
ViewGroup --> void invalidateChild(View child, final Rect dirty)
parent.invalidateChildInParent(location, dirty) --> ViewParent invalidateChildInParent(final int[] location, final Rect dirty)
没有找到具体的位置,不过父布局确实有重绘的可能。
触发时机:
- 直接调用
invalidate()
方法,请求重新draw()
,但只会绘制调用者本身,自定义的时候用的还挺多; - 调用
setSelection()
方法,请求重新draw()
,但只会绘制调用者本身; - 调用
setVisibility()
方法,会间接调用invalidate()
方法,继而绘制该View
; - 调用
setEnabled()
方法,请求重新draw()
,但不会重新绘制任何视图,包括调用者本身。
void postInvalidate()
线程中可用
请求重绘
void requestLayout()
对View树进行重新布局layout过程(包括measure()过程和layout()过程),不会调用draw()过程,即不会重新绘制任何视图,包括该调用者本身
boolean requestFocus()
请求View树的draw()过程,但只会绘制需要重绘的视图,即哪个View或ViewGroup调用了这个方法,就重绘哪个视图
参考和转载地址
手把手教你写一个完整的自定义View:https://www.jianshu.com/p/af266ff378c6
【Android - 自定义View】之自定义View浅析:https://www.cnblogs.com/itgungnir/p/6217447.html
本文地址:https://blog.csdn.net/weixin_35691921/article/details/110523313
推荐阅读
-
PHP学习记录之面向对象(Object-oriented programming,OOP)基础【接口、抽象类、静态方法等】
-
【Java基础】接口和抽象类之间的对比
-
C#接口在派生类和外部类中的调用方法示例
-
Java面向对象基础之多态性,抽象类和接口
-
Java基础语法——抽象类、接口和内部类
-
Spring AOP 切面编程记录日志和接口执行时间
-
【Java基础】接口和抽象类之间的对比
-
Go基础系列:接口类型探测和type-switch
-
黑马Android76期学习笔记01基础--day08--start/bind开启服务、电话录音,特别广播接收者,bindService/接口调用服务内方法,混合开启服务,进程间通讯,aidl应用场景
-
Python学习记录5:基础知识-用户输入和while循环