ConstraintLayout 1.1新功能

Posted by alonealice on 2017-12-18

ConstraintLayout初步探究中简单的介绍了ConstraintLayout的几个实用的属性,那些都是基于1.0.2的版本的功能。今年的google开发者大会,google为我们带来了新的ConstraintLayout。那么新版的ConstraintLayout又有哪些新的功能呢。

首先,本文基于的版本为1.1.0-beta3.

引用该版本:compile 'com.android.support.constraint:constraint-layout:1.1.0-beta3'

宽、高度比例

在之前的版本中,如果设置宽度或高度为0dp,View的相应宽、高度会自动撑满布局,这个可以通过设置layout_constraintHeight_default来改变。在1.1版本中,我们可以设置layout_constraintHeight_default=“percent”,同时设置layout_constraintWidth_percent=“0.4”,该属性的值为0-1。

1
2
3
4
5
6
7
8
<View
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_marginTop="200dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.4"
android:background="#332211"></View>

barrier

当我们的界面布局因为内容的变化而改变时,布局有时候会出现错乱的情况。比如View在两个TextView的右边,但是我们只能设置View的layout_constraintLeft_toRightOf其中的一个TextView,当另一个TextView的文字长度变化时,就会超过并与View重叠,而如果TextView设置layout_constraintRight_toLeftOf时,又会限制TextView的宽度。这时,我们就可以用到barrier了。

关于barrier的详细介绍,可以参考ConstraintLayout之Barrier

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<TextView
android:id="@+id/v1"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:text="dadsadsadasdsadsads"
app:layout_constraintTop_toTopOf="parent"
></TextView>

<TextView
android:id="@+id/view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
app:layout_constraintTop_toTopOf="parent"
android:text="dadsadsadasdsadsadsdsadsadsa"
></TextView>


<android.support.constraint.Barrier
android:id="@+id/Barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="v1,view"/>

<View
android:id="@+id/view2"
android:layout_width="10dp"
android:layout_height="match_parent"
android:background="#ff0000"
app:layout_constraintLeft_toRightOf="@+id/Barrier"
app:layout_constraintTop_toTopOf="parent"></View>

barrier在这里是一个不可见的控件,但是它可以帮我们添加约束条件。这里我们看到,我们设置了app:barrierDirection=“right”,说明约束条件为右,同时将设置constraint_referenced_ids设置barrier的childview。最后将View的layout_constraintLeft_toRightOf设置为barrier。

效果图:

Group

Group顾名思义就是将多个View放在Group中进行统一处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 <TextView
android:id="@+id/v1"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:text="dadsadsadasdsadsads"
app:layout_constraintTop_toTopOf="parent"
></TextView>

<TextView
android:id="@+id/view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
app:layout_constraintTop_toTopOf="parent"
android:text="dadsadsadasdsadsadsdsadsadsa"
></TextView>


<android.support.constraint.Group
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="v1,view"/>

当我们在代码中设置group.setVisibility(View.GONE)时,两个TextView都会消失。

Placeholder

Placeholder 可以将自己的内容替换为其他View,所以它可以用来写布局模板,也可以动态修改UI内容。

用作模板

模板xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0" encoding="utf-8"?>
<merge
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:parentTag="android.support.constraint.ConstraintLayout">

<android.support.constraint.Placeholder
android:id="@+id/template_save"
android:layout_width="48dp"
android:layout_height="48dp"
app:content="@+id/save"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintEnd_toStartOf="@+id/template_delete"
app:layout_constraintStart_toStartOf="parent"
/>

<android.support.constraint.Placeholder
android:id="@+id/template_delete"
android:layout_width="48dp"
android:layout_height="48dp"
app:content="@+id/delete"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/template_cancel"
app:layout_constraintStart_toEndOf="@+id/template_save"
/>

<android.support.constraint.Placeholder
android:id="@+id/template_cancel"
android:layout_width="48dp"
android:layout_height="48dp"
app:content="@+id/cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/template_edit"
app:layout_constraintStart_toEndOf="@+id/template_delete"
/>

<android.support.constraint.Placeholder
android:id="@+id/template_edit"
android:layout_width="48dp"
android:layout_height="48dp"
app:content="@+id/edit"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/template_cancel"
/>

</merge>

Placeholder中都设置了 app:content=“id”,表示需要替换的View的id。

真正的布局文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">

<include layout="@layout/temp" />

<ImageView
android:id="@+id/save"
android:layout_width="48dp"
android:layout_height="48dp"
app:srcCompat="@mipmap/two_point" />

<ImageView
android:id="@+id/edit"
android:layout_width="48dp"
android:layout_height="48dp"
app:srcCompat="@mipmap/three_point" />

<ImageView
android:id="@+id/cancel"
android:layout_width="48dp"
android:layout_height="48dp"
app:srcCompat="@mipmap/four_point" />

<ImageView
android:id="@+id/delete"
android:layout_width="48dp"
android:layout_height="48dp"
app:srcCompat="@mipmap/five_point" />

</android.support.constraint.ConstraintLayout>

这里模板文件需要放在最前面。

最后看看效果图:

动态替换

Placeholder可以在代码中动态替换掉代替的View

1
2
3
4
5
6
7
mPlaceholder= (Placeholder) findViewById(R.id.template_action);
findViewById(R.id.save).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPlaceholder.setContentId(v.getId());
}
});

这里的save是不能用Placeholder代替。

最后

在1.1版本中,我们可以看到ConstraintLayout的功能越来越多,不仅可以更好的减少代码层级,还可以代替掉一部分逻辑层的代码。