【eoe教程】Android中自定义视图的绘制方法
原文鏈接 :http://android.eoe.cn/topic/ui
自定義視圖最重要的部分是它的外觀.你可以根據應用的需求簡單或復雜的實現它. 這個教程包含了最常見的操作.
重寫onDraw()
繪制自定義視圖里最重要的一步是重寫onDraw())方法.?onDraw())的參數是視圖可以用來繪制自己的Canvas對象. Canvas定義用來繪制文本、線條、位圖和其他圖像單元. 你可以在onDraw())里使用這些方法創建你的自定義用戶界面(UI).
不過, 在你調用任何繪畫的方法之前, 你必須創建Paint對象. 下一章節將會探討Paint的更多細節.
創建繪畫對象
android.graphics框架把繪圖分成了兩部分:
-
畫什么, 由Canvas處理
-
怎么畫, 由Paint處理
例如,?Canvas提供畫線條的方法, 而Paint提供定義線條顏色的方法.?Canvas提供畫矩形的方法, 而Paint定義是否用顏色填充矩形或讓它為空. 簡而言之,?Canvas定義你可以在屏幕上畫的形狀, 而Paint為你畫的每個形狀定義顏色、樣式、字體等等.
所以, 在你畫任何東西之前, 你需要創建一個或多個Paint對象. * PieChart_'(餅圖)例子的'_init()* 方法里有這樣的實現, 這個方法在構造函數里調用:
| 123456789 10 11 12 13 14 15 16 17 18 | private void init() {mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mTextPaint.setColor(mTextColor);if (mTextHeight == 0) {mTextHeight = mTextPaint.getTextSize();} else {mTextPaint.setTextSize(mTextHeight);}mPiePaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPiePaint.setStyle(Paint.Style.FILL);mPiePaint.setTextSize(mTextHeight);mShadowPaint = new Paint(0);mShadowPaint.setColor(0xff101010);mShadowPaint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL));... |
提前創建對象是一個很重要的優化. 視圖頻繁的被重畫, 并且許多繪圖對象初始化需要消耗大量的資源. 在onDraw())方法里創建繪圖對象會嚴重降低性能, 并可以讓你的UI顯得有些遲鈍.
處理布局事件
為了正確的繪制你的自定義視圖, 你需要知道它的大小. 復雜的自定義視圖經常需要根據它的大小和在屏幕上的圖形區域執行多次布局計算. 你永遠不應該假設視圖在屏上的大小. 即使只有一個應用使用你的視圖, 應用也需要處理不同的屏幕尺寸, 多種屏幕分辨率, 以及在橫屏和豎屏模式下的各種高寬比.
雖然View有很多處理尺寸大小的方法, 但是大部分的需要重寫. 如果你的視圖不需要特別控制它的大小, 你只需要重寫方法: onSizeChanged() .
onSizeChanged()在你的視圖第一次分配大小的時候調用, 如果你的視圖因為任何原因改變了大小也會再次調用. 在該方法里計算位置、大小和其他一些與視圖大小相關的值, 而不是你每次繪制的時候重新計算. 在PieChart(餅圖)例子里, PieChar視圖在onSizeChanged()里計算餅圖的圖形邊界、文本標簽的相對位置和其他視覺元素.
當你的視圖分配了一個大小, 布局管理器會假設這個大小包含了所有視圖的padding值. 你必須在計算你視圖的大小的時候處理padding值. 下面是PieChart.onSizeChanged()中處理這個的代碼片段:
| 123456789 10 11 12 | // Account for paddingfloat xpad = (float)(getPaddingLeft() + getPaddingRight());float ypad = (float)(getPaddingTop() + getPaddingBottom());// Account for the labelif (mShowText) xpad += mTextWidth;float ww = (float)w - xpad;float hh = (float)h - ypad;// Figure out how big we can make the pie.float diameter = Math.min(ww, hh); |
如果你需要出色的控制你視圖的布局參數, 實現int) onMeasure()方法. 這個方法的參數是View.MeasureSpec值, 這個會告訴你你的視圖的父元素想讓你的視圖有多大, 并且告訴你這個大小是否是最大值或只是一個建議. 作為優化, 這些值保存為整數的封裝類型, 你可以用View.MeasureSpec里的靜態方法解析每個整數里面的信息.
下面是實現int) onMeasure()的例子. 在這個實現里面, PieChart嘗試讓它的面積大小足以讓餅圖可以標簽一樣大:
| 123456789 10 11 12 13 | @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// Try for a width based on our minimumint minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();int w = resolveSizeAndState(minw, widthMeasureSpec, 1);// Whatever the width ends up being, ask for a height that would let the pie// get as big as it canint minh = MeasureSpec.getSize(w) - (int)mTextWidth + getPaddingBottom() + getPaddingTop();int h = resolveSizeAndState(MeasureSpec.getSize(w) - (int)mTextWidth, heightMeasureSpec, 0);setMeasuredDimension(w, h); } |
在這段代碼中有三個重點需要注意:
-
- 計算需要考慮視圖的padding. 如上所述, 這個是視圖的職責.
-
- 方法resolveSizeAndState()用來創建最終的寬和高. 這個方法通過比較視圖的期望大小返回一個合適的View.MeasureSpec值傳入int) onMeasure()
-
- onMeasure()方法沒有返回值. 相反, 這個方法通過調用int) setMeasureDismension()方法傳遞結果. 調用這個方法是強制的. 如果你省略這個,?View類會拋出runtime exception
繪圖
一旦你有了創建的對象和定義了測繪布局的代碼, 你可以實現方法onDraw()) . 每個視圖實現不同的onDraw()) , 但是這里有些大多數視圖常用的操作:
-
使用drawText()畫文本,?setTypeface())指定字體,?setColor())指定文本顏色
-
畫基本的形狀用drawRect()) 、drawOval()) 、drawArc()) . 不論改變圖形的填充樣式還是邊框樣式還是都修改, 都是調用setStyle())
-
繪制復雜的形狀用Path類. 通過給Path對象增加線條和曲線定義形狀, 然后使用drawPath())繪制形狀. 就像基本的形狀一樣,?Path可以設置填充樣式、邊框樣式、或者都設置, 都依靠setStyle())
-
定義漸變的填充樣式通過創建LinearGradient對象. 在要填充的形狀上通過調用setShader())使用LinearGradient對象
-
繪制位圖使用drawBitmap()) .
例如, 這是是畫PieChart的代碼. 它混合使用了文本、線條、圖形.
| 123456789 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | protected void onDraw(Canvas canvas) {super.onDraw(canvas);// Draw the shadowcanvas.drawOval(mShadowBounds,mShadowPaint);// Draw the label textcanvas.drawText(mData.get(mCurrentItem).mLabel, mTextX, mTextY, mTextPaint);// Draw the pie slicesfor (int i = 0; i < mData.size(); ++i) {Item it = mData.get(i);mPiePaint.setShader(it.mShader);canvas.drawArc(mBounds,360 - it.mEndAngle,it.mEndAngle - it.mStartAngle,true, mPiePaint);}// Draw the pointercanvas.drawLine(mTextX, mPointerY, mPointerX, mPointerY, mTextPaint);canvas.drawCircle(mPointerX, mPointerY, mPointerSize, mTextPaint); } |
轉載于:https://www.cnblogs.com/vus520/archive/2013/06/09/3129451.html
總結
以上是生活随笔為你收集整理的【eoe教程】Android中自定义视图的绘制方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SYSENTER、SYSEXIT—快速系
- 下一篇: C语言中的位操作(8)--根据指定掩码选