每日一問:詳細說一下 MeasureSpec.UNSPECIFIED


詳細說一下 MeasureSpec.UNSPECIFIED

前面的文章 我留下了一個疑惑,那就是到底為什么 NestedScrollView 要把子 View 的測量模式強行設置為 MeasureSpec.UNSPECIFIED ,這不,在鴻洋的 "wanAndroid" 中,他再次提出了這樣的問題:

MesureSpec.UNSPECIFIED

  1. 這個模式什么時候會遇到?
  2. 遇到后怎么處理?
  3. 有什么注意事項?

下面摘自用戶「陳小緣啦啦啦」的回答,我覺得回答的非常到位,特別在這里和大家分享一下。

UNSPECIFID,就是未指定的意思,在這個模式下父控件不會干涉子 View 想要多大的尺寸。
那么,這個模式什么時候會onMeasure() 里遇到呢?其實是取決於它的父容器。
就拿最常用的 RecyclerView 做例子,在 Item 進行 measure() 時,如果列表可滾動,並且 Item 的寬或高設置了 wrap_content 的話,那么接下來,itemView 的 onMeasure( )方法的測量模式就會變成 MeasureSpec.UNSPECIFIED
我們不妨打開 RecyclerView 源碼,會在 getChildMeasureSpec() 方法里看到這么一句注釋:

MATCH_PARENT can't be applied since we can scroll in this dimension, wrap instead using UNSPECIFIED.

它想表達的是:在可滾動的ViewGroup中,不應該限制 Item 的尺寸(如果是水平滾動,就不限制寬度),為什么呢? 因為是可以滾動的,就算 Item 有多寬,有多高,通過滾動也一樣能看到滾動前被遮擋的部分。

這里其實也就回答了我之前詢問的 NestedScrollView 要強行設置 Item 為 UNSPECIFIED 的原因。
有同學可能會有疑問: 我設置 wrap_content,在 onMeasure() 中應該收到的是 AT_MOST 才對啊,為什么要強制變成 UNSPECIFIED

這是因為考慮到 Item 的尺寸有可能超出這個可滾動的 ViewGroup 的尺寸,而在 AT_MOST 模式下,你的尺寸不能超出你所在的 ViewGroup 的尺寸,最多只能等於,所以用 UNSPECIFIED會更合適,這個模式下你想要多大就多大。

那么,我們在自定義 View 的時候,在測量時發現是 UNSPECIFIED 模式時,應該怎么做呢?

這個就比較自由了,既然尺寸由自己決定,那么我可以寫死為 50,也可以固定為 200。但還是建議結合實際需求來定義咯。

比如 ImageView,它的做法就是:有設置圖片內容(drawable)的話,會直接使用這個 drawable 的尺寸,但不會超過指定的 MaxWidthMaxHeight, 沒有內容的話就是 0。而 TextView 處理 UNSPECIFIED 的方式,和 AT_MOST 是一樣的。

當然了,這些尺寸都不一定等於最后 layout 出來的尺寸,因為最后決定子 View 位置和大小的,是在 onLayout() 方法中,在這里你完全可以無視這些尺寸,去 layout()成自己想要的樣子。不過,一般不會這么做。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM