主要用于实现不规则的效果,即这种效果不方便经过布局的组合方式来实现。至关于就是得本身“画”了。采用这种方式须要本身支持wrap_content,padding也须要本身处理canvas
主要用于实现自定义的布局,看起来很像几种View组合在一块儿的时候,可使用这种方式。这种方式须要合适地处理ViewGroup的测量和布局,并同时处理子元素的测量和布局过程。好比自定义一个自动换行的LinerLayout等。微信
这种方法主要是用于扩展某种已有的View,增长一些特定的功能。这种方法比较简单,也不须要本身支持wrap_content和padding。ide
这种方式也比较常见,和上面的第2种方法比较相似,第2种方法更佳接近View的底层。布局
自定义View有多种方式,须要根据实际须要选择一种简单低成本的方式来实现post
直接继承View和ViewGroup的控件须要在onMeasure方法中处理wrap_content的方法。处理方法是在wrap_content的状况下设置一个固定的尺寸动画
//处理wrap_content的套路 @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //处理WAP_CONTENT int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(200,200); }else if (widthSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(200, heightSize); }else if (heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(widthSize, 200); } }
直接继承View的控件须要在onDraw方法中处理padding,不然用户设置padding属性就不会起做用。直接继承ViewGroup的控件须要在onMeasure和onLayout中考虑padding和子元素的margin对其形成的影响,否则将致使padding和子元素的margin失效。spa
@Override public void onDraw(Canvas canvas) { super.onDraw(canvas); //获取padding,而后根据实际状况处理就好 mPaddingLeft = getPaddingLeft(); mPaddingRight = getPaddingRight(); mPaddingTop = getPaddingTop(); mPaddingBottom = getPaddingBottom(); mWidth = getWidth() - mPaddingLeft - mPaddingRight; mHeight = getHeight() - mPaddingTop - mPaddingBottom; }
View中已经提供了post系列方法,彻底能够替代Handler的做用。线程
@UiThread public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource { ... public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); } // Postpone the runnable until we know on which thread it needs to run. // Assume that the runnable will be successfully placed after attach. getRunQueue().post(action); return true; } public boolean postDelayed(Runnable action, long delayMillis) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.postDelayed(action, delayMillis); } // Postpone the runnable until we know on which thread it needs to run. // Assume that the runnable will be successfully placed after attach. getRunQueue().postDelayed(action, delayMillis); return true; } ... }
在View的onDetachedFromWindow方法能够中止线程和动画,由于当View被remove或是包含此View的Activity退出时,就会调用View的onDetachedFromWindow方法。若是不处理的话极可能会致使内存泄漏code
View带有滑动嵌套时,须要处理好滑动冲突问题对象
在View的onDraw方法中不要建立太多的临时对象,也就是new出来的对象。由于onDraw方法会被频繁调用,若是有大量的临时对象,就会引发内存抖动,影响View的效果
今天你进步了嘛?欢迎关注个人微信公众号,和我一块儿天天进步一点点!