一、开门闲话
首先写这篇文章之前,扯个淡,关于ConstrainLayout约束布局中的app:layout_constraintDimensionRatio 属性,今天我总算通过自己努力钻牛角尖,自己解了自己困扰多年的问题。 如果你还没用过,说明基础还不行啊,倒回去多写写UI咯~
哈哈,开个玩笑。
废话少说,圆规正传。见名之义,它就是用来宽高约束的,这不废话么。 没错,废话也要说一遍。 虽然它只是一个布局属性,有人可能觉得很简单啊,写个比例完事了嘛。Really?如果你用过,你一定对这个属性会有和我以前一样的感觉和困惑之处 。
用到的时候,试个几遍总能试出来。但是如果要靠试出来,那就是没有真正理解到位。 为什么不能下意识就配置正确 ?下面就开始为你,用最通俗易懂的话语,排忧解惑。
- 总之,如果有疑惑,本文总结的内容,就是笔者辛苦实践后,独家揭秘,网上没有资料喔。值得一看。 - _ -
Tips:请耐心阅读。 想直接看结论的,可以直接跳最后。
二、雾里看花
- 什么时候用这个属性?
- 宽高比例约束怎么配置?如何去理解?
- 有了宽高比例约束,宽高属性值又如何配置?
- 既有宽高,又有约束如何理解?
- 如何快速去算?(也就是我总结的套路)
三、拨云见月
1 . 什么时候用这个属性?
当你布局一个控件,想按照一定比例去布局,但又不想写死具体值时。或者想要尽可能的适配不同的屏幕。
比如:你想要一个宽度充满屏幕,宽高相等1:1的控件?
常规布局是无法直接设置的。需要通过代码动态计算控件高度,设置高度=屏幕宽度
比如:你想要一个宽度100dp, 宽高又是16:9,或者1:10的控件?
插入动态代码计算,总之不好看
这时候就可以用上 app:layout_constraintDimensionRatio 属性。
2. 宽高比例如何配置?
通常情况下,配置宽高比时,宽高大小都会约束为0dp,约束到parent,进行铺满 android:layout_width="0dp" android:layout_height="100dp"
- 语法如下:
app:layout_constraintDimensionRatio="h,1:1"
h -->> 前面写h的时候,需要反过来理解,以宽度 w 的值为基准参考值,根据比例去算 高度 h
w -->> 前面写w的时候,需要反过来理解,以宽度 h 的值为基准参考值,根据比例去算 宽度 w
1:1 -->> 表示宽高比。记住: 不管前面写h,还是w, 请一定要理解成 宽 :高
-
如示例:h,1:1
以宽度w为参考,计算高度。 并且按比例1:1。因为宽度是充满。那么高度就一定是宽度的值,呈正方形了。
(约束布局下,宽度=0dp, start-parent, end-parent,就是match_parent)
-
再比如: 改为:w,1:1 。 宽、高均为0dp, 左右上下约束的是parent,也就是默认铺满
结果就是以高度为参考值,按照比例 宽高1:1,计算宽度w.
由图可以证实,宽度按照高度值已经超出屏幕之外
啊? 就这?别急!上面只是一种很基础的配置。我们加上一点条件,再变化一下看看情况。
3.配置了宽高比例,同时单边却有固定值 ?
-
比如:此时我的配置是
android:layout_width="100dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="h,1:10"
请先自己脑袋想一下2秒,此时布局,这个控件应该是个什么样? 再往下看。--
答案:高度保持0dp充满,宽度为固定值100dp. 宽高比:1:10.
前面写的h,按照前面总结的, 以w宽度为参考值,计算高度h.
此时,宽度固定为了100dp, 宽:高=1:10, 那么高度为1000dp. 如图
--
- 再变化一下,此时我的配置是
android:layout_width="100dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="w,1:10"
将h,改为了w,请先自己脑袋想一下2秒,此时布局,这个控件应该长什么样? 再往下看。
--
诶,马老师说"婷婷,我要婷婷” ,这个时候可能你就有疑惑了?
按照前面总结的,前面是w, 就是按照高度h为基准值,计算高度值。
可是此时高度为0dp, 充满屏幕,按照宽:高=1:10. 计算高度? 这逻辑说不通啊,咋一边按照h值,一边又计算它自己!
重点来了,这种情况下, 三个步骤
- 首先,如果某一边固定了具体的值,如100dp(0dp不算), 就是以该边为参考,求另一边。
- 宽高约束比前的值和该边相同,则忽略,不同则按比例值求算。 示例:宽度=100dp, w,1:10, 那么还是以宽度为参考,求h。
- 所求值(h)= 已知值 * 比例(1/10), h=10dp 。 如图
--
- 你理解了吗? 现在反过来。 给出单边固定高度h的情况。 来进行验证
w=0dp h=100dp铺满, 宽高比: w,1:10.
约束和固定边不同,则按照结论:以h为参考边,计算w的值
并且: w=h / 比例(1/10)
- w=0dp h=100dp铺满, 宽高比: h,1:10.
约束和固定边相同,则忽略结论:还是以固定边为参考边,计算w的值
并且: w=h* 比例(1/10)
4. 同时具有宽高固定值,又配置了宽高约束
这样的情况,
- 配置宽高都为固定值,此时宽高约束会无效。会优先按照宽高固定值。
- 配置为wrap_content, 此时宽高比约束会无效,也是安卓宽高固定值(自适应)
5. 特殊情况:宽高比例配置,不写w或者h
-
配置宽高比时,还可以省略 w或者h , 语法如:
app:layout_constraintDimensionRatio="1:20" -
这种情况应该以哪边为参考值呢? 也许你会认为,默认就是h,或者w。 其实不是这样的。 系统会根据比例数字大的一边作为长边参考值。
- 如 1:20 代表的是宽:高。20比1大,此时,就会以高度为参考值,去计算宽度。
- 高度由于是0dp,铺满屏幕, 那么宽度就是高度的 1/20.
<TextView
android:layout_width="0dp"
android:layout_height="0dp"
android:text="这是被约束比例的控件"
android:gravity="center"
android:textSize="30sp"
app:layout_constraintDimensionRatio="1:20"
android:background="@color/colorPrimary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
--
- 改为:
app:layout_constraintDimensionRatio="20:1" - 20:1 代表的是宽:高。20比1大,此时,就会以宽度为参考值,去计算高度。
- 宽度由于是0dp,铺满屏幕, 那么高度就是高度的 1/20
四、万变不离其宗
- 总是套路得人心。 举了这么多例子,是时候推出 最后的总结了。 如果你已经看出规律了。那太好了。说明本文的作用达到了
套路公式
- 宽高比属性值,写h时,求值时,采用 ➗ 比例。 如 :h, 1:10 x=y / (1/10)
- 宽高比属性值,写w时,求值时,采用 * 比例。 如 :w,1:10 x=y * (1/10)
- 但还得注意控件宽高属性值的配置。 见下图
- 同时如果省略h,w时,优先采用数字大的一边 作为参考边
五、结束语
这里做个结束语吧,本文只是笔者的一点见解。 虽然该知识点很小,很不惹人注意。但是要弄懂搞明白,实属需要花些心思。至少目前我没有看到网上有相关详细解读。只是单纯告诉你这个宽高比,但是规则却没有任何解析。导致几年前在写该属性时,每次都需要花一定时间去试。却始终找不到规律的痛苦。