Android自定义View实现总结---以百度锁屏项目界面为例

自定义View的原则:一个好的自定义控件应当和Android本身提供的控件一样,封装了一系列的功能以供开发者使用,不仅具有完备的功能,也需要高效的使用内存和CPU
开发自定义View的步骤

  • 编写继承自View的子类
  • 为自定义View类增加属性
  • 绘制自定义View
  • 响应用户消息和事件
  • 自定义回调函数

自定义View的三种形式

  1. 继承已有的控件: 往往继承自系统自带的控件,例如继承自ImageView, Viewpager等,例如ConstellationPager extends ViewPager,一个可以无限循环切换的ViewPager
    • ConstellationPager: 在该ViewPager的构造函数中初始化页面布局,通过addView添加自定义View,并设置OnPageChangeListener
  2. 组合已有的控件: 往往继承自Layout, 通过LayoutInflater inflate xml文件来组合多个控件。例如KeyguardLayout extends FrameLayout, 该界面包括MultiWaveView,WeatherView等多个View;例如WeatherView extends LinearLayout,该界面中同样包括多个基础View控件
  3. 完全自绘的控件: 往往继承View/ViewGroup,例如MultiWaveView extends View, 一个锁屏的控件,包括a handle and outer ring,内部的OnTriggerListener监听手指滑动响应解锁或者打开App的操作,内部还绘制了类似彗星划过效果的动画

自定义View的重载方法

  • measure 过程由measure(int, int)方法发起,从上到下有序的测量 View,在 measure 过程的最后,每个视图存储了自己的尺寸大小和测量规格(三种测量规格MeasureSpec 类);measure 过程会为一个 View 及所有子节点的 mMeasuredWidth 和 mMeasuredHeight 变量赋值;onMeasure方法中调用setMeasuredDimension方法来设置自定义视图的尺寸
  • layout子视图的具体位置都是相对于父视图而言的。View 的 onLayout 方法为空实现,而 ViewGroup 的 onLayout 为 abstract 的,因此,如果自定义的 View 要继承 ViewGroup 时,必须实现 onLayout 函数。在 layout 过程中,子视图会调用getMeasuredWidth()和getMeasuredHeight()方法获取到 measure 过程得到的 mMeasuredWidth 和mMeasuredHeight,作为自己的 width 和 height。然后调用每一个子视图的layout(l, t, r, b)函数,来确定每个子视图在父视图中的位置。
  • Draw所有的视图最终都是调用 View 的 draw 方法进行绘制的。在自定义的视图复写onDraw(Canvas) 方法进行绘制, 操作canvas对象对一个bitmap对象进行绘制;View 的onDraw(Canvas)默认是空实现,复写该方法绘制自身的内容; 过程:绘制背景—-绘制自身—-绘制子视图—-绘制Layer和ScrollBar
  • invalidate()请求重绘 View 树,即 draw 过程,假如视图发生大小没有变化就不会调用layout()过程,并且只绘制那些调用了invalidate()方法的 View
  • requestLayout()当布局变化的时候,比如方向变化,尺寸的变化,会调用该方法,在自定义的视图中,如果某些情况下希望重新测量尺寸大小,应该手动去调用该方法,它会触发measure()和layout()过程,但不会进行 draw。
  • onTouchEvent():监听触摸事件的回调