目录

android-ConstraintLayout布局-实战打造复杂界面的最佳实践

目录

android ConstraintLayout布局 实战:打造复杂界面的最佳实践

ConstraintLayout 的核心思想是通过 约束( Constraints ) 来定义视图之间的关系。每个视图都需要在水平和垂直方向上至少有一个约束,否则视图会默认放置在左上角(0,0)位置。

约束的类型

相对于父布局的约束 :将视图的边与父布局的边对齐。

加粗样式 相对于其他视图的约束:将视图的边与其他视图的边对齐。

引导线(Guideline) :一种不可见的辅助线,用于创建动态约束。

屏障(Barrier) :根据一组视图的动态位置自动调整约束。

链(Chain) :将多个视图在水平或垂直方向上连接起来,形成一种特殊的关系。

build.gradle 中添加 ConstraintLayout 的依赖:

dependencies {
    implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
}

下面我会通过 详细的示例 来讲解 ConstraintLayout 的使用,涵盖基本布局、引导线、链、屏障、组以及动态修改约束等内容。每个示例都会附带代码和说明。

1. 基本布局示例

目标:实现一个简单的界面,包含两个按钮和一个文本框。

按钮1位于左上角。

按钮2位于右上角。

文本框位于按钮1和按钮2的下方,水平居中。

代码:

<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">

    <!-- 按钮1:左上角 -->
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 1"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_marginTop="16dp"
        android:layout_marginStart="16dp"/>

    <!-- 按钮2:右上角 -->
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 2"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"/>

    <!-- 文本框:水平居中,位于按钮1和按钮2的下方 -->
    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Hello, ConstraintLayout!"
        android:gravity="center"
        android:padding="16dp"
        app:layout_constraintTop_toBottomOf="@id/button1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

说明:

按钮1和按钮2分别通过 app:layout_constraintTop_toTopOfapp:layout_constraintStart_toStartOf (或 **app:layout_constraintEnd_toEndOf)**约束到父布局的顶部和左右边缘。

文本框通过 app:layout_constraintTop_toBottomOf 约束到按钮1的下方,并通过 app:layout_constraintStart_toStartOfapp:layout_constraintEnd_toEndOf 实现水平居中。

2. 引导线(Guideline)示例

**目标:使用垂直引导线将界面分为左右两部分,左侧放置一个按钮,右侧放置一个文本框。

代码:**

<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">

    <!-- 垂直引导线,位于父布局的50%位置 -->
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5"/>

    <!-- 按钮:位于引导线左侧 -->
    <Button
        android:id="@+id/button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/guideline"
        android:layout_marginTop="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"/>

    <!-- 文本框:位于引导线右侧 -->
    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="This is the right side."
        android:gravity="center"
        android:padding="16dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toEndOf="@id/guideline"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

说明

引导线通过 app:layout_constraintGuide_percent=“0.5” 将界面分为左右两部分。

按钮的 app:layout_constraintEnd_toStartOf 约束到引导线,文本框的 app:layout_constraintStart_toEndOf 约束到引导线。

3. 链(Chain)示例

**目标:创建水平链,包含三个按钮,均匀分布。

代码:**

<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">

    <!-- 按钮1:链的起始 -->
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 1"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/button2"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="8dp"/>

    <!-- 按钮2:链的中间 -->
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 2"
        app:layout_constraintStart_toEndOf="@id/button1"
        app:layout_constraintEnd_toStartOf="@id/button3"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"/>

    <!-- 按钮3:链的结束 -->
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 3"
        app:layout_constraintStart_toEndOf="@id/button2"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="16dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

说明:

通过 app:layout_constraintHorizontal_chainStyle=“spread” 设置链的类型为均匀分布。

每个按钮通过 app:layout_constraintStart_toEndOfapp:layout_constraintEnd_toStartOf 连接到下一个按钮。

**4. 屏障(Barrier)示例

目标:根据两个按钮的动态宽度,创建一个屏障,使文本框始终位于较长的按钮下方。

代码:**

<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">

    <!-- 按钮1 -->
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Short Button"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_marginTop="16dp"
        android:layout_marginStart="16dp"/>

    <!-- 按钮2 -->
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Longer Button Text"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toEndOf="@id/button1"
        android:layout_marginTop="16dp"
        android:layout_marginStart="16dp"/>

    <!-- 屏障:位于按钮1和按钮2的结束边 -->
    <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="button1,button2"/>

    <!-- 文本框:位于屏障下方 -->
    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="This is below the longer button."
        android:gravity="center"
        android:padding="16dp"
        app:layout_constraintTop_toBottomOf="@id/barrier"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="16dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

说明:

屏障通过 app:barrierDirection=“end” 动态调整位置,始终位于按钮1和按钮2的结束边。

文本框通过 app:layout_constraintTop_toBottomOf 约束到屏障的下方。

5. 动态修改约束

**目标:在代码中动态修改按钮的位置。

代码:**

ConstraintLayout constraintLayout = findViewById(R.id.constraintLayout);
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(constraintLayout);

// 将按钮1移动到父布局的右下角
constraintSet.connect(R.id.button1, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 16);
constraintSet.connect(R.id.button1, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 16);
constraintSet.applyTo(constraintLayout);

说明:

使用 ConstraintSet 动态修改按钮的约束,将其移动到右下角。

通过这些示例,你可以掌握 ConstraintLayout 的核心用法和高级功能。