Android ConstraintLayout 基础
Android ConstraintLayout 基础
- 屏障线 Barrier
- 设置水平和垂直方向的约束关系
- 长宽比
- 链式结构
- 组
- 站位
- 辅助线
- 参考地址
屏障线 Barrier
以下是使用 ConstraintLayout
在 Android 中实现简单屏障线(Barrier)使用的示例代码,主要步骤如下:
首先,在 Android 项目的布局 XML 文件中,将根布局设置为 ConstraintLayout
。例如创建一个名为 activity_main.xml
的布局文件(以下代码基于 Kotlin 语言环境,Java 语言使用方式类似,只是语法上稍有不同):
<?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"
tools:context=".MainActivity">
<!-- 创建两个视图,这里以两个 TextView 为例 -->
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView 1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView 2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView1" />
<!-- 创建屏障 -->
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="textView1,textView2" />
<!-- 再创建一个视图,让它根据屏障来布局 -->
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintStart_toEndOf="@id/barrier"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget ConstraintLayout>
在上述代码中:
- 首先定义了两个
TextView
(textView1
和textView2
),它们都是靠父布局左侧(start
侧)对齐并且垂直排列。 - 接着创建了一个
Barrier
(barrier
),通过app:constraint_referenced_ids
属性指定它关联的视图为textView1
和textView2
,app:barrierDirection="end"
表示这个屏障的方向是在关联视图的右侧(结束侧),会根据关联视图中最右侧的边界来确定自身位置。 - 最后创建了一个
Button
,它的左侧(start
侧)通过app:layout_constraintStart_toEndOf="@id/barrier"
约束到了这个屏障的右侧,这样按钮就会位于两个TextView
的右侧,并且会随着TextView
中靠右侧最远的那个视图位置变化而自适应位置。
https://www.jianshu.com/p/6ee3caaa4135
设置水平和垂直方向的约束关系
-
在XML布局文件中设置约束关系(静态方式)
- 水平方向约束关系:
- 左对齐(start对齐):
- 假设在
ConstraintLayout
中有一个TextView
,要使其左边缘与父布局的左边缘对齐,可以这样设置:
<TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello" app:layout_constraintStart_toStartOf="parent"/>
- 这里
app:layout_constraintStart_toStartOf="parent"
表示将textView
的start
(在从左到右的布局语言环境中相当于左侧)边缘与父布局(parent
)的start
边缘对齐。
- 假设在
- 右对齐(end对齐):
- 例如,要使一个
Button
的右边缘与父布局的右边缘对齐:
<Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Click Me" app:layout_constraintEnd_toEndOf="parent"/>
- 其中
app:layout_constraintEnd_toEndOf="parent"
用于将button
的end
(在从左到右的布局语言环境中相当于右侧)边缘与父布局的end
边缘对齐。
- 例如,要使一个
- 水平居中对齐:
- 对于一个
ImageView
,要使其在父布局中水平居中,可以使用以下约束:
<ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/>
- 通过将
imageView
的start
边缘与父布局的start
边缘对齐,并且end
边缘与父布局的end
边缘对齐,就可以实现水平居中。
- 对于一个
- 左对齐(start对齐):
- 垂直方向约束关系:
- 顶部对齐(top对齐):
- 假设有一个
EditText
,要使其顶部边缘与父布局的顶部边缘对齐:
<EditText android:id="@+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent"/>
- 这里
app:layout_constraintTop_toTopOf="parent"
确保了editText
的top
边缘与父布局的top
边缘对齐。
- 假设有一个
- 底部对齐(bottom对齐):
- 例如,使一个
LinearLayout
的底部边缘与父布局的底部边缘对齐:
<LinearLayout android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent"/>
- 其中
app:layout_constraintBottom_toBottomOf="parent"
实现了linearLayout
的bottom
边缘与父布局的bottom
边缘对齐。
- 例如,使一个
- 垂直居中对齐:
- 对于一个
View
,要使其在父布局中垂直居中,可以这样设置:
<View android:id="@+id/view" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:licensePlateConstraintBottom_toBottomOf="parent"/>
- 通过同时将
view
的top
边缘与父布局的top
边缘对齐,以及bottom
边缘与父布局的bottom
边缘对齐,实现垂直居中。
- 对于一个
- 顶部对齐(top对齐):
- 水平方向约束关系:
-
在Java代码中设置约束关系(动态方式)
- 使用
ConstraintSet
设置水平方向约束关系:- 首先,在
Activity
的onCreate
方法或者其他合适的方法中,获取ConstraintLayout
和要设置约束的视图,以及创建ConstraintSet
对象:
import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity { private ConstraintLayout constraintLayout; private Button button; private ConstraintSet constraintSet; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); constraintLayout = findViewById(R.id.constraint_layout); button = findViewById(R.id.button); constraintSet = new ConstraintSet(); } }
- 左对齐(start对齐):
- 假设要将
button
的start
边缘与父布局的start
边缘对齐,可以这样设置:
constraintSet.clone(constraintLayout); constraintSet.connect(button.getId(), ConstraintSet.START, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintSet.START); constraintSet.applyTo(constraintLayout);
- 首先通过
constraintSet.clone(constraintLayout)
克隆当前布局的约束集。然后使用constraintSet.connect
方法,将button
的START
(左侧)约束连接到父布局(ConstraintLayout.LayoutParams.PARENT_ID
)的START
边缘。最后通过constraintSet.applyTo(constraintLayout)
将修改后的约束应用到布局中。
- 假设要将
- 右对齐(end对齐):
- 要将
button
的end
边缘与父布局的end
边缘对齐,可以使用以下代码:
constraintSet.clone(constraintLayout); constraintSet.connect(button.getId(), ConstraintSet.END, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintSet.END); constraintSet.applyTo(constraintLayout);
- 这里的逻辑与左对齐类似,只是将连接的方向改为
END
(右侧)。
- 要将
- 水平居中对齐:
- 若要使
button
在父布局中水平居中,可以这样设置:
constraintSet.clone(constraintLayout); constraintSet.connect(button.getId(), ConstraintSet.START, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintSet.START); constraintSet.connect(button.getId(), ConstraintSet.END, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintSet.END); constraintSet.applyTo(constraintLayout);
- 通过同时将
button
的START
和END
边缘分别与父布局的START
和END
边缘连接,实现水平居中。
- 若要使
- 首先,在
- 使用
ConstraintSet
设置垂直方向约束关系:- 顶部对齐(top对齐):
- 假设要将
button
的top
边缘与父布局的top
边缘对齐,可以这样设置:
constraintSet.clone(constraintLayout); constraintSet.connect(button.getId(), ConstraintSet.TOP, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintSet.TOP); constraintSet.applyTo(constraintLayout);
- 首先克隆约束集,然后使用
connect
方法将button
的TOP
(顶部)约束连接到父布局的TOP
边缘,最后应用修改后的约束。
- 假设要将
- 底部对齐(bottom对齐):
- 要将
button
的bottom
边缘与父布局的bottom
边缘对齐,可以使用以下代码:
constraintSet.clone(constraintLayout); constraintSet.connect(button.getId(), ConstraintSet.BOTTOM, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintSet.BOTTOM); constraintSet.applyTo(constraintLayout);
- 这里的逻辑与顶部对齐类似,只是将连接的方向改为
BOTTOM
(底部)。
- 要将
- 垂直居中对齐:
- 若要使
button
在父布局中垂直居中,可以这样设置:
constraintSet.clone(constraintLayout); constraintSet.connect(button.getId(), ConstraintSet.TOP, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintSet.TOP); constraintSet.connect(button.getId(), ConstraintSet.BOTTOM, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintSet.BOTTOM); constraintSet.applyTo(constraintLayout);
- 通过同时将
button
的TOP
和BOTTOM
边缘分别与父布局的TOP
和BOTTOM
边缘连接,实现垂直居中。
- 若要使
- 顶部对齐(top对齐):
- 使用
长宽比
-
在XML布局文件中设置长宽比约束(静态方式)
- 使用
app:layout_constraintDimensionRatio
属性:- 例如,对于一个
ImageView
,想要保持其宽度和高度的特定比例(假设为16:9),可以这样设置:
<ImageView android:id="@+id/imageView" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintDimensionRatio="16:9" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"/>
- 这里将
layout_width
和layout_height
都设置为0dp
,这是因为在使用长宽比约束时,需要通过其他约束(如这里的start
、end
、top
、bottom
与父布局的对齐约束)来确定视图的整体尺寸范围,然后按照指定的长宽比来分配宽度和高度。app:layout_constraintDimensionRatio="16:9"
指定了宽度和高度的比例关系。
- 例如,对于一个
- 使用
-
在Java代码中设置长宽比约束(动态方式)
- 使用
ConstraintSet
设置长宽比约束:- 首先,在
Activity
的onCreate
方法或者其他合适的方法中获取ConstraintLayout
和视图,以及创建ConstraintSet
对象。以下以一个Button
为例:
import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity { private ConstraintLayout constraintLayout; private Button button; private ConstraintSet constraintSet; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); constraintLayout = findViewById(R.id.constraint_layout); button = findViewById(R.id.button); constraintSet = new ConstraintSet(); } }
- 假设要为
button
设置长宽比为4:3,可以这样做:
constraintSet.clone(constraintLayout); // 设置长宽比为4:3 constraintSet.setDimensionRatio(button.getId(), "4:3"); // 需要同时设置宽度和高度的约束方式,例如都设置为WRAP_CONTENT constraintSet.constrainWidth(button.getId(), ConstraintSet.WRAP_CONTENT); constraintSet.constrainHeight(button.getId(), ConstraintSet.WRAP_CONTENT); constraintSet.applyTo(constraintLayout);
- 首先通过
constraintSet.clone(constraintLayout)
克隆当前布局的约束集。然后使用constraintSet.setDimensionRatio(button.getId(), "4:3")
设置button
的长宽比为4:3。需要注意的是,同时还要通过constraintSet.constrainWidth
和constraintSet.constrainHeight
设置宽度和高度的约束方式(这里都设置为WRAP_CONTENT
,也可以根据实际情况设置为MATCH_PARENT
或固定尺寸等),最后通过constraintSet.applyTo(constraintLayout)
将修改后的约束应用到布局中。
- 首先,在
- 使用
链式结构
-
链式结构在
ConstraintLayout
中的概念- 在
ConstraintLayout
中,链式结构是一种用于管理多个视图之间布局关系的方式。它允许将一组视图按照线性方式(水平或垂直)排列,并定义它们之间的间距和对齐方式等约束。可以把它想象成一条链,链上的每个环节(视图)都与相邻的环节相互关联,并且整体链的布局受到特定规则的约束。
- 在
-
水平链式结构(Horizontal Chains)
- 创建水平链式结构(XML方式):
- 假设要创建一个水平链式结构,包含三个
TextView
。首先,在ConstraintLayout
布局文件中进行如下设置:
<androidx.constraintlayout.widget.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"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView 1" app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintStart_toStartOf="parent"/> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView 2" app:layout_constraintStart_toEndOf="@id/textView1"/> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView 3" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/textView2"/> </androidx.constraintlayout.widget.ConstraintLayout>
- 在这个例子中:
app:layout_constraintHorizontal_chainStyle="spread"
应用在textView1
上,这定义了水平链的样式为spread
(伸展)。这种样式下,链中的视图会在水平方向上均匀分布,两端的视图分别与父布局的左右边缘对齐。textView1
通过app:layout_constraintStart_toStartOf="parent"
与父布局的左侧对齐。textView2
通过app:layout_constraintStart_toEndOf="@id/textView1"
与textView1
的右侧连接。textView3
通过app:layout_constraintEnd_toEndOf="parent"
与父布局的右侧对齐,并且通过app:layout_constraintStart_toEndOf="@id/textView2"
与textView2
的右侧连接,这样就形成了一个水平链式结构。
- 假设要创建一个水平链式结构,包含三个
- 水平链式结构的样式(
chainStyle
):spread
(伸展)样式:- 如上述示例,视图会均匀分布在水平方向上,并且两端的视图会分别与父布局的左右边缘对齐。如果有剩余空间,会平均分配到每个视图之间的间距中。
spread_inside
(内部伸展)样式:- 与
spread
类似,但两端的视图不会与父布局的边缘对齐,而是链中的视图在除去两端视图与父布局边缘的间距后,在内部均匀分布。例如:
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView 1" app:layout_constraintHorizontal_chainStyle="spread_inside" app:layout_constraintStart_toStartOf="parent"/>
- 这样设置后,
textView1
和其他在链中的视图会在父布局内部更均匀地分布,两端会留出一定的间距。
- 与
packed
(紧凑)样式:- 链中的视图会紧密排列在一起,并且可以通过
app:layout_constraintHorizontal_bias
属性来控制它们在水平方向上相对于链的起始位置的偏移量。例如:
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView 1" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintStart_toStartOf="parent"/>
- 视图会紧凑地排列,并且可以根据需要调整
bias
属性来改变它们在水平方向上的位置。
- 链中的视图会紧密排列在一起,并且可以通过
- 在Java代码中设置水平链式结构:
- 首先,在
Activity
的onCreate
方法中获取ConstraintLayout
和相关视图,并创建ConstraintSet
对象:
import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private ConstraintLayout constraintLayout; private TextView textView1; private TextView textView2; private TextView textView3; private ConstraintSet constraintSet; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); constraintLayout = findViewById(R.id.constraint_layout); textView1 = findViewById(R.id.textView1); textView2 = findViewById(R.id.textView2); textView3 = findViewById(R.id.textView3); constraintSet = new ConstraintSet(); } }
- 假设要将水平链式结构的样式从
spread
改为packed
,可以这样做:
constraintSet.clone(constraintLayout); constraintSet.setHorizontalChainStyle(textView1.getId(), ConstraintSet.CHAIN_PACKED); // 应用修改后的约束 constraintSet.applyTo(constraintLayout);
- 这里通过
constraintSet.setHorizontalChainStyle
方法,将以textView1
为头部的水平链式结构的样式修改为packed
,然后应用到布局中。
- 首先,在
- 创建水平链式结构(XML方式):
-
垂直链式结构(Vertical Chains)
- 创建垂直链式结构(XML方式):
- 例如,要创建一个垂直链式结构,包含三个
Button
,在ConstraintLayout
布局文件中设置如下:
<androidx.constraintlayout.widget.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"> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 1" app:layout_constraintVertical_chainStyle="spread" app:layout_constraintTop_toTopOf="parent"/> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 2" app:layout_constraintTop_toBottomOf="@id/button1"/> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 3" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/button2"/> </androidx.constraintlayout.widget.ConstraintLayout>
- 在这个例子中:
app:layout_constraintVertical_chainStyle="spread"
应用在button1
上,定义了垂直链的样式为spread
(伸展)。在这种样式下,链中的视图会在垂直方向上均匀分布,两端的视图分别与父布局的上下边缘对齐。button1
通过app:layout_constraintTop_toTopOf="parent"
与父布局的顶部对齐。button2
通过app:layout_constraintTop_toBottomOf="@id/button1"
与button1
的底部连接。button3
通过app:layout_constraintBottom_toBottomOf="parent"
与父布局的底部对齐,并且通过app:layout_constraintTop_toBottomOf="@id/button2"
与button2
的底部连接,从而形成一个垂直链式结构。
- 例如,要创建一个垂直链式结构,包含三个
- 垂直链式结构的样式(
chainStyle
):- 垂直链式结构的样式(
spread
、spread_inside
、packed
)与水平链式结构类似,只是方向是垂直的。它们在垂直方向上控制视图的分布和对齐方式。
- 垂直链式结构的样式(
- 在Java代码中设置垂直链式结构:
- 首先,在
Activity
的onCreate
方法中获取ConstraintLayout
和相关视图,并创建ConstraintSet
对象:
import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity { private ConstraintLayout constraintLayout; private Button button1; private Button button2; private Button button3; private ConstraintSet constraintSet; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); constraintLayout = findViewById(R.id.constraint_layout); button1 = findViewById(R.id.button1); button2 = findViewById(R.id.button2); button3 = findViewById(R.id.button3); constraintSet = new ConstraintSet(); } }
- 假设要将垂直链式结构的样式从
spread
改为packed
,可以这样做:
constraintSet.clone(constraintLayout); constraintSet.setVerticalChainStyle(button1.getId(), ConstraintSet.CHAIN_PACKED); // 应用修改后的约束 constraintSet.applyTo(constraintLayout);
- 这里通过
constraintSet.setVerticalChainStyle
方法,将以button1
为头部的垂直链式结构的样式修改为packed
,然后应用到布局中。
- 首先,在
- 创建垂直链式结构(XML方式):
组
-
在XML布局文件中使用组(Groups)
- 创建组的基本语法:
- 在
ConstraintLayout
中,可以使用<androidx.constraintlayout.widget.Group>
标签来创建一个组。例如,要将两个TextView
归为一组,可以这样写:
<androidx.constraintlayout.widget.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"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView 1" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView 2" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textView1"/> <androidx.constraintlayout.widget.Group android:id="@+id/group" android:layout_width="wrap_content" android:layout_height="wrap_content" app:constraint_referenced_ids="textView1,textView2"/> </androidx.constraintlayout.widget.ConstraintLayout>
- 在这个例子中,
<androidx.constraintlayout.widget.Group>
标签有一个app:constraint_referenced_ids
属性,用于指定组内包含的视图的id
。这里将textView1
和textView2
归为一组,组的id
为group
。
- 在
- 控制组的可见性来管理视图可见性:
- 可以通过在Java代码中控制组的可见性,从而同时控制组内所有视图的可见性。例如,在
Activity
的onCreate
方法中:
import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.Group; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private ConstraintLayout constraintLayout; private TextView textView1; private TextView textView2; private Group group; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); constraintLayout = findViewById(R.id.constraint_layout); textView1 = findViewById(R.id.textView1); textView2 = findViewById(R.id.textView2); group = findViewById(R.id.group); // 隐藏组内的所有视图 group.setVisibility(View.GONE); } }
- 当执行
group.setVisibility(View.GONE);
时,组内的textView1
和textView2
都会被隐藏。同样,如果设置为View.VISIBLE
,组内的视图都会显示。
- 可以通过在Java代码中控制组的可见性,从而同时控制组内所有视图的可见性。例如,在
- 创建组的基本语法:
-
在Java代码中创建和管理组(动态方式)
- 创建组并添加视图到组中:
- 首先,在
Activity
的onCreate
方法中获取ConstraintLayout
对象,然后创建一个Group
对象并添加视图到组中。以下是一个示例:
import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.Group; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private ConstraintLayout constraintLayout; private TextView textView1; private TextView textView2; private Group group; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); constraintLayout = findViewById(R.id.constraint_layout); textView1 = findViewById(R.id.textView1); textView2 = findViewById(R.id.textView2); group = new Group(constraintLayout.getContext()); group.setId(View.generateViewId()); group.addView(textView1); group.addView(textView2); constraintLayout.addView(group); } }
- 这里首先创建了一个
Group
对象,然后通过setId
方法为组设置一个唯一的id
。接着使用addView
方法将textView1
和textView2
添加到组中,最后将组添加到ConstraintLayout
中。
- 首先,在
- 控制组的可见性动态管理视图可见性:
- 可以在任何事件处理方法或者需要的地方控制组的可见性。例如,在一个按钮点击事件处理方法中:
public void onButtonClick(View view) { if (group.getVisibility() == View.VISIBLE) { group.setVisibility(View.GONE); } else { group.setVisibility(View.VISIBLE); } }
- 这段代码通过检查组的当前可见性状态,如果是可见的,则将组(以及组内的所有视图)隐藏;如果是隐藏的,则将组(以及组内的所有视图)显示。这样就可以通过组来方便地管理多个视图的可见性。
- 创建组并添加视图到组中:
站位
-
Placeholder在
ConstraintLayout
中的概念Placeholder
是ConstraintLayout
中的一个特殊组件,它主要用于在布局中预留一个位置,这个位置可以在运行时被其他视图替换。就像是在舞台上为某个演员(视图)预留了一个特定的站位,当需要的时候,真正的演员(视图)就可以站到这个位置上。
-
在XML布局文件中使用Placeholder(静态方式)
- 基本使用示例:
- 假设在一个
ConstraintLayout
布局中有一个Placeholder
,并且在合适的时候要用一个TextView
来替换它。首先,在布局文件中定义Placeholder
和TextView
:
<androidx.constraintlayout.widget.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"> <androidx.constraintlayout.widget.Placeholder android:id="@+id/placeholder" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Replaced Text" android:visibility="gone"/> </androidx.constraintlayout.widget.ConstraintLayout>
- 在这个例子中,
Placeholder
通过app:layout_constraintStart_toStartOf="parent"
和app:layout_constraintTop_toTopOf="parent"
约束在父布局的左上角。TextView
的初始可见性设置为gone
,因为它一开始不需要显示,等待替换Placeholder
的时候再显示。
- 假设在一个
- 替换
Placeholder
的操作(在Java代码中实现):- 在
Activity
的onCreate
方法或者其他合适的方法中,进行如下操作来替换Placeholder
:
import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.Placeholder; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private ConstraintLayout constraintLayout; private Placeholder placeholder; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); constraintLayout = findViewById(R.id.constraint_layout); placeholder = findViewById(R.id.placeholder); textView = findViewById(R.id.textView); placeholder.setContentId(textView.getId()); textView.setVisibility(View.VISIBLE); } }
- 首先通过
placeholder.setContentId(textView.getId());
语句将textView
的id
设置给Placeholder
,这就告诉Placeholder
要被textView
替换。然后将textView
的可见性设置为View.VISIBLE
,这样textView
就会显示在原来Placeholder
所在的位置,完成替换操作。
- 在
- 基本使用示例:
-
Placeholder的优势和应用场景
- 优势:
- 布局灵活性:可以在布局设计阶段预先为不同类型的视图预留位置,根据运行时的条件(如用户权限、数据加载情况等)动态地填充合适的视图,而不需要频繁地修改布局结构。
- 代码可读性和可维护性:使得布局和视图替换的逻辑更加清晰。通过
Placeholder
的机制,开发人员可以很容易地理解某个位置上的视图是可以被替换的,并且替换的操作集中在代码中的特定部分,便于维护。
- 应用场景:
- 动态内容展示:例如在一个新闻应用中,根据新闻类型(文字新闻、图片新闻、视频新闻等),可以在一个预留的
Placeholder
位置展示不同的视图来呈现新闻内容。 - 权限相关布局变化:如果一个应用中有部分功能需要特定权限才能使用,当用户权限状态改变时,可以使用
Placeholder
在相同位置替换不同的视图,来显示权限允许或禁止时的不同界面内容。
- 动态内容展示:例如在一个新闻应用中,根据新闻类型(文字新闻、图片新闻、视频新闻等),可以在一个预留的
- 优势:
辅助线
-
Guideline在
ConstraintLayout
中的概念Guideline
是ConstraintLayout
中的一种辅助布局工具,它本质上是一条虚拟的线,用于帮助开发者更精准地定位和约束视图。这条线可以是水平方向的,也可以是垂直方向的,并且可以设置其位置相对于布局的边界(如parent
的边缘)或者相对于布局的百分比位置,为视图的布局提供参考依据。
-
在XML布局文件中使用Guideline(静态方式)
- 创建水平Guideline:
- 例如,要创建一条水平方向的
Guideline
,将其位置设置为距离布局顶部30%
的位置,可以这样写:
<androidx.constraintlayout.widget.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"> <androidx.constraintlayout.widget.Guideline android:id="@+id/horizontalGuideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.3"/> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello" app:layout_constraintTop_toTopOf="@id/horizontalGuideline"/> </androidx.constraintlayout.widget.ConstraintLayout>
- 在这个例子中,
<androidx.constraintlayout.widget.Guideline>
标签用于创建Guideline
。android:orientation="horizontal"
表示这是一条水平方向的线。app:layout_constraintGuide_percent="0.3"
将Guideline
的位置设置为距离布局顶部30%
的高度处。然后TextView
通过app:layout_constraintTop_toTopOf="@id/horizontalGuideline"
将其顶部约束到这条Guideline
的顶部,从而使TextView
的位置与Guideline
相关联。
- 例如,要创建一条水平方向的
- 创建垂直Guideline:
- 假设要创建一条垂直方向的
Guideline
,位于距离布局左侧20%
的位置,代码如下:
<androidx.constraintlayout.widget.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"> <androidx.constraintlayout.widget.Guideline android:id="@+id/verticalGuideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_begin="20%p"/> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Click Me" app:layout_constraintStart_toStartOf="@id/verticalGuideline"/> </androidx.constraintlayout.widget.ConstraintLayout>
- 这里
android:orientation="vertical"
表示是垂直方向的Guideline
。app:layout_constraintGuide_begin="20%p"
将Guideline
的位置设置为距离布局左侧20%
(%p
表示相对于父布局的百分比)。Button
通过app:layout_constraintStart_toStartOf="@id/verticalGuideline"
将其左侧约束到这条Guideline
的左侧,确定了Button
的水平位置。
- 假设要创建一条垂直方向的
- Guideline位置的其他设置方式:
- 除了使用百分比(
app:layout_constraintGuide_percent
和app:layout_constraintGuide_begin
)来设置位置外,还可以将Guideline
直接与布局的边缘对齐。例如,将水平Guideline
与布局底部对齐:
<androidx.constraintlayout.widget.Guideline android:id="@+id/bottomGuideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_end="parentBottom"/>
- 这里
app:layout_constraintGuide_end="parentBottom"
表示将Guideline
的底部与父布局的底部对齐。
- 除了使用百分比(
- 创建水平Guideline:
-
在Java代码中使用Guideline(动态方式)
- 获取和修改Guideline的位置(以垂直Guideline为例):
- 首先,在
Activity
的onCreate
方法中获取ConstraintLayout
和Guideline
对象:
import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.Guideline; import android.os.Bundle; import android.view.View; public class MainActivity extends AppCompatActivity { private ConstraintLayout constraintLayout; private Guideline verticalGuideline; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); constraintLayout = findViewById(R.id.constraint_layout); verticalGuideline = findViewById(R.id.verticalGuideline); } }
- 假设要将垂直
Guideline
的位置从距离左侧20%
修改为30%
,可以这样做:
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.Guideline; import android.os.Bundle; import android.view.View; public class MainActivity extends AppCompatActivity { // 前面代码省略... @Override protected void onCreate(Bundle savedInstanceState) { // 前面代码省略... ConstraintLayout.LayoutParams guidelineParams = (ConstraintLayout.LayoutParams) verticalGuideline.getLayoutParams(); guidelineParams.guidePercent = 0.3f; verticalGuideline.setLayoutParams(guidelineParams); } }
- 首先通过
verticalGuideline.getLayoutParams()
获取Guideline
的布局参数,然后将guidePercent
属性修改为0.3f
(表示30%
),最后通过verticalGuideline.setLayoutParams(guidelineParams)
应用修改后的布局参数,从而改变Guideline
的位置。
- 首先,在
- 获取和修改Guideline的位置(以垂直Guideline为例):
通过使用Guideline
,可以更灵活地控制视图的布局,特别是在需要按照一定比例或者相对于布局边界进行精确布局的情况下,能够大大提高布局的准确性和可维护性。
参考地址
豆包AI