1.介绍
2.为什么要用ConstraintLayout
3.如何使用ConstraintLayout
3.1 添加依赖
3.2 相对定位
3.3 角度定位
3.4 边距
3.5 偏移
3.6 尺寸约束
3.6.1 使用指定的尺寸
3.6.2使用wrap_content,让控件自己计算大小
3.6.3 使用 0dp (MATCH_CONSTRAINT)设置百分比布局:
3.6.4 宽高比
3.7 链
4.辅助工具
4.1 Optimizer
4.2 Barrier
4.3 Group
4.4 Placeholder
4.5.Guideline
5.综合案例
注意:1.官方的模板默认使用 ConstraintLayout。
2.ConstraintLayout属性不能在嵌套布局中使用,不能使用match_parent。
3. android:layout_width=“0dp”
android:layout_height=“0dp”
都设置为0dp时,控件大小需要特殊处理,否则不显示。详情见综合案例。
4.constraintlayout,滑动问题还没有很好的解决。可以使用百分比布局。
1.介绍
约束布局ConstraintLayout 是一个ViewGroup,可以在Api9以上的Android系统使用它,它的出现主要是为了解决布局嵌套过多的问题,以灵活的方式定位和调整小部件
2.为什么要用ConstraintLayout
-
在开发过程中经常能遇到一些复杂的UI,可能会出现布局嵌套过多的问题,嵌套得越多,设备绘制视图所需的时间和计算功耗也就越多
-
ConstraintLayout使用起来比RelativeLayout更灵活,性能更出色!
-
ConstraintLayout可以按照比例约束控件位置和尺寸,能够更好地适配屏幕大小不同的机型。
3.如何使用ConstraintLayout
3.1 配置
1.添加依赖(创建项目时自动添加)
首先我们需要在app/build.gradle文件中添加ConstraintLayout的依赖,如下所示。
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
2.如果使用app属性需要在ConstraintLayout中添加
xmlns:app="http://schemas.android.com/apk/res-auto"
3.如果有报错
ConstraintLayout中 xmlns:tools=“
http://schemas.android.com/tools
”
TextView中加上:tools:ignore=“MissingConstraints”(等同下图)
<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.support.constraint.ConstraintLayout>
3.2 相对定位
常用属性:
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
3.3 角度定位
角度定位指的是可以用一个角度和一个距离来约束两个空间的中心。举个例子:
<TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/TextView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintCircle="@+id/TextView1"
app:layout_constraintCircleAngle="120"
app:layout_constraintCircleRadius="160dp" />
上面例子中的TextView2用到了3个属性:
app:layout_constraintCircle="@+id/TextView1"
app:layout_constraintCircleAngle=“120”(角度)
app:layout_constraintCircleRadius=“160dp”(距离)
指的是TextView2的中心在TextView1的中心的120度,距离为160dp,效果如下:
3.4 边距
3.4.1 margin
ConstraintLayout的边距常用属性如下: android:layout_marginStart android:layout_marginEnd android:layout_marginLeft android:layout_marginTop android:layout_marginRight android:layout_marginBottom 注:控件在ConstraintLayout里面要实现margin,必须先约束该控件在ConstraintLayout里的相对位置且margin只能大于等于0。 例:
不生效:
<android.support.constraint.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp" />
</android.support.constraint.ConstraintLayout>
生效:
<android.support.constraint.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="00dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
控件可见性,有三种状态,分别为:visible, invisilbe,gone.。visible表示控件可见
3.4.2 goneMargin
goneMargin主要用于约束的控件可见性被设置为gone的时候使用的margin值,属性如下: layout_goneMarginStart layout_goneMarginEnd layout_goneMarginLeft layout_goneMarginTop layout_goneMarginRight layout_goneMarginBottom
补充:控件可见性,有三种状态,分别为:visible, invisilbe,gone.。visible表示控件可见,invisible表示控件不可见,但是任然占用空间,gone表示不见,且不占用空间。
举个例子:
假设TextView2的左边约束在TextView1的右边,并给TextView2设一个app:layout_goneMarginLeft=“20dp”:
效果如下,TextView2在TextView1的右边,且没有边距
这个时候把TextView1的可见性设为gone,TextView1消失后,TextView2有一个距离左边10dp的边距。效果如下:
3.5 偏移
layout_constraintHorizontal_bias=“percent” 水平偏移
layout_constraintVertical_bias=“percent” 垂直偏移
举个例子:
<TextView
android:id="@+id/TextView1"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
效果如下:
3.6 尺寸约束
-
使用指定的尺寸
-
使用wrap_content,让控件自己计算大小
当控件的高度或宽度为wrap_content时,可以使用下列属性来控制最大、最小的高度或宽度:
android:minWidth 最小的宽度
android:minHeight 最小的高度
android:maxWidth 最大的宽度
android:maxHeight 最大的高度
使用 0dp (MATCH_CONSTRAINT)设置百分比布局:
1.layout_width或者 layout_height 设置为0dp(只能一个)
2.设置 layout_constraintWidth_percent="percent"或者 layout_constraintHeight_percent=“percent”
-
宽高比
当宽或高至少有一个尺寸被设置为0dp时或为wrap_content时,可以通过以下属性设置宽高比:
layout_constraintDimensionRatio ="1:1"
app:layout_constraintDimensionRatio="H,2:3"指的是 高:宽=2:3
app:layout_constraintDimensionRatio="W,2:3"指的是 宽:高=2:3
3.7 Chainl链
1.如果两个或以上控件通过下图的方式约束在一起,就可以认为是他们是一条链(图为横向的链,纵向同理)。
代码:
<TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/TextView2" />
<TextView
android:id="@+id/TextView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toRightOf="@+id/TextView1"
app:layout_constraintRight_toLeftOf="@+id/TextView3"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:id="@+id/TextView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toRightOf="@+id/TextView2"
app:layout_constraintRight_toRightOf="parent" />
以下链的内容转自:
https://www.jianshu.com/p/2c125a8074ca
2.一个链条里面的第一个元素即为头,水平最左边,垂直最上边的控件,链头的作用是控制整个链条的属性,如上面的A控件就是链头。
3.在链头上面设置margin,整个链条都会响应这个margin,比如设置链头的一个左边android:layout_marginStart=“10dp”,这整个链条都会响应这个margin
4.Chain Style
链条可以设置不同的style,通过设置下面两个属性分别设置水平或者垂直(在链头设置):
layout_constraintHorizontal_chainStyle
layout_constraintVertical_chainStyle
而style包括三种:
-
spread(默认)-元素被分散开:
-
spread_inside-与spread类似,只是链条的端点不会被分散链接:
-
packed-链条内的元素将被捆在一起:
同时还有两种组合,在链条里面,可以使用weight和bias:-spread + weight-将元素的尺寸设置为MATCH_CONSTRAINT时,可以与weight平分空间:
-
packed + bias- 前面说过bias是偏重的意思,这里就是将链条集体偏重:
-
综合案例:
<!-- weight chain -->
<TextView
android:id="@+id/weightStart"
android:layout_width="0dp"
app:layout_constraintHorizontal_weight="1" />
<TextView
android:id="@+id/weightCenter"
android:layout_width="0dp"
app:layout_constraintHorizontal_weight="2" />
<TextView
android:id="@+id/weightEnd"
android:layout_width="0dp"
app:layout_constraintHorizontal_weight="2" />
<!-- spread chain-->
<TextView
android:id="@+id/spreadStart"
app:layout_constraintBottom_toTopOf="@id/weightStart"
app:layout_constraintEnd_toStartOf="@id/spreadCenter"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/spreadCenter" />
<TextView
android:id="@+id/spreadEnd" />
<!-- packed chain -->
<TextView
android:id="@+id/packedStart"
app:layout_constraintHorizontal_chainStyle="packed" />
<TextView
android:id="@+id/packedCenter" />
<TextView
android:id="@+id/packedEnd" />
<!-- spread_inside chain -->
<TextView
android:id="@+id/insideStart"
app:layout_constraintHorizontal_chainStyle="spread_inside" />
<TextView
android:id="@+id/insideCenter"/>
<TextView
android:id="@+id/insideEnd" />
<!-- packed chain with bias -->
<TextView
android:id="@+id/packedBiasStart"
app:layout_constraintHorizontal_bias="0.2"
app:layout_constraintHorizontal_chainStyle="packed" />
<TextView
android:id="@+id/packedBiasCenter" />
<TextView
android:id="@+id/packedBiasEnd" />
4.辅助工具
以下辅助工具内容转自:
https://www.jianshu.com/p/17ec9bd6ca8a
4.1 Optimizer
当我们使用 MATCH_CONSTRAINT 时,ConstraintLayout 将对控件进行 2 次测量,ConstraintLayout在1.1中可以通过设置 layout_optimizationLevel 进行优化,可设置的值有:
none:无优化
standard:仅优化直接约束和屏障约束(默认)
direct:优化直接约束
barrier:优化屏障约束
chain:优化链约束
dimensions:优化尺寸测量
4.2 Barrierr
假设有3个控件ABC,C在AB的右边,但是AB的宽是不固定的,这个时候C无论约束在A的右边或者B的右边都不对。当出现这种情况可以用Barrier来解决。Barrier可以在多个控件的一侧建立一个屏障,如下所示:
这个时候C只要约束在Barrier的右边就可以了,代码如下:
<TextView
android:id="@+id/TextView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/TextView1" />
<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="TextView1,TextView2" />
<TextView
android:id="@+id/TextView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toRightOf="@+id/barrier" />
app:barrierDirection为屏障所在的位置,可设置的值有:bottom、end、left、right、start、top
app:constraint_referenced_ids为屏障引用的控件,可设置多个(用“,”隔开)
4.3 Groupr
Group可以把多个控件归为一组,方便隐藏或显示一组控件,举个例子:
<TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/TextView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toRightOf="@+id/TextView1" />
<TextView
android:id="@+id/TextView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toRightOf="@id/TextView2" />
现在有3个并排的TextView,用Group把TextView1和TextView3归为一组,再设置这组控件的可见性,如下所示:
<android.support.constraint.Group
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
app:constraint_referenced_ids="TextView1,TextView3" />
4.4 Placeholder
Placeholder指的是占位符。在Placeholder中可使用setContent()设置另一个控件的id,使这个控件移动到占位符的位置。举个例子:
<android.support.constraint.Placeholder
android:id="@+id/placeholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:content="@+id/textview"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#cccccc"
android:padding="16dp"
android:text="TextView"
android:textColor="#000000"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
新建一个Placeholder约束在屏幕的左上角,新建一个TextView约束在屏幕的右上角,在Placeholder中设置 app:content="@+id/textview",这时TextView会跑到屏幕的左上角。效果如下:
4.5 Guideliner
Guildline像辅助线一样,在预览的时候帮助你完成布局(不会显示在界面上)。
Guildline的主要属性:
android:orientation 垂直vertical,水平horizontal
layout_constraintGuide_begin 开始位置
layout_constraintGuide_end 结束位置
layout_constraintGuide_percent 距离顶部的百分比(orientation = horizontal时则为距离左边)
举个例子:
<android.support.constraint.Guideline
android:id="@+id/guideline1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="50dp" />
<android.support.constraint.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
guideline1为水平辅助线,开始位置是距离顶部50dp,guideline2位垂直辅助线,开始位置为屏幕宽的0.5(中点位置),效果如下:
5.综合案例
固定百分比高度:
<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=".MainActivity">
<TextView
android:id="@+id/tab_layout"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/colorAccent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHeight_percent="0.06"
tools:ignore="MissingConstraints" />
</android.support.constraint.ConstraintLayout>
<?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">
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
app:layout_constraintGuide_percent=".5"/>
<Button
android:id="@+id/button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/guideline"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:text="Button"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/button" />
<TextView
android:id="@+id/textView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/colorAccent"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/guideline"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
固定百分比:
<?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:cardview="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
<android.support.constraint.Guideline
android:id="@+id/guideline1"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
app:layout_constraintGuide_percent=".05"/>
<android.support.constraint.Guideline
android:id="@+id/guideline2"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
app:layout_constraintGuide_percent=".20"/>
<ImageView
android:id="@+id/iv_portrait"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toRightOf="@+id/guideline1"
app:layout_constraintRight_toLeftOf="@+id/guideline2"
app:layout_constraintDimensionRatio="1:1"
android:orientation="horizontal"
android:src="@mipmap/ic_launcher"
tools:ignore="MissingConstraints" />
<android.support.constraint.Guideline
android:id="@+id/guideline3"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
app:layout_constraintGuide_percent=".25"/>
<android.support.constraint.Guideline
android:id="@+id/guideline4"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".05"/>
<android.support.constraint.Guideline
android:id="@+id/guideline5"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".7"/>
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@+id/guideline4"
app:layout_constraintLeft_toRightOf="@+id/guideline3"
app:layout_constraintRight_toRightOf="parent"
android:text="新闻标题"
android:textColor="@color/blue_light"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="135dp"
tools:layout_editor_absoluteY="16dp" />
<TextView
android:id="@+id/tv_desc"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@+id/guideline5"
app:layout_constraintLeft_toRightOf="@+id/guideline3"
app:layout_constraintRight_toRightOf="parent"
android:text="新闻部分内容"
android:textColor="@android:color/black"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="135dp"
tools:layout_editor_absoluteY="47dp" />
</android.support.constraint.ConstraintLayout>