最近在学习ConstraintLayout时遇到这个属性用不太明白,网上找不到太多详细的资料,参考官网文档和自己的摸索后,把自己的结论跟大家分享下,欢迎批评指正。
首先来看一下官网的解释,如图
由文档我们首先能得出以下结论:
- 如果要使用这个属性,我们至少要把控件的宽或高中间的一个设置为match constraints,具体怎么设置就不再赘述(XML和View Inspector里都可以).
- ratio的比值表示的是宽高比,注意,一直都是宽高比
了解这两点之后,问题来了,系统是怎么知道我们究竟是"以宽为准,按比例去设置高"呢? 还是"以高为准,按比例去设置宽"呢?
我们首先注意到1.里所说的,必须把宽或者高其中之一设为match_constraint,而match_constraint的意思是满足约束。为什么要这么做呢?
举个例子,我们把layout_width设置为match_constraint, layout_height设为固定值100dp,那么很显然,高度是写死的,宽度是需要满足某种约束。此时,如果我们设置了layout_constraintDimensionRatio ="4:1",会出现什么效果呢?很显然,系统会保持高度为100dp,而宽度为高度的4倍,即400dp,从而“match_constraint”满足约束。下面我们来试验一下:
约束width, layout_width="0dp"
XML代码如下:
<?xml version="1.0" encoding="utf-8"?>
<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.example.xuqi.constraintlayoutdemo.MainActivity">
<ImageView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_marginBottom="252dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="w,4:1"
tools:layout_editor_absoluteX="5dp"
android:background="@color/colorAccent"/>
</android.support.constraint.ConstraintLayout>
preview如下:
显然达到了我们的预期。
约束height,layout_height="0dp"
同理,如果我们把height设为match_constraint,width设为100dp,那么系统就认为我们要以width为准去约束height,我们再加上一句app:layout_constraintDimensionRatio="h,1:2",那么高就是宽的2倍
<?xml version="1.0" encoding="utf-8"?>
<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.example.xuqi.constraintlayoutdemo.MainActivity">
<ImageView
android:id="@+id/textView"
android:layout_width="100dp"
android:layout_height="0dp"
android:layout_marginBottom="252dp"
android:background="@color/colorAccent"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,1:2"
tools:layout_editor_absoluteX="5dp" />
</android.support.constraint.ConstraintLayout>
效果如下:
同时约束,layout_width="0dp" && layout_height="0dp"
想象一个场景,我们想在布局里放一张banner,宽度铺满全屏,高度始终为宽度的1/3。那么我们首先为了宽度铺满全屏,需要将width设为match_constraint,又因为高度需要跟宽度形成1:3的比例,所以高度也要同样设置match_constraint,然后将app:layout_constraintDimensionRatio设为"h,3:1"即可
<?xml version="1.0" encoding="utf-8"?>
<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.example.xuqi.constraintlayoutdemo.MainActivity">
<ImageView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/colorAccent"
android:text="TextView"
app:layout_constraintDimensionRatio="h,3:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="0dp" />
</android.support.constraint.ConstraintLayout>
效果如下:
h和w参数的解释
这里我们还需要解释一下app:layout_constraintDimensionRatio的值里面的h和w是什么意思。一般来说,加上h的意思就是,h之后的比例是以w为基础去设置h,即h = w * ratio。反之,写上w的意思是,w = h / ratio (因为 ratio = w / h 代表宽高比)。
以及,如图
英文好的同学可以直接看文档
我们可以看到,如果只把一条边设为0dp,那么我们是无需添加h和w的(会有默认值)。因为我们只能去通过未设为0dp的边来约束设为0dp的那条边,也就是说h和w就对应设为0dp的那条边。而如果两条边都设为0dp,那么就必须设置h和w了,不然系统不知道我们想约束哪条边。原理还是一样的,希望哪条边被约束,我们就写哪条边的字母。
总结
以上主要还是想告诉大家这个属性的原理,其实真正去用的时候还是用View Inspector来做的比较多。当我们把至少一条边设为match_constraint后,点击方框左上角的toggle按钮,可以设置对应的比例,方框里显示的横线或竖线表示哪条边是被限制,跟属性里的h和w是对应的。示例如下:
- layout_width = "0dp" && layout_height = "0dp"
- layout_height = "0dp"
- layout_width = "0dp"