自定义view

自定义view优秀讲解

3.1.2 自定义 View 布局阶段
在 View 的布局阶段会执行两个方法(在布局阶段,View 的父 View 会通过调用 View 的 layout() 方法将 View 的实际尺寸(父 View 根据 View 的期望尺寸确定的 View 的实际尺寸)传给 View,View 需要在 layout() 方法中将自己的实际尺寸保存(通过调用 View 的 setFrame() 方法保存,在 setFrame() 方法中,又会通过调用 onSizeChanged() 方法告知开发者 View 的尺寸修改了)以便在绘制和触摸反馈阶段使用。保存 View 的实际尺寸之后,View 的 layout() 方法又会调用 View 的 onLayout() 方法,不过 View 的 onLayout() 方法是一个空实现,因为它没有子 View):

layout() onLayout()

layout() : 保存 View 的实际尺寸。调用 setFrame() 方法保存 View 的实际尺寸,调用
onSizeChanged() 通知开发者 View 的尺寸更改了,并最终会调用 onLayout() 方法让子 View 布局(如果有子
View 的话。因为自定义 View 中没有子 View,所以自定义 View 的 onLayout() 方法是一个空实现);
onLayout() : 空实现,什么也不做,因为它没有子 View。如果是 ViewGroup 的话,在 onLayout()
方法中需要调用子 View 的 layout() 方法,将子 View 的实际尺寸传给它们,让子 View
保存自己的实际尺寸。因此,在自定义 View 中,不需重写此方法,在自定义 ViewGroup 中,需重写此方法。 注意: layout()
& onLayout() 并不是「调度」与「实际做事」的关系,layout() 和 onLayout() 均做事,只不过职责不同。

3.1.3 自定义 View 绘制阶段
在 View 的绘制阶段会执行一个方法——draw(),draw() 是绘制阶段的总调度方法,在其中会调用绘制背景的方法 drawBackground()、绘制主体的方法 onDraw()、绘制子 View 的方法 dispatchDraw() 和 绘制前景的方法 onDrawForeground()。
draw() : 绘制阶段的总调度方法,在其中会调用绘制背景的方法 drawBackground()、绘制主体的方法
onDraw()、绘制子 View 的方法 dispatchDraw() 和 绘制前景的方法 onDrawForeground();
drawBackground() : 绘制背景的方法,不能重写,只能通过 xml 布局文件或者 setBackground()
来设置或修改背景;
onDraw() : 绘制 View 主体内容的方法,通常情况下,在自定义 View 的时候,只用实现该方法即可;
dispatchDraw() : 绘制子 View 的方法。同 onLayout() 方法一样,在自定义 View
中它是空实现,什么也不做。但在自定义 ViewGroup 中,它会调用 ViewGroup.drawChild() 方法,在
ViewGroup.drawChild() 方法中又会调用每一个子 View 的 View.draw() 让子 View 进行自我绘制;
onDrawForeground() : 绘制 View 前景的方法,也就是说,想要在主体内容之上绘制东西的时候就可以在该方法中实现。
注意: Android
里面的绘制都是按顺序的,先绘制的内容会被后绘制的盖住。如,你在重叠的位置「先画圆再画方」和「先画方再画圆」所呈现出来的结果是不同的。

view和ViewGroup的测量绘制过程我大致总结如下:
measure()
会被父view调用(应该是在onMeasure方法中调用),并传进父view对view的尺寸要求,完成一些测量前的优化和前置工作。measure接着会调用onMeasure方法,进行正式的测量,并最后通过setMeasureDimension告知父view自己的期望尺寸。(在ViewGroup中就是在onMeasure中调用子view的measure方法的)
layout
保存view的实际尺寸,通过调用setFrame方法。接着通过onSizeChange方法通知开发者view的尺寸发生了变化,最后调用onLayout方法(在onLayout中调用子view的layout方法)让子view进行布局(如果有子view的话)。
draw
依次执行绘制背景(不可重写,只能通过setBackground或xml进行设置)、绘制主体内容(onDraw)、绘制子view的方法(dispatchDraw()),会调ViewGroup.drawChild(),drawChild又会调用view的draw()方法依次类推、绘制前景。下面是重写draw()相关方法顺序不同的效果。
在这里插入图片描述
通过自定义ViewGroup和view来检验以上方法的执行顺序得到以下结果(以下结果均是在各方法体里的super代码前后打印log所得):

  1. VG-onMeasure:前
  2. V-onMeasure:前
  3. V-onMeasure:后
  4. VG-onMeasure:后
  5. VG-onLayout:前
  6. V-layout:前
  7. V-onLayout:前
  8. V-onLayout:后
  9. V-layout:后
  10. VG-onLayout:后
  11. VG-dispatchDraw:前
  12. V-draw:前
  13. V-onDraw:前
  14. V-onDraw:后
  15. V-dispatchDraw:前
  16. V-dispatchDraw:后
  17. V-draw:后
  18. VG-dispatchDraw:后

其中VG代表ViewGroup,V代表View;而且measure方法View和ViewGroup中均不能重写;layout方法ViewGroup中写成了final,故不能重写,View中可以;ViewGroup一般情况下不会执行draw方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值