Android进阶知识(十五):自定义View的那些事

  这一篇章,笔者并不打算介绍如何自定义View,毕竟诸如此类的博客众多,而且从笔者前几篇对View的层次结构、事件分发机制以及工作原理的介绍,对自定义View的实现所涉及的技术都有一定的了解了。这一篇,笔者将简单的介绍以下自定义View的分类以及需要注意的地方。

一、自定义View的分类

  自定义View的分类标准不唯一,这里将自定义View分为4类。

  1. 继承View重写onDraw方法
      这种方法主要用于实现一些不规则的效果,即这种效果不方便通过布局的组合方式来实现,往往需要静态或动态显示一些不规则的图形。这需要通过绘制的方式实现,即重写onDraw。
      采用这种方式需要自己支持wrap_content,并且padding也需要自己处理
  2. Android 自定义native 服务 android 自定义view 注意点_自定义

  3. 继承ViewGroup派生特殊的Layout

  这种方法主要用于实现自定义的布局。采用这种方法稍微复杂,需要合适地处理ViewGroup的测量、布局两个过程,并同时处理子元素的测量和布局过程

Android 自定义native 服务 android 自定义view 注意点_自定义_02

  1. 继承特定的View

  这种方法比较常见,一般是用于扩展某种已有的View的功能,比如TextView。
  这种方法易实现,且不需要自己支持wrap_content和padding等

  1. 继承特定的ViewGroup

  当某种效果看起来像是几种View组合在一起时,可以采用这种方法实现。采用这种方法不需要自己处理ViewGroup的测量和布局这两个过程。一般来说方法2能实现的效果方法4也能实现,两者的主要差别在于方法2更接近View的底层

  自定义View讲究的是灵活性,一种效果可能多种方法都可以实现,开发者需要做的就是找到一种代价最小、最高效的方法去实现

Android 自定义native 服务 android 自定义view 注意点_自定义_03

二、自定义View须知

  自定义View过程中需要注意一些事项,否则有可能会影响到View的正常使用,甚至导致内存泄漏等。

  1. 让View支持wrap_content

  直接继承View或者ViewGroup的控件,不对wrap_content进行处理的情况下,当外界布局在使用wrap_content的时候效果等同于match_parent。具体原有参照Android进阶知识(十二):View的工作原理之基本概念 中普通View的MeasureSpec的构建规则表。

Android 自定义native 服务 android 自定义view 注意点_Android_04

  1. 如果有必要,让View支持padding

  直接继承View的控件,如果不在draw方法中处理padding,那么padding属性将无法起作用。另外,直接继承ViewGroup的控件需要在onMeasure和onLayout中考虑padding和子元素的margin对其造成的影响,不然将导致padding和子元素的margin无效

  1. 尽量不要在View中使用Handler,没必要

  View内部本身提供了post系列方法,完全可以替代Handler的作用。

  1. View中如果有线程或者动画,需及时停止

  如果有线程或者动画需要停止,那么onDetachedFromWindow是一个很好的时机。当包含View的Activity退出或者当前View被remove时,View的onDetachedFromWindow方法将被调用。与之对应的是onAttachedToWindow,当包含View的Activity启动时候,View的onAttachedToWindow方法会被调用。

  同时,当View不可见时,也需要停止线程和动画,如果不及时处理有可能造成内存泄漏

Android 自定义native 服务 android 自定义view 注意点_自定义View知识_05

  1. View带有滑动嵌套情形时,需要处理好滑动冲突

  如果有滑动冲突的话,那么需要合适地处理滑动冲突,否则将会严重影响View的效果。

参考资料:《Android艺术开发探索》