編輯:Android開發教程
技術是永無止境的,如果真的愛技術,那就勇敢的堅持下去。我很喜歡這句話,當我在遇到問題的時候、當我覺得代碼枯燥的時候,我就會問自己,到底是不是真的熱愛技術,這個時候,我心裡總是起著波瀾,我的答案是肯定的,我深深的愛著這門技術。
今天我們繼續聊聊Android的自定義View系列。先看看效果吧:
這個是我手機殺毒軟件的一個動畫效果,類似於雷達搜索,所以用途還是很廣泛的,特別是先了解一下這裡的具體邏輯和寫法,對技術的進步一定很有用。
先簡單的分析一下這裡的元素,主要有四個圓、一個扇形、還有八條虛線。當知道這些以後,代碼就可以開始寫了。
先看看這裡用到了哪些變量。
mWidth; mHeight; Paint mPaint, mPaint2, mPaint3, mPaint4, mLinePaint; RectF mRectF; startAngle = ; radius1, radius2, radius3, radius4; Path path;
不是很多,有畫筆6個,然後是寬與高,還有就是角度以及四個圓的半徑以及一個矩形、當然還有繪制虛線的Path類。接下來是初始化的操作。
// 初始化畫筆操作 private void initData() { mPaint = new Paint() mPaint() mPaint(true) mPaint(Style) mPaint(Color()) mPaint2 = new Paint() mPaint2() mPaint2(Color()) mPaint3 = new Paint() mPaint3() mPaint3(true) mPaint3(Style) mPaint3(Color()) mPaint4 = new Paint() mPaint4() mPaint4(true) mPaint4(Style) mPaint4(Color()) mLinePaint = new Paint(Paint_ALIAS_FLAG) mLinePaint() mLinePaint(Paint) mLinePaint(true) mLinePaint(Color()) path = new Path() }
這裡包括了五個畫筆的初始化操作、一個路徑的初始化操作。注意每個畫筆的具體樣式是不一樣的,這樣方便實現不同的效果。
初始化的操作完了之後,就是給變量賦值了,還是一樣的,我們選擇在onSizeChange()裡面對變量進行賦值。代碼如下:
( w, h, oldw, oldh) { .onSizeChanged(w, h, oldw, oldh); mWidth = getWidth(); mHeight = getHeight(); mRectF = RectF(() (mWidth * ), () (mWidth * ), () (mWidth * ), () (mWidth * )); LinearGradient gradient = LinearGradient(() (mWidth * ), () (mWidth * ), () (mWidth * ), () (mWidth * ), [] { Color.parseColor(), Color.GREEN, Color.parseColor(), Color.WHITE, Color.parseColor() }, , Shader.TileMode.CLAMP); mPaint2.setShader(gradient); radius1 = () (mWidth * ); radius2 = () (mWidth * ); radius3 = () (mWidth * ); radius4 = () (mWidth * ); }
其實很明顯啊,我們在前面講的幾個自定義的View中,幾乎所有的變量初值都是在這個方法裡面寫的,這個方法究竟有什麼特點呢?其實這個是系統回調方法,是系統調用的,它的方法名已經告訴我們了,這個方法會在這個view的大小發生改變是被系統調用,我們要記住的就是view大小變化,這個方法就被執行就可以了。最主要的是,它還在onDraw方法之前調用。
還記得之前的效果嗎?裡面有一個漸變,這個漸變就是代碼裡LinearGradient 類的操作結果了,具體的用法,我在後面會專門去解釋它。
到了這裡,基本上所有的准備工作都完成了,接下來進行真真的繪圖。
先看看onDraw方法裡面做的操作:
protected void onDraw(Canvas ) { super.onDraw(); canvasArc(); canvasArc2(); canvasCircle(); canvasLine(); }
這裡有畫圓的,有畫扇形的,也有畫線的,所以可以發現,我們所有看到的效果,都是在onDraw方法裡面實現的。我們具體看看每一個方法:
第一個繪制扇形:
(Canvas canvas) { canvas.drawArc(mRectF, startAngle, , , mPaint2); }
只有兩行代碼,也很容易理解,那麼第二個扇形也是差不多:
(Canvas canvas) { canvas.drawArc(mRectF, startAngle, , , mPaint3); }
值得注意的是,第二個的扇形的角度是1,為什麼是1呢,原來我這裡只是想要它旋轉角度的效果,並不需要它有多寬,所以在具體實現自定義View的時候,也要學會活學活用。
兩個扇形已經畫好了,那就看看四個圓怎麼畫:
private void canvasCircle(Canvas ) { .drawCircle(mWidth / , mHeight / , radius1, mPaint3); .drawCircle(mWidth / , mHeight / , radius2, mPaint); .drawCircle(mWidth / , mHeight / , radius3, mPaint); .drawCircle(mWidth / , mHeight / , radius4, mPaint4); }
四個圓就是四行代碼,怎麼樣,很簡單吧?
注意他們所用的畫筆是不太一樣的,這裡是比較容易忽視的地方。
最後來看看我糾結很久的畫虛線的操作,這裡真是把我卡了好一會兒,先看看代碼:
(Canvas canvas) { lineCount = ; ( i = ; i < lineCount; i++) { path.moveTo(mWidth / , mHeight / ); path.lineTo(radius1, radius4); PathEffect effects = DashPathEffect( [] { () (mWidth * ), () (mWidth * ), () (mWidth * ), () (mWidth * ) }, ); mLinePaint.setPathEffect(effects); canvas.drawPath(path, mLinePaint); canvas.rotate(, mWidth / , mHeight / ); } }
按理說,繪制虛線,本質也是畫線,但是我一開始是用canvas.drawLine方法,但是沒有效果,網上查找了資料,才知道可能是版本的問題,於是我換用了path。
到了這個時候,全部效果已經出來了,那麼為了讓她動起來,我們還是要加點邏輯,我的思路是這樣的:
定義一個線程,然後通過改變扇形的開始角度來實現動畫的效果。
代碼如下:
{ @Override run() { () { (running) { SystemClock.sleep(); handler.sendEmptyMessage(); } } } } running = ; Handler handler = Handler() { handleMessage(android.os.Message msg) { synchronized () { (startAngle < ) { startAngle = ; } { startAngle--; invalidate(); } } }; };
使用TimePicker,可以讓用戶去選擇一天中的事件,包括24小時制和AM/PM制。下面的例子將會展示如何 使用TimePicker。1. 創建一個工程:BasicVi
本文中如果直接安裝時不出現錯誤,則可以忽略(一、二、三、四、五),我安裝的是5.1.1,直接成功,就是有點慢,要有耐心。如果到最後一步,啟動不起來,報錯:emulator
Toast通知是Android中最簡單的消息通知。接下來展示如何使用吐司通知。1. 新建一個工程, Toast。2. main.xml中的代碼。<RelativeL
變態問題常有,今年特別多,,, - - # 今天遇到的這個非處理不可,不然沒法在HTC One S使用SearchView,其軟鍵盤不支持action設置。問題設備:HT