原文:ConstraintLayout basics guidelines 作者:Mark Allison
有時候,我們需要創(chuàng)建一些固定方向比的 View 組件,最常使用固定橫縱比的就是當 ImageView
用于展示一些固定橫縱比的圖片的時候。舉些例子,書面封面(尺寸橫縱比多種多樣),電影海報(一般是 4:6 ),電影劇照(一般是 1.85:1 或 2.39:1 ),電視?。ㄒ话闶?4:3 或 16:9 )
對于不熟悉什么是橫縱比的,橫縱比就是表示了 View 的寬度與高度的比例 w:h
。例如,對于一個擁有橫縱比為 4:6
擁有寬度為 40dp
的 View 組件有著高度是 60dp
,若它的寬度改為 30dp
則它的高度就是 45dp
。
若我們現(xiàn)實的圖片能保證同樣的橫縱比和像素大小,我們可以簡單的在兩個方向上使用 wrap_content
即可。然而,現(xiàn)實情況由于數(shù)學四舍五入等多種原因都有可能造成實際現(xiàn)實的一些小誤差。如果只是現(xiàn)實一個圖片可能不會有多大問題,但是如果多個圖片展示的時候小問題也會被有很不好的視覺效果,甚至當有 View 對齊于這些圖片的 ImageView 的時候,也因此產(chǎn)生了變化,整體就會造成布局不平衡混亂了。
對于這個問題的解決方案之一是,通過創(chuàng)建繼承于 ImageView
的子類,并通過覆寫 onMeasure()
來實現(xiàn)固定橫縱比的布局。常用的 support library 中的 PercentLayout
也提供了一些機制來結(jié)局這類橫縱比問題。
同樣的 ConstraintLayout
也提供了機制來專門解決這個問題,選擇想要控制橫縱比的 View 然后通過屬性視圖中修改 ratio
值來改變橫縱比,如下圖紅色圈內(nèi)設置:
如上圖,我們設置的 View 組件有著向父組件的 start 和 top 邊緣的約束,它的 end 邊緣則約束向一條參考線,而 bottom 邊緣則沒有被約束,這個 View 的 layout_width
和 layout_height
都被設置成 match_constraint
,表示他們會根據(jù)所有的約束來設置寬高。在布局階段這個組件的寬度就被計算好了,但是它的高度好像沒有被確定。然后,因為設置了寬高橫縱比,高度其實也被確定了,只是寬度的一個函數(shù)輸出值(在以上例子中橫縱比是 16:9 )
這樣設置的好處就是,當寬度變化的時候,高度自動跟著變化,如下圖通過移動這個 View 組件 end 邊緣約束向的參照線就可以看到效果。
上例中的 XML 源碼如下:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.stylingandroid.scratch.MainActivity">
<View
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
app:layout_constraintDimensionRatio="h,15:9"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.39" />
</android.support.constraint.ConstraintLayout>
可以發(fā)現(xiàn),設置橫縱比的屬性是 app:layout_constraintDimensionRatio
,而這個值有兩個部分組成:方向和比例值。
通過上面的視圖編輯器,我們已經(jīng)知道了寬度就是輸入的固定值,從而設置了方向是 h
標識了 horizontal
。其實這個方向可以不用設置,在運行時的 layout 布局過程就可以計算推斷出來,但顯示的在 xml 源碼中聲明避免了所有可能出現(xiàn)模棱兩可的情況發(fā)生。在大多數(shù)情況下,這非常不必要因為本身方向是不言自明的,就像例子中,唯有高度沒被約束,很容易推斷出來高度是根據(jù)寬度來的變量函數(shù)。
這種橫縱比的組件往往又很大的說服力,當橫縱比的權(quán)利被賦予的時候。
最后還要提到的是,上文提到的寬高屬性被設置成 match_constraint
實際上在 XML 源碼中表現(xiàn)是被設置成 0dp
,這就像 LinearLayout
的 weight
屬性一樣,會在 XML 中設置為 0dp
,而實際大小會根據(jù)父組件在布局 layout
過程中的大小來決定計算出來。
更多建議: