Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android的Kotlin秘方(I):OnGlobalLayoutListener,

Android的Kotlin秘方(I):OnGlobalLayoutListener,

編輯:關於android開發

Android的Kotlin秘方(I):OnGlobalLayoutListener,


春節後,又重新“開張”。各位高手請繼續支持。謝謝!

 

 

原文標題:Kotlin recipes for Android (I): OnGlobalLayoutListener

原文鏈接:http://antonioleiva.com/kotlin-ongloballayoutlistener/

原文作者:Antonio Leiva(http://antonioleiva.com/about/)

原文發布:2016-03-16 ­

 

Android的Kotlin秘方(I):OnGlobalLayoutListener

 

今天一位同伴問我怎樣恰當使用OnGlobalLayoutListener,而不需要太多的模板。這是一個棘手的問題,我們需要進一步深入研究。

 

OnGlobalLayoutListener是干什麼的?

這個偵聽器對於任何試圖的ViewTreeObserver都適用,並且在已知視圖寬度和高度進行各種計算、動畫等等時,為擴展和測量視圖常常回調它。

 

幸虧Kotlin提供很好的與Java互操作性,我們能夠以一種非常清晰的方法 —— 使用它的模擬屬性和Lambda表達式 —— 實現單一方法接口:

1 recycler.viewTreeObserver.addOnGlobalLayoutListener {
2     // do whatever
3 }

這裡有什麼問題嗎?為了預防洩漏,推薦的實踐是在完成使用它後,立即刪除這個偵聽器。但是由於使用了Lambda表達式,Lambda沒有對象那麼精確,我們沒有對象的引用。

 

原方式還是可以用,但是在Kotlin中直接用匿名對象,每次都會有一只小貓死去。如果仍然需要做下面這樣的事,沒法改用更好開發語言:

1 recycler.viewTreeObserver.addOnGlobalLayoutListener(
2         object : ViewTreeObserver.OnGlobalLayoutListener {
3             override fun onGlobalLayout() {
4                 recycler.viewTreeObserver.removeOnGlobalLayoutListener(this);
5                 // do whatever
6             }
7         });

 

找一個更佳替換方法

好了,既已知不要那樣做。那麼有什麼更好的方法嗎?我們被迫使用一種看上去沒有那麼好看的方法,但是可能是一種好的選擇,將擴展函數隱藏起來。

 

為視圖接收另一個函數創建一個新函數,由它自己創建和刪除偵聽器。就像這樣:

1 inline fun View.waitForLayout(crossinline f: () -> Unit) = with(viewTreeObserver) {
2     addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
3         override fun onGlobalLayout() {
4             removeOnGlobalLayoutListener(this)
5             f()
6         }
7     })
8 }

 

現在你就可以調用這個函數,確保其自己添加和刪除偵聽器。除非,你永遠不會忘記刪除:

1 recycler.waitForLayout { 
2     // do whatever
3 }

 

如果喜歡,可以用擴展ViewTreeObserver的函數,而不是直接用View。這取決你。

 

但是我們仍可以改進它

這是在測試視圖後布局偵聽器通常要做的一些事,所以需要等待寬度和高度大於0。而且可能要在視圖中調用它時做一些事,這為什麼不能轉換參數函數到擴展函數

 

我還泛型該函數使它能夠在任何繼承View的對象中使用,也能夠從編寫的函數中訪問所有它的指定函數和屬性。

 1 inline fun <T: View> T.afterMeasured(crossinline f: T.() -> Unit) {
 2     viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
 3             override fun onGlobalLayout() {
 4                 if (measuredWidth > 0 && measuredHeight > 0) {
 5                    viewTreeObserver.removeOnGlobalLayoutListener(this)
 6                    f()
 7                 }
 8             }
 9        })
10 }

 

這個afterMeasured函數非常類似前者,但是在Lambda表達式內直接用視圖的屬性和public方法。例如,我們能夠得到recycler的寬度和基於它用列的動態數組設置布局。

1 recycler.afterMeasured {
2     val columnCount = width / columnWidth
3     layoutManager = GridLayoutManager(context, columnCount)
4 }

總結

在Android中運行時,這確實仍有些事情做的不是很好,即使是移植Kotlin,但是總是可以通過隱藏在其他結構背後的不確定因素,找到提升可讀性和避免不確定因素的選擇。至少,僅需要編寫一次,而其它代碼則非常漂亮!

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved