程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程解疑 >> android自定義 iew-有沒有Android中自定義布局的詳細教程!

android自定義 iew-有沒有Android中自定義布局的詳細教程!

編輯:編程解疑
有沒有Android中自定義布局的詳細教程!

有沒有Android中自定義布局的詳細教程!我想寫一個課程表布局,在網上找了幾個demo,但是裡面的自定義布局看不明白!

最佳回答:


Composite View
Composite views (也被稱為 compound views) 是眾多將多個view結合成為一個可重用UI組件的方法中最簡單的。這種方法的實現過程是這樣的:

繼承相關的內建的布局。
在構造函數裡面填充一個 merge 布局。
初始化成員變量並通過 findViewById()指向內部view。
添加自定義的API來查詢和更新view的狀態。
TweetCompositeViewcode 就是一個 composite view。它繼承於 RelativeLayout,並填充了 tweet_composite_layout.xmlcode 布局文件,最後向外界暴露了 update()方法來更新它在adaptercode裡面的狀態。

Custom Composite View
上面提到的TweetCompositeView 這種實現方式能滿足大部分的情況。但是碰到某些情況就不靈了。假設你現在想要減少子視圖的數量,讓布局元素的便利更加有效。

這個時候我們可以回過頭來看看,盡管 composite views 實現起來比較簡單,但是使用這些內建的布局還是有不少的開銷的——特別是 LinearLayout 和RelativeLayout這種比較復雜的容器。由於Android平台內建布局的實現,在一次布局元素遍歷中,系統需要處理許多布局的結合和子視圖的多次測量——LinearLayout的 layout_weight 的屬性就是常見例子。

因此你可以為你的app量身定做一套子視圖的計算和定位邏輯,這樣的話你就可以極大的優化你的UI了。這種做法就是我接下來要介紹的 custom composite view.

顧名思義,一個 custom composite view 就是一個重寫了onMeasure() 和onLayout() 方法的 composite view 。因此相比之前的composite view繼承了 RelativeLayout,現在我們需要更進一步——繼承更抽象的ViewGroup。

TweetLayoutViewcode 就是通過這種技術實現的。注意現在這個實現不像 TweetComposiveView 繼承了LinearLayout ,這也就避免了 layout_weightcode這個屬性的使用了。

這個大費周折的過程通過ViewGroup’s 的measureChildWithMargins() 方法和背後的 getChildMeasureSpec() 方法計算出了每個子視圖的 MeasureSpec 。

TweetLayoutView 不能正確地處理所有可能的 layout 組合但是它也不必這樣。我們肯定需要根據特定需求來優化我們的自定義布局,這種方式可以讓我們寫出簡單高效的布局代碼。

Flat Custom View
如你所見,custom composite views 可以簡單地通過使用ViewGroup 的API就可以實現了。大部分時候,這種實現是可以滿足我們的需求的。

然而我們想更進一步的話——優化我們應用中的關鍵部分UI,比如 ListViews ,ViewPager等等。如果我們把所有的 TweetLayoutView 子視圖合並成一個單一的自定義視圖然後統一管理會怎麼樣呢?這就是我們接下來要討論的 flat custom view——參看下面的圖片。

layouts

左邊為CUSTOM COMPOSITE VIEW ,右邊是FLAT CUSTOM VIEW

flat custom view 就是一個完全自定義的 view ,它完全負責內部的子視圖的計算,位置安排,繪制。所以它就直接繼承了View 而不是 ViewGroup。

如果你想找找現實生活中app是否存在這樣的例子,很簡單——開啟你手機“開發者模式”裡面的 “顯示布局邊界”選項,然後打開 Twitter, Gmail, 或者 Pocket這些app,它們在列表UI裡面都采用了 flat custom view。

使用 flat custom view最主要的好處就是可以極大地壓縮app 的視圖層級,進而可以進行更快的布局元素遍歷,最終可以減少內存占用。

Flat custom view 可以給你最大的自由,就好像你在一張白紙上面作畫。但是這樣的自由是有代價的:你不能使用已有的那些視圖元素了,比如 TextView 和 ImageView。沒錯,在 Canvas 上面描繪文本 的確很簡單,但要你實現 ellipsizing(就是對過長的文本截斷)呢?同樣, 在 Canvas 上面 描繪圖片確很簡單,但是如何縮放呢?這些限制同樣適用於touch events, accessibility, keyboard navigation等等。

