当小白的我一开始接触到ConstraintLayout(约束布局,以下简称为cons),我被这扁平化、减少嵌套的特殊布局吸引了。虽然我对其他布局了解不是太深入,但在很多博客、书籍里面都说过减少嵌套可以优化性能。在看了好几篇关于cons的实用技巧的博客,并且尝试学着文中布局之后,我成了cons的忠实拥趸。刚好想做一个复利计息的界面,按其他布局来计算应该会有至少三个层级的,我打算用cons下的一个层级就给搞定,然后真的做出来了 0.0 。实际上也修改了不少次,参考了不少博客,才做出来的。cons可能在上手时会有些难度,很多属性很抽象不好记忆,但对着下面我推荐的博客,假设一个嵌套层级较多的场景界面来练习几次,就会发现cons真的很好用。后面会有我觉得不错的博客,和我觉得我用的比较多的属性与小技巧。之后是我用cons一个层级完成的功能UI界面与代码(结合了抽象布局),可以参考一下,还有些我对cons使用的心得。
首先推荐一下三篇关于cons的很棒的博客。
郭霖大神的简洁易懂的入门教程:Android新特性介绍,ConstraintLayout完全解析
接下来这俩篇就是进阶版了,因为是根据新版本来写的,所以用法更多样(俩篇侧重点不同,一起食用最好):
ConstraintLayout在项目中实践与总结
ConstraintLayout 用法全解析
从大佬们的博客里面学到了很多有趣的用法,这也是我想用cons的一方面原因。
约束布局的定位属性有十三种,我的记忆方式是 :
layout_constraint(本组件的部位)_to(建立连接的组件部位)Of:(建立连接的id)
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
建议不用带left、right的属性,这样影响适配,横向只用start和end就好了。
cons中的每个属性建议至少使用俩个定位属性,这样大部分的界面都可以实现了。我的做法是一般都start和top位置的定位属性,这样对大多数左对齐的界面方便管理和编写代码。
另一个我觉得很实用的方法就是辅助线用法,我在看博客时学习了俩种辅助线的用法,一种是1px的view,用法如下:
上方一整块背景是用一个view+颜色背景实现的,以为cons设置背景色只能在主布局中设置背景色,所以想实现如图的样式需要设置辅助线。view2本是
app:layout_constraintBottom_toBottomOf="@id/view"
但用android:layout_marginBottom="280dp",将它在原有的位置上上升了280dp,这个也刚好是view的高度,然后再把所有的组件一个个在view2下方放置就好了。
第二个辅助线就是官方的GuideLine,使用方法如下。
我在项目中定义了四条辅助线,可以看出其实 gl_top跟第一个方法用的view2是一样的作用,这个等一下说。
我觉得辅助线的精髓在于下面这俩条属性。
app:layout_constraintGuide_percent="0.5"
app:layout_constraintGuide_end="@dimen/margin_m"
这是给的辅助线的定位,既有百分比,又有具体距离的设置。百分比的设置让适配变得方便,具体距离的设置让组建的位置更为精准。有这个辅助线是实现稳定的组件们的线性排列变得方便。场景可参考项目图中的俩个edittext和俩个button的横向线性排列,用GuideLine后取代了线性布局的嵌套。
你们肯定要问了,设置view2这种抖机灵的小部件有何用,还消耗性能!不不不,我在刚才写博客时也想了一下,View2这种“自制辅助线”到底有何用呢。GuideLine只能在cons主布局中做组件的定位的辅助线,它的百分比和距离定位都是相对于主布局的,没法哪一个组件具体的辅助线,这是我们的“自制辅助线”就派上用场了,与某个组件建立约束,修改特定的margin值,就成了专属辅助线,在此辅助线建立的约束可以消去与其他组件的耦合(cons下的每个组件之间的关联太紧密,取消一个如牵一发而动全身,这也是很多人不想用cons的原因,但这个也是它的优势,精准定位,适配方便)。
解释一下,其实在我做的这个项目中,界面最上方的辅助线其实是不需要的(我也是写博客时才发觉),之所以没代码中没去掉是为了简单地演示一下辅助线的用法,cons中一个点(每个组件包括parent都有上下左右四个点)都可以建立多个约束的,所以组件覆盖另一个组件也是ok的(这好像是帧布局的功能0.0)。
此外cons很多实用方法,在我推荐的博客上可以看到。cons真的很强大!
以下是我强迫症般地使用cons的界面截图,该项目的idea仅做参考(我知道不怎么好看。。。)
可以看出整个布局毫无嵌套,仅一个层级。真机界面看下图
当然,这个界面不算复杂,但只用一个层级就能做出来,那估计只有cons布局才能做到了。
你也许会说,这里有include,还有viewstub这种抽象布局,那里面肯定会有嵌套的啊。
客官莫急,且看代码。
以上是主要布局代码,看起来很少是因为蓝色部分组件给放进了calculator_merge里面了,而merge并不会增加层级,只是把代码分开,优化UI方便修改,都在一个xml里面看起来太臃肿了。merge支持主布局的规则,当然也支持主布局是cons。下面就是merge部分代码。
最重要的是下面一行代码,是我大佬回复我评论告诉我的。没有这段代码无法建立约束关系。
tools:parentTag="android.support.constraint.ConstraintLayout"
写在merge里面,唯一的不好就是太烦了,很多地方没有代码提示,可以现在主布局代码里面写好,再移过去。
说完了merge,再说说viewstub吧。先上代码
这是calculator_viewstub_btn.xml的代码。(好了,你不要再说了,我知道这是个滚动嵌套布局,,,,)然而这个嵌套却可以不需要initView时加载。viewstub可以算作一个占位符,它是是一个不可见的,大小为0的View,需要inflate()方法将它加载出来,然而只要在合适的时机加载,就不会影响UI初始化的性能了。我这个隐藏button的idea可以让ViewStub的使用场景变得更多。具体的实现我会在我的下一篇博客《ViewStub的奇淫巧技 》详细介绍。
通过我的介绍各位看官可以看出cons的强大,很多常用布局它都可以实现,当它跟抽象布局配合起来更强大。因为强大,它的源码也是多得惊人,虽然官方称ConstraintLayout在测量/布局阶段比RelativeLayout好40%左右,但是在onDraw()的阶段呢。所以深度嵌套肯定首选cons。cons的使用在刚上手的时候是比较繁琐,但建议你在使用多层嵌套布局时去试着多练习一下cons的使用,为了优化!
这个界面把三个抽象布局标签都用了,也算圆满了,希望这种布局优化可以给你提供一点思路。
写博客真得让我关注到了做项目时很多不注意的细节,感觉对cons的记忆更深刻了,这也许就是博客让人提升的地方吧。
望指正,谢谢!
参考:https://blog.csdn.net/stevenhenry/article/details/78954981
https://blog.csdn.net/xyz_lmn/article/details/14524567