当前位置: 首页 > article >正文

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>

在上述代码中:

  • 首先定义了两个 TextViewtextView1textView2),它们都是靠父布局左侧(start 侧)对齐并且垂直排列。
  • 接着创建了一个 Barrierbarrier),通过 app:constraint_referenced_ids 属性指定它关联的视图为 textView1textView2app:barrierDirection="end" 表示这个屏障的方向是在关联视图的右侧(结束侧),会根据关联视图中最右侧的边界来确定自身位置。
  • 最后创建了一个 Button,它的左侧(start 侧)通过 app:layout_constraintStart_toEndOf="@id/barrier" 约束到了这个屏障的右侧,这样按钮就会位于两个 TextView 的右侧,并且会随着 TextView 中靠右侧最远的那个视图位置变化而自适应位置。

https://www.jianshu.com/p/6ee3caaa4135

设置水平和垂直方向的约束关系

  1. 在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"表示将textViewstart(在从左到右的布局语言环境中相当于左侧)边缘与父布局(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"用于将buttonend(在从左到右的布局语言环境中相当于右侧)边缘与父布局的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"/>
        
        • 通过将imageViewstart边缘与父布局的start边缘对齐,并且end边缘与父布局的end边缘对齐,就可以实现水平居中。
    • 垂直方向约束关系
      • 顶部对齐(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"确保了editTexttop边缘与父布局的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"实现了linearLayoutbottom边缘与父布局的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"/>
        
        • 通过同时将viewtop边缘与父布局的top边缘对齐,以及bottom边缘与父布局的bottom边缘对齐,实现垂直居中。
  2. 在Java代码中设置约束关系(动态方式)

    • 使用ConstraintSet设置水平方向约束关系
      • 首先,在ActivityonCreate方法或者其他合适的方法中,获取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对齐)
        • 假设要将buttonstart边缘与父布局的start边缘对齐,可以这样设置:
        constraintSet.clone(constraintLayout);
        constraintSet.connect(button.getId(), ConstraintSet.START, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintSet.START);
        constraintSet.applyTo(constraintLayout);
        
        • 首先通过constraintSet.clone(constraintLayout)克隆当前布局的约束集。然后使用constraintSet.connect方法,将buttonSTART(左侧)约束连接到父布局(ConstraintLayout.LayoutParams.PARENT_ID)的START边缘。最后通过constraintSet.applyTo(constraintLayout)将修改后的约束应用到布局中。
      • 右对齐(end对齐)
        • 要将buttonend边缘与父布局的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);
        
        • 通过同时将buttonSTARTEND边缘分别与父布局的STARTEND边缘连接,实现水平居中。
    • 使用ConstraintSet设置垂直方向约束关系
      • 顶部对齐(top对齐)
        • 假设要将buttontop边缘与父布局的top边缘对齐,可以这样设置:
        constraintSet.clone(constraintLayout);
        constraintSet.connect(button.getId(), ConstraintSet.TOP, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintSet.TOP);
        constraintSet.applyTo(constraintLayout);
        
        • 首先克隆约束集,然后使用connect方法将buttonTOP(顶部)约束连接到父布局的TOP边缘,最后应用修改后的约束。
      • 底部对齐(bottom对齐)
        • 要将buttonbottom边缘与父布局的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);
        
        • 通过同时将buttonTOPBOTTOM边缘分别与父布局的TOPBOTTOM边缘连接,实现垂直居中。

长宽比

  1. 在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_widthlayout_height都设置为0dp,这是因为在使用长宽比约束时,需要通过其他约束(如这里的startendtopbottom与父布局的对齐约束)来确定视图的整体尺寸范围,然后按照指定的长宽比来分配宽度和高度。app:layout_constraintDimensionRatio="16:9"指定了宽度和高度的比例关系。
  2. 在Java代码中设置长宽比约束(动态方式)

    • 使用ConstraintSet设置长宽比约束
      • 首先,在ActivityonCreate方法或者其他合适的方法中获取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.constrainWidthconstraintSet.constrainHeight设置宽度和高度的约束方式(这里都设置为WRAP_CONTENT,也可以根据实际情况设置为MATCH_PARENT或固定尺寸等),最后通过constraintSet.applyTo(constraintLayout)将修改后的约束应用到布局中。

