Android自定义ViewGroup记录

来源:互联网 发布:收银员练习软件 编辑:程序博客网 时间:2024/06/05 08:45

在对自定义View的基础步骤有了一定的了解之后,总结下来就是这么几大步骤:

  1. 自定义属性(其中有自身View的属性以及布局属性就是layout_开头的属性)
  2. 重写onMeasure
  3. 重写onDraw(单纯的自定义view中不需要onLayout即可)
  4. 添加一些动画以及暴露的接口,触摸事件分发等

但是要实现一些复杂的效果,例如metrail-design的cardview的效果等,就需要掌握自定义ViewGroup的相关技能,这篇文章仅仅是个人的学习记录,如有不当处,欢迎斧正。

首先是View的工作原理。在Activity的创建的过程中会有一个DecorView,这个是整个Activity的根View,它包含了不同版本的标题栏,以及我们在setContentView中添加的布局。这个DecorView是一个FramLayout,所以Activity加载布局的过程的后半部分就是DecorView的展现,而前半部分就是如何通过WimdowManager来添加View吧(这是个人理解)。跑偏了主题了…..,拉回来。首先是整个window的流程:
这里写图片描述

如上图所示(借鉴网友的图片),整个window首先会执行performTraversales()方法,接着会依次调用measure(测量),layout(布局),draw(绘制)来在屏幕上展现整个view。而在自定义view中有几个方法是比较重要的:

  1. invalidate(): 请求重绘整个view tree,谁调用就重绘谁,如果视图大小不发生变化,则只是重新执行onDraw方法
  2. postInvalidate():适用于在非UI线程调用来控制viewtree的重绘
  3. requestFocus(): 请求view的draw过程,只请求draw过程
  4. requestLayout() :会重新请求view的measure以及layout过程。

在view的measure,layout,以及draw过程中,根据源码来看会有一定的条件控制,比如在draw过程中如果没有什么可以会知道的内容,就不会调用onDraw方法,例如在自定义ViewGroup的时候,没有设定什么可以绘制的内容,比如设定背景色就是绘制内容,在draw的过程中没有可以绘制的内容就会根据条件dispatchDraw过程向子view中调用draw过程,这样遍历下去。

自定义ViewGroup的过程相比于自定义View的话,本身更注重的是measure,layout过程,对我们而言就是,onMeasure以及onLayout方法的自定义上。

在Measure过程中,我们需要重视这三个方法:

  1. measureChildren
  2. measureChild
  3. measureChildWithMargin

根据方法名我们也能知晓这是向子view分发measure过程的方法,只有经过了此过程getChild().getMeasureWidth()才会有值,之后才能根据需求measure自身viewgroup,当然还是利用setMeasureDemession方法。

在layout过程中,就是根据自己的不同的的需求来对child进行layout过程了,通过getChildCount,以及getChild(int i)来获取child,再通过child.layout(l,t,r,b)方法来进行布局。在此记住一点,自身的onLayout的四个参数是相对于父布局的。在调用child.layout()传入的四个参数也需要是相对于viewgroup的值。

以上仅作记录,如有不妥处,敬请斧正!谢谢!

原创粉丝点击