主要用於實現不規則的效果,即這種效果不方便經過佈局的組合方式來實現。至關於就是得本身「畫」了。採用這種方式須要本身支持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的效果
今天你進步了嘛?歡迎關注個人微信公衆號,和我一塊兒天天進步一點點!