链式结构

  1. 链式结构在ConstraintLayout中的概念

    • ConstraintLayout中,链式结构是一种用于管理多个视图之间布局关系的方式。它允许将一组视图按照线性方式(水平或垂直)排列,并定义它们之间的间距和对齐方式等约束。可以把它想象成一条链,链上的每个环节(视图)都与相邻的环节相互关联,并且整体链的布局受到特定规则的约束。
  2. 水平链式结构(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代码中设置水平链式结构
      • 首先,在ActivityonCreate方法中获取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,然后应用到布局中。
  3. 垂直链式结构(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
      • 垂直链式结构的样式(spreadspread_insidepacked)与水平链式结构类似,只是方向是垂直的。它们在垂直方向上控制视图的分布和对齐方式。
    • 在Java代码中设置垂直链式结构
      • 首先,在ActivityonCreate方法中获取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,然后应用到布局中。

  1. 在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。这里将textView1textView2归为一组,组的idgroup
    • 控制组的可见性来管理视图可见性
      • 可以通过在Java代码中控制组的可见性,从而同时控制组内所有视图的可见性。例如,在ActivityonCreate方法中:
      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);时,组内的textView1textView2都会被隐藏。同样,如果设置为View.VISIBLE,组内的视图都会显示。
  2. 在Java代码中创建和管理组(动态方式)

    • 创建组并添加视图到组中
      • 首先,在ActivityonCreate方法中获取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方法将textView1textView2添加到组中,最后将组添加到ConstraintLayout中。
    • 控制组的可见性动态管理视图可见性
      • 可以在任何事件处理方法或者需要的地方控制组的可见性。例如,在一个按钮点击事件处理方法中:
      public void onButtonClick(View view) {
          if (group.getVisibility() == View.VISIBLE) {
              group.setVisibility(View.GONE);
          } else {
              group.setVisibility(View.VISIBLE);
          }
      }
      
      • 这段代码通过检查组的当前可见性状态,如果是可见的,则将组(以及组内的所有视图)隐藏;如果是隐藏的,则将组(以及组内的所有视图)显示。这样就可以通过组来方便地管理多个视图的可见性。

站位

  1. Placeholder在ConstraintLayout中的概念

    • PlaceholderConstraintLayout中的一个特殊组件,它主要用于在布局中预留一个位置,这个位置可以在运行时被其他视图替换。就像是在舞台上为某个演员(视图)预留了一个特定的站位,当需要的时候,真正的演员(视图)就可以站到这个位置上。
  2. 在XML布局文件中使用Placeholder(静态方式)

    • 基本使用示例
      • 假设在一个ConstraintLayout布局中有一个Placeholder,并且在合适的时候要用一个TextView来替换它。首先,在布局文件中定义PlaceholderTextView
      <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代码中实现)
      • ActivityonCreate方法或者其他合适的方法中,进行如下操作来替换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());语句将textViewid设置给Placeholder,这就告诉Placeholder要被textView替换。然后将textView的可见性设置为View.VISIBLE,这样textView就会显示在原来Placeholder所在的位置,完成替换操作。
  3. Placeholder的优势和应用场景

    • 优势
      • 布局灵活性:可以在布局设计阶段预先为不同类型的视图预留位置,根据运行时的条件(如用户权限、数据加载情况等)动态地填充合适的视图,而不需要频繁地修改布局结构。
      • 代码可读性和可维护性:使得布局和视图替换的逻辑更加清晰。通过Placeholder的机制,开发人员可以很容易地理解某个位置上的视图是可以被替换的,并且替换的操作集中在代码中的特定部分,便于维护。
    • 应用场景
      • 动态内容展示:例如在一个新闻应用中,根据新闻类型(文字新闻、图片新闻、视频新闻等),可以在一个预留的Placeholder位置展示不同的视图来呈现新闻内容。
      • 权限相关布局变化:如果一个应用中有部分功能需要特定权限才能使用,当用户权限状态改变时,可以使用Placeholder在相同位置替换不同的视图,来显示权限允许或禁止时的不同界面内容。

辅助线

  1. Guideline在ConstraintLayout中的概念

    • GuidelineConstraintLayout中的一种辅助布局工具,它本质上是一条虚拟的线,用于帮助开发者更精准地定位和约束视图。这条线可以是水平方向的,也可以是垂直方向的,并且可以设置其位置相对于布局的边界(如parent的边缘)或者相对于布局的百分比位置,为视图的布局提供参考依据。
  2. 在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>标签用于创建Guidelineandroid: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"表示是垂直方向的Guidelineapp:layout_constraintGuide_begin="20%p"Guideline的位置设置为距离布局左侧20%%p表示相对于父布局的百分比)。Button通过app:layout_constraintStart_toStartOf="@id/verticalGuideline"将其左侧约束到这条Guideline的左侧,确定了Button的水平位置。
    • Guideline位置的其他设置方式
      • 除了使用百分比(app:layout_constraintGuide_percentapp: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的底部与父布局的底部对齐。
  3. 在Java代码中使用Guideline(动态方式)

    • 获取和修改Guideline的位置(以垂直Guideline为例)
      • 首先,在ActivityonCreate方法中获取ConstraintLayoutGuideline对象:
      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,可以更灵活地控制视图的布局,特别是在需要按照一定比例或者相对于布局边界进行精确布局的情况下,能够大大提高布局的准确性和可维护性。

参考地址

豆包AI


http://www.kler.cn/a/403504.html

相关文章:

  • [第五空间 2021]pklovecloud 详细题解
  • css iframe标签使用
  • Parker派克防爆电机在实际应用中的安全性能如何保证?
  • Android12 的 Vold梳理
  • 如何进行Apache的配置与调试?
  • 使用 npm 安装 Electron 作为开发依赖
  • Day03_AJAX原理 (黑马笔记)
  • Python从0到100(七十三):Python OpenCV-OpenCV实现手势虚拟拖拽
  • 2025年软考初级【信息处理技术员】考试大纲
  • SELinux 的端口号权限以及使用 semanage 工具添加权限
  • 《TCP/IP网络编程》学习笔记 | Chapter 12:I/O 复用
  • Ubuntu 22.04 上快速搭建 Samba 文件共享服务器
  • 微信小程序的医院预约挂号系统
  • netcore Kafka
  • 【SQL 实现计算已历完整月份不同日期的场景】
  • JDK安装和Linux常见设置详细版教程
  • springboot第82集:消息队列kafka,kafka-map
  • VRT: 关于视频修复的模型
  • 佛山三水戴尔R740服务器黄灯故障处理
  • 使用docker compose安装部署gitlab
  • SQL 数据库管理:提升数据管理效率的关键
  • 【ChatGPT】如何通过角色扮演让ChatGPT回答更贴合实际场景
  • Android 功耗分析(底层篇)
  • 微服务即时通讯系统的实现(客户端)----(4)
  • CPU和GPU有什么区别,玩游戏哪个更重要?
  • 提升工作效率的好用的IDEA插件