Android——自定義View

Android之自定義View

繼承特定View控件

這種自定義 View 在系統控件的基礎上進行拓展,一般是添加新的功能或者修改顯示的效果,一般情況下在onDraw()方法中進行處理。

我們寫一個自定義View,繼承自TextView:

在這裏插入圖片描述

  • 這個自定義View繼承了TextView,並且在onDraw()方法中畫了一條紅色的橫線。

繼承View

與上面的繼承系統控件的自定義View不同,繼承View的自定義View實現起來要稍微複雜一些。其不只是要實現onDraw()方法,而且在實現過程中還要考慮到wrap_content屬性以及padding 屬性的設置;爲了方便配置自己的自定義 View,還會對外提供自定義的屬性。另外,如果要改變觸控的邏輯,還要重寫 onTouchEvent()等觸控事件的方法。按照上面的例子我們再寫一個RectView類繼承View來畫一個正方形,代碼如下所示。

在這裏插入圖片描述

在這裏插入圖片描述
效果如下:
在這裏插入圖片描述

處理padding

只需要在onDraw()方法中稍加修改,在繪製正方形的時候考慮padding屬性即可,代碼如下所示:

在這裏插入圖片描述
運行後效果
在這裏插入圖片描述

處理wrap_content屬性

爲何會產生這種情況,詳細內容參考View的工作流程。

這種情況需要我們在onMeasure方法中指定一個默認的寬和高,在設置wrap_content屬性時設置此默認的寬和高就可以了:

在這裏插入圖片描述

自定義屬性

首先在values目錄下創建 attrs.xml:
在這裏插入圖片描述
這個配置文件定義了名爲RectView的自定義屬性組合。我們定義了rect_color屬性,它的格式爲color。接下來在RectView的構造方法中解析自定義屬性的值,如下所示:
在這裏插入圖片描述
用 TypedArray 來獲取自定義的屬性集 R.styleable.RectView,這個 RectView 就是我們在XML中定義的name的值,然後通過TypedArray的getColor方法來獲取自定義的屬性值。

View滑動衝突

在界面中只要內外兩層同時可以滑動,這個時候就會產生滑動衝突。

常見的滑動衝突

  • 場景一: 外部滑動方向和內部方向不一致
  • 場景二:外部滑動方向和內部滑動方向一致
  • 場景三:上面兩種情況的嵌套

先說場景1,主要是將ViewPager和Fragment配合使用所組成的頁面滑動效果,
主流應用幾乎都會使用這個效果。在這種效果中,可以通過左右滑動來切換頁面,而
每個頁面內部往往又是一個ListView. 本來這種情況下是有滑動衝突的,但是
ViewPager內部處理了這種滑動衝突,因此採用ViewPager時我們無須關注這個問題,
如果我們採用的不是ViewPager而是ScrolIView等,那就必須手動處理滑動衝突了,
否則造成的後果就是內外兩層只能有一層能夠滑動,這是因爲兩者之間的滑動事件有衝突。除了這種典型情況外,還存在其他情況,比如外部上下滑動、內部左右滑動等,
但是它們屬於同一類滑動衝突。

再說場景2,這種情況就稍微複雜些, 當內外兩層都在同一個方向可以滑動的時候,
顯然存在邏輯問題。因爲當手指開始滑動的時候,系統無法知道用戶到底是想讓哪- -層滑
動,所以當手指滑動的時候就會出現問題,要麼只有一層能滑動,要麼就是內外兩層都滑
動得很卡頓。在實際的開發中,這種場景主要是指內外兩層同時能上下滑動或者內外兩層
同時能左右滑動。

最後說下場景3,場景3是場景1和場景2兩種情況的嵌套,因此場景3的滑動衝突
看起來就更加複雜了。比如在許多應用中會有這麼一個效果:內層有一個場景1中的滑動
效果,然後外層又有一個場景2中的滑動效果。具體說就是,外部有一個SlideMenu效果,
然後內部有一個ViewPager, ViewPager 的每-一個 頁面中又是一個ListView。雖然說場景3
的滑動衝突看起來更復雜,但是它是幾個單- -的滑動衝突的疊加,因此只需要分別處理內
層和中層、中層和外層之間的滑動衝突即可,而具體的處理方法其實是和場景1.場景2
相同的。

處理規則

對於場景1,它的處理規則是:當用戶左右滑動時,需要讓外部的View
攔截點擊事件,當用戶上下滑動時,需要讓內部View攔截點擊事件。這個時候我們就可以
根據它們的特徵來解決滑動衝突,具體來說是:根據滑動是水平滑動還是豎直滑動來判斷
到底由誰來攔截事件,如圖,根據滑動過程中兩個點之間的座標就可以得出到底
是水平滑動還是豎直滑動。如何根據座標來得到滑動的方向呢?這個很簡單,有很多可以
參考,比如可以依據滑動路徑和水平方向所形成的夾角,也可以依據水平方向和豎直方向
上的距離差來判斷,某些特殊時候還可以依據水平和豎直方向的速度差來做判斷。這裏我
們可以通過水平和豎直方向的距離差來判斷,比如豎直方向滑動的距離大就判斷爲豎直滑
動,否則判斷爲水平滑動。根據這個規則就可以進行下-步的解決方法制定了。

在這裏插入圖片描述
對於場景2來說,比較特殊,它無法根據滑動的角度、距離差以及速度差來做判斷,
但是這個時候- -般 都能在業務上找到突破點,比如業務上有規定:當處於某種狀態時需要
外部Vicw響應用戶的滑動,而處於另外種狀態時則需 要內部View來響應View的滑動,
根據這種業務上的需求我們也能得出相應的處理規則,有了處理規則同樣可以進行下一步
處理。

對於場景3來說,它的滑動規則就更復雜了,和場景2一樣,它也無法直接根據滑動
的角度、距離差以及速度差來做判斷,同樣還是隻能從業務上找到突破點,具體方法和場
景2一樣,都是從業務的需求上得出相應的處理規則。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章