自定义View时,用到Paint Canvas的一些温故,讲讲平时一些效果是怎么画的(基础篇 一)...
轉載請注明出處王亟亟的大牛之路
之前也有一個類似于畫板的操作,但是不夠詳細,這邊先補上鏈接,有興趣的小伙伴可以看看http://blog.csdn.net/ddwhan0123/article/details/48804761
還是老規(guī)矩,將內容之前說下我們的一些知識點,今天的第一個知識點有點高DA上的名詞“硬件加速”。
硬件加速:
問題1:這玩意有什么用?
在繪制View的時候支持硬件加速,充分利用GPU的特性,使得繪制更加平滑。
問題2:怎么用?
在AndroidManifest的Application 或者Activity節(jié)點<application android:hardwareAccelerated="true/false">就可以進行開關。或者用Java代碼:getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
如果這些你都不喜歡,你只要那個類當中的某個View是對這部分功能有需求的,那么這樣:view.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 但是要記住Window只能打開,View只能關閉所以還是在Activity和Application層面操作吧。
問題3:非用不可嗎?
如果你的View的繪制內容比較復雜,比較對多,還是建議開著,諸如畫密度很細的那種虛線或者顏色區(qū)域草雞付擦的一些試圖的畫還是開著吧,不然說不定你再掛個什么網(wǎng)絡的操作萬一客戶機爛一點一個未響應提示就來了。
Paint:
這部分的內容就不提了,網(wǎng)上多如牛毛,貼一個寫的比較簡單易通的http://www.cnblogs.com/tianzhijiexian/p/4297170.html?utm_source=tuicool&utm_medium=referral
http://www.kancloud.cn/kancloud/android-tutorial/87246
Canvas:
如上,還是附上可參考的鏈接:http://blog.sina.com.cn/s/blog_61ef49250100qw9x.html
http://www.kancloud.cn/kancloud/android-tutorial/87261
性能優(yōu)化(跟自定義繪圖相關的):
1.設置緩存:View 中設置緩存屬性.setDrawingCache為true
2.優(yōu)化布局:tools目錄下的layoutopt 命令
3.將Acitivity 中的Window 的背景圖設置為空(默認不為空)。getWindow().setBackgroundDrawable(null);
4.采用SurfaceView在子線程刷新UI,:避免手勢的處理和繪制在同一UI線程(普通View都這樣做)。
5:采用JNI:將耗時間的處理放到c/c++層來處理。
主要來說下自定義控件重要的三個方法“onMeasure()”,“onDraw()”,“onLayout()”:
1.onMeasure()方法就是用于測量視圖的大小的,不然你的空間永遠都只是白屏,不是沒畫上去,而是沒有尺寸。
measure()方法接收兩個參數(shù),widthMeasureSpec和heightMeasureSpec也就是寬度和長度。
MeasureSpec的值由specSize和specMode共同組成的,specSize是大小,specMode是規(guī)格。
有三種規(guī)格:1. EXACTLY,AT_MOST,UNSPECIFIED。這三種規(guī)格細說太復雜了,我整合給大家聽下
(1):子視圖的大小應該是由specSize的值來決定,用戶也可自行定義
(2):子視圖最多只能是specSize中指定的大小,只能更小不能更大了
(3):可以將視圖按照自己的意愿設置成任意的大小,沒有任何限制
當rootDimension參數(shù)等于MATCH_PARENT的時候,MeasureSpec的specMode就等于EXACTLY,當rootDimension等于WRAP_CONTENT的時候,MeasureSpec的specMode就等于AT_MOST。并且MATCH_PARENT和WRAP_CONTENT時的specSize都是等于windowSize的,也就意味著根視圖總是會充滿全屏的。
這里的rootDimension是根布局的尺寸
總結:視圖大小的控制是由父視圖、布局文件、以及視圖本身共同完成的,父視圖會提供給子視圖參考的大小,而開發(fā)人員可以在XML文件中指定視圖的大小,然后視圖本身會對最終的大小進行拍板。
不然就會出現(xiàn)onCreate時發(fā)現(xiàn)控件寬高都是0,之前有提到,看這里http://blog.csdn.net/ddwhan0123/article/details/50386685
2.onLayout()用于給視圖進行布局的,也就是確定視圖的位置,會在onMeasure方法之后執(zhí)行。
layout()方法接收四個參數(shù),分別代表著左、上、右、下的坐標,當然這個坐標是相對于當前視圖的父視圖而言的。
像這樣layout(0, 0, host.mMeasuredWidth, host.mMeasuredHeight);
但是繪圖的位置操作我們可以在onDraw里執(zhí)行,所以如果你不想了解這部分,這方法你不調用都行,但是要記得在畫的時候重現(xiàn)位置特性,不然就是“一坨屎在一起了”
3.onDraw(),measure和layout的過程都結束后,接下來就進入到這個方法了。我們所有的作畫的事,都在這干!
ViewRoot中的代碼會繼續(xù)執(zhí)行并創(chuàng)建出一個Canvas對象,然后調用View的draw()方法來執(zhí)行具體的繪制工作
我們的繪畫都是在這個Canvas對象的支持下實現(xiàn)的,簡單寫個例子。
public class TestView extends View {Paint paint;Context context;public TestView(Context context) {super(context);this.context = context;}public TestView(Context context, AttributeSet attrs) {super(context, attrs);init(context, attrs);}public TestView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}@TargetApi(Build.VERSION_CODES.LOLLIPOP)public TestView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);init(context, attrs);}private void init(Context context, AttributeSet attrs) {paint = new Paint(); // paint.setColor(getResources().getColor(R.color.SlateBlue));paint.setColor(getResources().getColor(R.color.Gold));paint.setStrokeWidth(3);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Log.d("--->onDraw", "onDraw()"); // canvas.drawCircle(0, 0, 90, paint);canvas.drawCircle(100, 100, 90, paint);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);Log.d("--->onLayout", "changed = " + changed + " left = " + left + " top = " + top + " right = " + right + " bottom " + bottom);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);Log.d("--->onMeasure", " widthMeasureSpec =" + widthMeasureSpec + " heightMeasureSpec = " + heightMeasureSpec);setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);} }注釋部分運行效果:
現(xiàn)有代碼效果:
打印的順序
請仔細看onLayout()的那些坐標,他任然保持著父布局的一系列屬性參數(shù):
android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"相關資源收集:http://blog.csdn.net/michaelcao1980/article/details/43233909
總結
以上是生活随笔為你收集整理的自定义View时,用到Paint Canvas的一些温故,讲讲平时一些效果是怎么画的(基础篇 一)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#面向对象设计模式纵横谈——6.Pro
- 下一篇: Session问题