ConstraintLayout

目前ConstraintLayout(alpha-4)还是打包到support library中的,因此 属性前缀 app: 而非 android:,以后应该会放到包的命名区间。

I. 位置:

1. 锚点

View相对与其他元件(同级别View、父节点View、guideline)是如何布局的。

格式

1
layout_constraint[SourceAnchor]_[TargetAnchor]="[TargetId]"

其中SourceAnchor/TargetAnchor 可以是:

  • Top,Bottom,Start(Left),End(Right)
  • CenterX、CenterY
  • Baseline(只有Text-Based的View支持)

2. Bias:

  • 横向比重: layout_constraintHorizontal_bias=左方占比
  • 纵向比重: layout_constraintVertical_bias=上方占比

3. Guidelines:

特征:

  1. measure大小始终是0;
    2.它的visibility始终是View.GONE

特有参数:

  • 到开始边缘的绝对距离: layout_constraintGuide_begin
  • 到结束边缘的绝对距离: layout_constraintGuide_end
  • 到开始边缘的占比百分数: layout_constraintGuide_Percent

P.S: Guideline是纵向还是横向的,由android:orientation="<vertical|horizontal>"决定。

4. 编辑器辅助

layout_editor_absoluteXlayout_editor_absoluteY是只有在编辑器中使用,设备上运行时这些是没有效果的。参数空间是在: http://schemas.android.com/tools

II. 大小

1. 没有了match_parent

可替代 : 将layout_width/layout_height设为0dp: 填充满附属的锚点布局。

原因 : 但是更加灵活,可以类似以前的layout_weight使用。

2. 支持长宽比

layout_constraintDimensionRatio 提供长宽比如: 4:3。在给了这个参数的情况下,需要提供任意一边的值(指定值或wrap_content)

III. 原理与性能

添加子View到ContraintLayout时,所有XML中layout_前缀的属性都会添加到LayoutParams实例中。

ConstraintLayout子View中的LayoutParams存储着ConstraintWidgetConstraintWidget用于逻辑运算与分析,并且每个ConstraintWidgetConstraintLayout中的ConstraintWidgetContainer相联系。

ClassHierarchy

ConstraintWidget持有所有关于View位置与大小的信息,在measure与layout时作为数据依据。

ConstraintWidget

在layout的期间,会根据LayoutParams中constraint的信息,为ConstraintWidget中每个连接的锚点定义ConstraintAnchor

AnchorConnection

1. measure

MeasureFlow

这里的”Any Size”View,指的是XML中给的长或宽为0dp的View。

“Any Size”View,需要两次运算,首次会直接不做检查在ConstraintLayout#internalMeasureChildren中直接使用WRAP_CONTENT用于计算大小(ViewGroup#getChildMeasureSpec),第二次根据其他的计算结果在ConstraintLayout#onMeasure中计算出真正的大小。

P.S: Add Constraints to Equation SolverMinimize Linear SystemUpdate Child Bounds from solution 都是在ConstraintLayout#onMeasure中在执行的ConstraintLayout#internalMeasureChildren。该算法计通过LinearSystem算出了View的bound。

2. layout

由于上面在measure时已经估算出各view的大小与位置,因此在此之后ConstraintWidget中已经有对应View适当的bound了。因此在onLayout中只需要遍历所有子View,设置他们的bound值就行,十分轻量。

1
2
3
4
5
6
7
8
9
10
11
for(int i = 0; i < getChildCount(); ++i) {
View child = this.getChildAt(i);
ConstraintLayout.LayoutParams params =
(ConstraintLayout.LayoutParams)child.getLayoutParams();
ConstraintWidget widget = params.widget;
int l = widget.getDrawX();
int t = widget.getDrawY();
int r = l + widget.getWidth();
int b = t + widget.getHeight();
child.layout(l, t, r, b);
}

IV. 性能方面

由于ConstraintLayout有效的优化了layout与draw,并且从质上有效的减少了层级,因此相同的布局呈现上,通常情况下ConstrantLayout的性能都比其他的Layout性能要好。


文中图片全部来源: http://wiresareobsolete.com/2016/07/constraintlayout-part-2/


Jacksgong wechat
欢迎关注Jacks Blog公众号,第一时间接收原创技术沉淀干货。