所以使用flat custom view的底線就是:只將flat custom view應用於你的app的UI核心部分,其他的就直接依賴Android平台提供的view了。

TweetElementViewcode 就是 flat custom view。為了更容易的實現它,我創建了一個小小的自定義視圖框架叫做UIElement。你可以在 canvascode 這個包裡找到它。

UIElement 提供了和Android平台類似的 measure/layout API 。它包含了沒有圖像界面的 TextView 和 ImageView ,這兩個元素包含了幾個必需的特性——分別參看 TextElementcode 和ImageElementcode 。它還擁有自己的 inflatercode ,幫助從 布局資源文件code裡面實例化UIElement 。

注意: UIElement 還處於非常早期的開發階段,所以還有很多缺陷,不過將來隨著不斷的改進UIElement 可能會變得非常有用。

你可能覺得TweetElementView 的代碼看起來很簡單,這是因為實際代碼都在 TweetElementcode裡面——實際上TweetElementView 扮演托管的角色code。

TweetElement 裡面的布局代碼和TweetLayoutView‘非常類似,但是它使用 Picasso 請求圖片時卻不一樣code ,因為TweetElement 沒有使用ImageView。

Async Custom View
總所周知,Android UI 框架時單線程的 。 這樣的單線程會帶來一些限制。比如,你不能在主線程之外遍歷布局元素——然而這對復雜、動態的UI是很有益處的。

假如你的app 在一個ListView 中很布局比較復雜的條目(就像大多數社交app一樣),那麼你在滑動ListView 就很有可能出現跳幀的現象,因為ListView 需要為列表中即將出現的新內容計算它們的視圖大小code和布局code。同樣的問題也會出現在GridViews,ViewPagers等等。

如果我們可以在主線程之外的線程上面對那些還沒有出現的子視圖進行布局遍歷是不是就可以解決上面的問題了?也就是說,在子視圖上面調用 measure() 和layout() 方法都不會占用主線程的時間了。

所以 async custom view 就是一個允許子視圖布局遍歷過程發生在主線程之外的實驗,這個idea是受到Facebook的Paperteam async node framework 這個視頻激發所想到的。

既然我們在主線程之外永遠接觸不到Android平台的UI組件,因此我們需要一個API在不能直接接觸到這個視圖的前提下對這個視圖的內容進行測量、布局。這恰恰就是 UIElement 框架提供給我的功能。

AsyncTweetViewcode 就是一個 async custom view。它使用了一個線程安全的 AsyncTweetElementcode 工廠類code 來定義它的內容。具體過程是一個 Smoothie 子項加載器code 在一個後台線程上對暫時不可見的AsyncTweetElement 進行創建、預測量和緩存(在內存裡面,以便後來直接使用)。

當然在實現這個異步UI的過程中我還是妥協了一些,因為你不知道如何顯示任意高度的布局占位符。比如,當布局異步傳遞過來的時候你只能在後台線程對它們的大小進行一次更改。因此當一個 AsyncTweetView 就要顯示的時候卻無法在內存裡面找到合適的AsyncTweetElement ,這個時候框架就會強制在主線程上面創建一個AsyncTweetElement code。

還有,預先加載的邏輯和內存緩存過期時間設置都需要比較好的實現來保證在主線程盡可能多地利用內存裡面的緩存布局。比如,這個方案中使用 LRU 緩存code 就不是一個明智的選擇。

盡管還存在這些限制,但是使用 async custom view 的得到的初步結果還是很有前途的。當然我也會通過重構這個UIElement 框架和使用其他類別的UI在這個領域繼續探索。讓我們靜觀其變吧。

總結

在我們涉及到布局的時候,我們自定義的越深,我們能從Android平台所能獲得的依賴就越少。所以我們也要避免過早優化,只在確實能實實在在改善app質量和性能的區域進行完全的布局自定義。

這不是一個非黑即白的決定。在使用平台提供的UI元素和完全自定義的兩種極端之間還有很多方案——從簡單的composite views 到復雜的 async views。實際項目中,你可能會結合文中的幾種方案寫出優秀的app。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved