关于自定义view的补充

1.为什么自定义view需要重写onMeasure方法并设置wrap-content自身大小,否则布局效果和match_parent一样?

答:view在布局中使用wrap-content的话,其specMode为AT_MOST,这种情况下无论父容器是什么specMode(unspecified除外),子的specSize都是parentSize,宽高都等于父容器剩余的大小,这种效果和在布局中使用match_parent的效果一致,因此需要在onMeasure方法中给view指定一个默认的宽高,并在mode是AT_MOST的时候指定即可。

2. requestLayout() & invalidate() & postInvalidate()

requestLayout():

子view请求了这个方法后,会标记当前view并逐层向上调用直到ViewRootImp的requestLayout方法,即从view树的根部开始对于每一个含有标记位的view重新进行一次测量,布局,如果测量布局的结果发生变化时会调用绘制方法。

invalidate():该方法常用于内部调用或需要刷新界面的时候,在主线程调用该方法

先设置当前视图的标记位,然后通过dowhile循环不断向上回溯父容器,求父容器和子容器中需要绘制的部分的并集(dirty)。

再调用ViewGroup的invalidateChildInParent方法,该方法中将dirty区域坐标转换成父容器坐标,再求并集,向父容器传,直到ViewRootImpl的invalidateChildInParent方法

该方法也进行了offset和union对坐标的调整,然后把dirty区域的信息保存在mDirty中,最后调用了scheduleTraversals方法,触发View的工作流程,由于没有添加measure和layout的标记位,因此measure、layout流程不会执行,而是直接从draw流程开始。进行对整个view树的绘制(只绘制,并且只绘制需要绘制的部分(onDraw中代码))

postInvalidate():方法与invalidate一样,只不过是在非ui线程调用

大体与上文一致,只不过在绘制之前有一步,ViewRootImpl的dispatchInvalidateDelayed方法将重绘的消息传给mhandler(在主线程中ViewRootImpl所持有的handler),由这个handler执行invalidate()方法。

结论:

 

如果View确定自身不再适合当前区域,比如说它的LayoutParams发生了改变,需要父布局对其进行重新测量、布局、绘制这三个流程,往往使用requestLayout。而invalidate则是刷新当前View,使当前View进行重绘,不会进行测量、布局流程,因此如果View只需要重绘而不需要测量,布局的时候,使用invalidate方法往往比requestLayout方法更高效。

参考文档:Android View 深度分析requestLayout、invalidate与postInvalidate - 一点点征服 - 博客园

3.view的四种构造方法:

public View(Context context):在代码中创建view时会调用该方法。

public View(Context context, @Nullable AttributeSet attrs):该构造方法适用于反映在xml中创建的view,因为默认样式为0.所以此仅应用上下文主题和给定AttributeSet中的属性值。(没指定style时)

public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr):一般系统不会主动调用,需要手动调用,可以手动传入defStyleAttr并调用(指定一个基本style,如果没有对view设置某些属性则用style中的属性)

public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes):defStyleRes参数仅当在defStyleAttr为0或者找不到的时候才会用到

Context - 上下文;
AttributeSet - xml文件中的属性;
int defStyleAttr - Theme中的默认样式;
int defStyleResource - defStyleAttr未使用(为0,或者未匹配到),则应用于View的默认样式;
R.style中系统为view定义了很多默认主题Theme,主题中有对某些属性的默认赋值。

4.view和viewGroup的区别

参考链接:基础篇——View和ViewGroup的区别_一个灵活的胖子_Mr.Wang的博客-CSDN博客_viewgroup

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值