(一)Canvas的save()和restore()
首先要有“分层”的一个概念,比如 时钟的 时针、分针、 秒针
如果都在同一个canvas上的话,canvas旋转后,所有的都跟着旋转了,为了防止这种情况,
canvas.save() ;
//在这中间draw,相当于另起了一层
canvas.restore();
可以想象一下,许多层玻璃面板,在不同的玻璃面板上draw完后,合在一块,就是最后的效果
(二)canvas的坐标系
drawLine(...)也好drawPoint(...)也好,参数中传进去的X、Y坐标点,是基于父View减去padding后的坐标系
(三)自定义View的分类
http://blog.csdn.net/jasonpeak/article/details/51729192
- 继承 View重写 onDraw 方法
这种方式主要用于显示不规则的效果哦,即这种效果不方便用布局组合来实现,往往需要静态或者动态的显示一些不规则的图形 采用这种方式需要自己支持wrap_content,并且padding也需要自己处理。
- 继承ViewGroup派生特殊的Layout
这种方法主要用于实现自定义布局,即除了LinearLayout,RelativeLayout等系统布局之外的一种重新定义的全新的布局,当某种效果很像 几种View组合在一起的时候就可以采用这种方法。 这种方法稍微复杂一些,需要合适的处理ViewGroup的测量和布局这俩个过程 - 继承特定的View(比如TextView)
这种方法一般用于扩展某种已有的View功能。这种方法不需要自己支持wrap_content,padding等。 - 继承特定的ViewGroup(比如LinearLayout等)
当某种效果很像几种View组合在一起的时候就可以采用这种方法。这种方法不需要自己处理ViewGroup的测量和布局这俩个过程。 与1.2比较,一般来说,1.2能实现的效果1.4也都能实现,但1.2更接近View的底层。
自定义View的注意事项
- 让View支持wrap_content
这是因为直接继承View或ViewGroup的控件,如果不在onMeasure中处理wrap_content,那么外界在布局中使用wrap_content时就无法达到预期效果 - 让View支持padding
直接继承View的控件,如果不再draw方法中处理padding,那么这个属性是无法起作用的。 直接继承ViewGroup的控件需要在onMeasure和onLayout中考虑padding和子元素的margin对其造成的影响,不然将导致pading和子元素的margin失效 - 不要在View中使用Handler
这是因为View内部本身就提供了post系列方法,完全可以替代Handler的作用。除非你很明确要用Handler来发送消息。 - View中如果有线程和动画,及时停止
如果有线程和动画需要停止的时候,onDetachedFromWindow就恶意做到。这是因为当包含此View的Activity退出或者当前View被remove时,View的onDetachedFromWindow方法就会被调用。相对的,当包含此View的Activity启动时onAttachedToWindow会被调用。同时,View不可见时,我们也需要停止线程和动画,如果不及时停止,可能会导致内存泄漏。 - 如果有滑动嵌套时,当然要处理好滑动冲突的问题。