android自定義控制項組合
1. 如何系統的學習android自定義各種酷炫控制項
首先,為什麼需要自定義View?
1. 現有的View滿足不了你的需求,也沒有辦法從已有控制項派生一個出來;界面元素需要自己繪制。
2. 現有View可以滿足要求,把它做成自定義View只是為了抽象:為這個自定義View提供若干方法,方便調用著操縱View。通常做法是派生一個已有View,或者結合xml文件直接inflate。
目前常用的基本上是第二種方式,這種方式非常簡單,與通常的View使用方法基本相同,但是作用卻異常強大,擁有了這一層抽象,代碼更加整潔也更容易維護,通過抽取自定義View的公共操作方法也減少了冗餘代碼,雖然簡單,但不可忽視。
大多數人感覺神秘的應該是第一種,自繪控制項,完全自定義;但其實這兩種方式歸根結底全部都是自繪;不信你去看看TextView的源碼。只不過通常情況下系統幫我們繪制好了一些控制項給開發者使用;OK,接下來就是一個問題。
在講述之前我還是啰嗦地重申一下,復用已有View是最最常用也最有效的自定義View方式,必須熟練使用。
其次,如何自定義View?
想一下,一個View給用戶最直觀的感知是什麼?靜止的形態和動態的操作。靜止的形態意思就是一個View呈現到用戶眼裡長成啥樣子?動態操作指的是,用戶與View之間可以有哪些交互?點擊滑動View的不同地方會有什麼反應?
1. 靜態
如果一個自定義View的樣式都沒有辦法繪制出來,那麼後續的交互就是空談了;我們一步步分解這個問題。
1.1 你的自定義View分為哪幾個部分?是所有的部分都需要手動繪制還是只有一部分——找出需要完全自定義的部分,其他的部分用已有View實現。
1.2 你的自定義View的每個部分長成什麼樣,佔用多大空間——結合理論知識View的measure過程,比如match_parent, wrap_content結合父View的laout_params參數最終測量大小是多少?
1.3 你的自定義View每個部分擺放在哪?相對位置如何?——View的layout過程。
1.4 你的自定義View那些完全需要手動繪制的部分是什麼樣,如何繪制?
你得學會操縱Canvas,學會2D繪圖,什麼?你跟我說3D,OpenGL?學會這些再說。
2. Android 自定義控制項 layout
Android 繪制流程
View :View主要執行layout方法,使用 serFrame 方法來設置本身 View 的四個頂點的位置,確定View本身的位置。
ViewGroup :ViewGroup主要執行onLayout方法,遞歸遍歷所有子View,確定子View的位置。
我們來看ViewRootImpl中的 performLayout() 方法
看到這里,那host.getMeasuredWidth() / host.getMeasuredHeight()是什麼?它是直接調用View中的方法,其實就是經過measure後的DecorView的測量寬度和高度。在 Android 自定義控制項 measure 中有說明。
2.3.2.1 我們先來看ViewGroup中的 layout() 方法
ViewGroup裡面的layout最終會調入到父類View中的layout,View的layout後面講解。這里可以先告訴大家,最終會調用View的onLayout方法,而ViewGroup的onLayout是抽象方法,所以它的子類LinearLayout必須要實現。
2.3.2.2 我們再來看LinearLayout中的 onLayout() 方法。
2.3.2.3 挑一個縱向的吧,我們再來看LinearLayout中的 layoutVertical() 方法。
2.3.2.4 我們再來看LinearLayout中的 setChildFrame() 方法。
又一次回到了View的layout方法,接下來就看View分發的layout。
我們先來看View中的 layout() 方法。
我們先來看View中的 onLayout() 方法。
空空如也,其實View的布局由父容器決定,所以空實現是正常的,當然也可以在自定義View中進行更改。
《Android 視圖模塊 全家桶》
Android開發之自定義控制項(二)---onLayout詳解
自定義View Layout過程 - 最易懂的自定義View原理系列(3)
3. android自定義listview控制項,動態添加item,並對item進行操作
這是最基本的listView啊。把BaseAdapter弄明白就可以實現了。
4. Android自定義控制項之可平移、縮放、旋轉圖片控制項
先上效果圖
源碼
單點拖動圖片對圖片進行平移操作。雙手縮放圖片大小和旋轉圖片到一定的角度。圖片縮放的時候 不能大於最大的縮放因子和小於最小的縮放因子。大於最大縮放因子或者小於最小縮放因子需要對圖像進行回彈。圖片旋轉的角度只能為90度的倍數,不滿足90度要進行回彈。圖片回彈要一個漸變的效果。
大體思路: 首先,Android中提供了Matrix類可以對圖像進行處理。其次,要顯示一張圖片最容易想到的就是ImageView。回彈要求漸變的過程,可以通過屬性動畫進行設置。所以大體的思路是:繼承ImageView,重寫onTouchEvent()方法,判斷事件類型,在對應的事件使用Matrix對圖像進行變換。
Matrix是一個已經封裝好的矩陣,最重要的作用就是對坐標點進行變換。
舉個栗子:
1.某個點(x0,y0,1)通過單位矩陣E映射得到的點還是(x0,y0,1)。
3.點(x0,y0,1)通過矩陣T映射得到的點就會做如下的變換
可以看到點(x0,y0,1)經過T矩陣在x軸方向上平移了dx,在y軸方向上平移了dy。
通過以上的變換可以得到具體的思路: 我們維護一個圖像對應的矩陣mCurrentMatrix,該矩陣主要是對ImageView中的圖像的各個點進行映射。ImageView在容器位置擺放完成之後,置mCurrentMatrix矩陣為單位矩陣。當onTouchEvent()方法中觸發單點觸控並且手指進行平移的時候,調用矩陣mCurrentMatrix的postTranslate(dx,dy),對mCurrentMatrix進行變換。當手指抬起,利用變換結束後的矩陣對圖像的各個點進行映射,從而得到平移變換後的圖像。同理可得,在兩只手指進行縮放旋轉的時候,我們對矩陣mCurrentMatrix進行各種變換,當縮放旋轉的事件結束再利用變換完的矩陣去映射圖像的各個點,從而得到縮放、旋轉後的圖像。
安卓自定義View進階 - Matrix原理
安卓自定義View進階 - Matrix詳解
首先理清事件的邏輯:
初始化圖像大小和位置
縮放圖像大小和控制項大小自適應,平移圖像中心和控制項中心重合
onTouchEvent()函數
平移操作
將圖像對應的矩陣進行變換。
縮放操作
mBoundRectF為記錄圖像邊界的矩形。縮放的時候選取圖像的中心進行縮放。
旋轉操作
旋轉的時候旋轉的旋轉中心也是圖像的中心
圖像中各個點的映射
調用ImageView的setImageMatrix(Matrix matrix)會讓ImageView根據設置的matrix去重新繪制圖像。
更新圖像的矩形邊界
獲得圖像的矩形,並根據矩陣映射矩形各個點的坐標。
縮放回彈
旋轉回彈
一些計算方法
要求圖像的變換是一個漸變的過程,很容易想到的就是屬性動畫。因為屬性動畫本身就是對值進行不斷set的過程。而我們維護的矩陣也是一個值,所以很自然可以想到,如果得到回彈之前的矩陣的值以及回彈之後矩陣的值,就可以根據動畫監聽器中動畫當前的系數值去改變矩陣的值。
對animator對象設置完監聽器之後,就可以在手指抬起的時候調用屬性動畫的start()方法開啟動畫。
自定義可平移、縮放、旋轉的控制項主要點有兩個方面:一是onTouchEvent()中判斷平移、旋轉、縮放的觸發條件,平移位移量、縮放比例因子、旋轉角度的計算。二是Matrix矩陣的應用。