约束布局ConstraintLayout使用详解
从 Android Studio 2.3起,官方的模板默认使用 ConstraintLayout。ConstraintLayout 官方文档,之前项目中用的比较少,有些属性不是很熟练,做个笔记方便查找
相对定位的常用属性:
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
注意点:
- 对于一个view,使用布局必须要设置水平方向及垂直方向的定位属性,不然会报错。
- 设置同一方向设置,比如水平方向,仅设置constraintLeft则会为左对齐,仅设置constraintRight则会右对齐,两者都设置默认居中对齐。如果不想居中对齐,则需要设置属性
layout_constraintHorizontal_bias
范围为0~1,默认居中为0.5.
layout_constraintVertical_bias
垂直偏移
两个TextView
的高度不一致,但是又希望他们文本对齐,这个时候就可以使用layout_constraintBaseline_toBaselineOf
边距
常用margin ConstraintLayout的边距常用属性如下:
android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom
我们只有设置了相应的约束margin才有效,如设置了layout_constraintLeft_toLeftOf
或者
layout_constraintLeft_toRightOf
后layout_marginLeft
才会生效。
goneMargin
goneMargin
主要用于约束的控件可见性被设置为gone
的时候,使用的margin值是否有效,属性如下:
layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
尺寸约束
控件的尺寸可以通过四种不同方式指定:
1. 使用指定的尺寸
2.使用wrap_content
,让控件自己计算大小
当控件的高度或宽度为wrap_content时,可以使用下列属性来控制最大、最小的高度或宽度:
android:minWidth
最小的宽度
android:minHeight
最小的高度
android:maxWidth
最大的宽度
android:maxHeight
最大的高度
注意!当ConstraintLayout为1.1版本以下时,使用这些属性需要加上强制约束,如下所示:
app:constrainedWidth=”true”
app:constrainedHeight=”true”
3.使用 0dp (MATCH_CONSTRAINT)
官方不推荐在ConstraintLayout中使用match_parent
,可以设置 0dp (MATCH_CONSTRAINT) 配合约束代替match_parent
4.宽高比
当宽或高至少有一个尺寸被设置为0dp时,可以通过属性layout_constraintDimensionRatio
设置宽高比
app:layout_constraintDimensionRatio="H,2:3"指的是 高:宽=2:3
app:layout_constraintDimensionRatio="W,2:3"指的是 宽:高=2:3
链
如果两个或以上控件通过下图的方式约束在一起,就可以认为是他们是一条链(图为横向的链,纵向同理)。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="text1"
android:background="@color/colorAccent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/text2"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="text2"
android:background="@color/colorPrimary"
app:layout_constraintStart_toEndOf="@id/text1"
app:layout_constraintEnd_toStartOf="@id/text3"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="text3"
android:background="#921"
app:layout_constraintStart_toEndOf="@id/text2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
layout_constraintHorizontal_chainStyle
默认为spread
,效果如图
另外两个取值packed
spread_inside
辅助工具
Guideline
Guildline是一条辅助线,帮助你完成布局但它不会显示在界面上。
Guildline的主要属性:
android:orientation
:垂直vertical
,水平horizontal
layout_constraintGuide_begin
指定位置距离开始
layout_constraintGuide_end
指定位置距离结束
layout_constraintGuide_percent
距离顶部的百分比(orientation = horizontal时则为距离左边)
Barrier
假设有3个控件ABC,C在AB的右边,但是AB的宽是不固定的,这个时候C无论约束在A的右边或者B的右边都不对。当出现这种情况可以用Barrier来解决。Barrier可以在多个控件的一侧建立一个屏障,如下所示:
Barrier
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/colorAccent"
android:padding="10dp"
android:text="text1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:padding="10dp"
android:text="this is the text2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text1" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="text1,text2" />
<TextView
android:id="@+id/text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#872"
android:padding="10dp"
android:text="text3"
app:layout_constraintLeft_toRightOf="@+id/barrier" />
</androidx.constraintlayout.widget.ConstraintLayout>
效果如下
app:barrierDirection
为屏障所在的位置,可设置的值有:bottom
、end
、left
、right
、start
、top
app:constraint_referenced_ids
为屏障引用的控件,可设置多个,用“,”隔开
Group
Group可以把多个控件归为一组,方便隐藏或显示一组控件,举个例子:
<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="text1,text3" />
设置group
的visibility
为invisible
,则text1与text3均不可见。
Placeholder
Placeholder
指的是占位符,可以定义一个位置,当给Placeholder
使用setContentId()
设置另一个控件的id,使这个控件移动到占位符的位置了
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<Button
android:id="@+id/left_btn"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="left_top"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:onClick="clickview"
/>
<Button
android:id="@+id/right_btn"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="right_top"
android:textColor="@android:color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:onClick="clickview"/>
<Button
android:id="@+id/left_bot_btn"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="left_bot"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:onClick="clickview"/>
<Button
android:id="@+id/right_bot_btn"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="right_bot"
android:textColor="@android:color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:onClick="clickview"/>
<androidx.constraintlayout.widget.Placeholder
android:id="@+id/place_holder"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="right"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
在Activity中设置
placeholder=findViewById(R.id.place_holder);
public void clickview(View view){
placeholder.setContentId(view.getId());
}
实现点击四个角的那一个按钮,那么该按钮就会显示在正中间