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 为例 --><TextViewandroid: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" /><TextViewandroid: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.Barrierandroid:id="@+id/barrier"android:layout_width="wrap_content"android:layout_height="wrap_content"app:barrierDirection="end"app:constraint_referenced_ids="textView1,textView2" /><!-- 再创建一个视图,让它根据屏障来布局 --><Buttonandroid: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,要使其左边缘与父布局的左边缘对齐,可以这样设置:
        <TextViewandroid: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的右边缘与父布局的右边缘对齐:
        <Buttonandroid: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,要使其在父布局中水平居中,可以使用以下约束:
        <ImageViewandroid: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,要使其顶部边缘与父布局的顶部边缘对齐:
        <EditTextandroid: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的底部边缘与父布局的底部边缘对齐:
        <LinearLayoutandroid: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,要使其在父布局中垂直居中,可以这样设置:
        <Viewandroid: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;@Overrideprotected 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),可以这样设置:
      <ImageViewandroid: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;@Overrideprotected 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"><TextViewandroid: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"/><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="TextView 2"app:layout_constraintStart_toEndOf="@id/textView1"/><TextViewandroid: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类似,但两端的视图不会与父布局的边缘对齐,而是链中的视图在除去两端视图与父布局边缘的间距后,在内部均匀分布。例如:
        <TextViewandroid: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属性来控制它们在水平方向上相对于链的起始位置的偏移量。例如:
        <TextViewandroid: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;@Overrideprotected 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"><Buttonandroid: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"/><Buttonandroid:id="@+id/button2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Button 2"app:layout_constraintTop_toBottomOf="@id/button1"/><Buttonandroid: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;@Overrideprotected 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"><TextViewandroid: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"/><TextViewandroid: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.Groupandroid: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;@Overrideprotected 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;@Overrideprotected 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.Placeholderandroid:id="@+id/placeholder"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"/><TextViewandroid: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;@Overrideprotected 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.Guidelineandroid:id="@+id/horizontalGuideline"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.3"/><TextViewandroid: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.Guidelineandroid:id="@+id/verticalGuideline"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_begin="20%p"/><Buttonandroid: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.Guidelineandroid: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;@Overrideprotected 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 {// 前面代码省略...@Overrideprotected 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.mzph.cn/news/886770.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NLP论文速读(多伦多大学)|利用人类偏好校准来调整机器翻译的元指标

论文速读|MetaMetrics-MT: Tuning Meta-Metrics for Machine Translation via Human Preference Calibration 论文信息&#xff1a; 简介&#xff1a; 本文的背景是机器翻译&#xff08;MT&#xff09;任务的评估。在机器翻译领域&#xff0c;由于不同场景和语言对的需求差异&a…

AJAX学习(24.11.1-24.11.14)(包含HTTP协议)

AJAX学习&#xff08;24.11.1-11.14) 来源&#xff1a; 传智 | 高校学习平台-首页 传智播课&#xff1a;黑马程序员 1.服务器和客户端 1.服务器&#xff1a;存放和对外提供资源的电脑。 2.客户端&#xff08;用户&#xff09;&#xff1a;获取和消费资源的电脑。&#xff0…

好用的js组件库

lodash https://www.lodashjs.com/https://www.lodashjs.com/ uuid 用于生成随机数&#xff0c;常用于生成id标识 GitHub - uuidjs/uuid: Generate RFC-compliant UUIDs in JavaScripthttps://github.com/uuidjs/uuid dayjs 常用于时间的处理 安装 | Day.js中文网 (fenxi…

基于麒麟服务器操作系统V10版本,部署Nginx服务、MySql服务搭建PHP环境,实现静态网站平台的搭建。

一、环境准备 关闭防火墙。 查看当前防火墙的状态 systemctl status firewalld Copy 如果防火墙的状态参数是inactive,则防火墙为关闭状态。 如果防火墙的状态参数是active,则防火墙为开启状态。 关闭防火墙。 如果您想临时关闭防火墙,需要运行以下命令: systemctl…

[JavaWeb] 尚硅谷JavaWeb课程笔记

1 Tomcat服务器 Tomcat目录结构 bin&#xff1a;该目录下存放的是二进制可执行文件&#xff0c;如果是安装版&#xff0c;那么这个目录下会有两个exe文件&#xff1a;tomcat10.exe、tomcat10w.exe&#xff0c;前者是在控制台下启动Tomcat&#xff0c;后者是弹出GUI窗口启动To…

SRP 实现 Cook-Torrance BRDF

写的很乱&#xff01; BRDF&#xff08;Bidirectional Reflectance Distribution Function&#xff09;全称双向反射分布函数。辐射量单位非常多&#xff0c;这里为方便直观理解&#xff0c;会用非常不严谨的光照强度来解释说明。 BRDF光照模型&#xff0c;上反射率公式&#…

向量数据库FAISS之五:原理(LSH、PQ、HNSW、IVF)

1.Locality Sensitive Hashing (LSH) 使用 Shingling MinHashing 进行查找 左侧是字典&#xff0c;右侧是 LSH。目的是把足够相似的索引放在同一个桶内。 LSH 有很多的版本&#xff0c;很灵活&#xff0c;这里先介绍第一个版本&#xff0c;也是原始版本 Shingling one-hot …

基于YOLOv8深度学习的无人机航拍小目标检测系统(PyQt5界面+数据集+训练代码)

本研究提出并实现了一种基于YOLOv8深度学习模型的无人机航拍小目标检测系统&#xff0c;旨在解决高空环境下汽车目标检测的技术难题。随着无人机技术的发展&#xff0c;航拍图像已广泛应用于交通监控、城市管理、灾害应急等多个领域。然而&#xff0c;由于无人机通常在较高的飞…

LeetCode 热题 100 回顾

目录 一、哈希部分 1.两数之和 &#xff08;简单&#xff09; 2.字母异位词分组 &#xff08;中等&#xff09; 3.最长连续序列 &#xff08;中等&#xff09; 二、双指针部分 4.移动零 &#xff08;简单&#xff09; 5.盛最多水的容器 &#xff08;中等&#xff09; 6…

使用 PyTorch 实现 ZFNet 进行 MNIST 图像分类

在本篇博客中&#xff0c;我们将通过两个主要部分来演示如何使用 PyTorch 实现 ZFNet&#xff0c;并在 MNIST 数据集上进行训练和测试。ZFNet&#xff08;ZFNet&#xff09;是基于卷积神经网络&#xff08;CNN&#xff09;的图像分类模型&#xff0c;广泛用于图像识别任务。 环…

【计算机网络实验】之静态路由配置

【计算机网络实验】之静态路由配置 实验题目实验目的实验任务实验设备实验环境实验步骤路由器配置设置静态路由测试路由器之间的连通性配置主机PC的IP测试 实验题目 静态路由协议的配置 实验目的 熟悉路由器工作原理和机制&#xff1b;巩固静态路由理论&#xff1b;设计简单…

driver.js实现页面操作指引

概述 在访问某些网站的时候&#xff0c;第一次进去你会发现有个操作指引&#xff0c;本文引用driver.js&#xff0c;教你在你的页面也加入这般高大上的操作指引。 实现效果 实现 driver.js简介 driver.js是一个功能强大且高度可定制的基于原生JavaScript开发的新用户引导库…

无人机航测技术算法概述!

一、核心技术 传感器技术&#xff1a; GPS/GLONASS&#xff1a;无人机通过卫星定位系统实现高精度的飞行控制和数据采集。 高清相机&#xff1a;用于拍摄地面图像&#xff0c;通过后续图像处理生成三维模型。 激光雷达&#xff08;LiDAR&#xff09;&#xff1a;通过激光扫…

Docker 基础命令介绍和常见报错解决

介绍一些 docker 可能用到的基础命令&#xff0c;并解决三个常见报错&#xff1a; 权限被拒绝&#xff08;Permission Denied&#xff09;无法连接到 Docker 仓库&#xff08;Timeout Exceeded&#xff09;磁盘空间不足&#xff08;No Space Left on Device&#xff09; 命令以…

Java RPC框架的接口预热原理及无损实现

&#x1f680; 博主介绍&#xff1a;大家好&#xff0c;我是无休居士&#xff01;一枚任职于一线Top3互联网大厂的Java开发工程师&#xff01; &#x1f680; &#x1f31f; 在这里&#xff0c;你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人&#xff0c;我不仅热衷…

java的强,软,弱,虚引用介绍以及应用

写在前面 本文看下Java的强&#xff0c;软&#xff0c;弱&#xff0c;虚引用相关内容。 1&#xff1a;各种引用介绍 顶层类是java.lang.ref.Reference,注意是一个抽象类&#xff0c;而不是接口&#xff0c;其中比较重要的引用队列ReferenceQueue就在该类中定义&#xff0c;子…

已有docker增加端口号,不用重新创建Docker

已有docker增加端口号&#xff0c;不用重新创建Docker 1. 整体描述2. 具体实现2.1 查看容器id2.2 停止docker服务2.3 修改docker配置文件2.4 重启docker服务 3. 总结 1. 整体描述 docker目前使用的非常多&#xff0c;但是每次更新都需要重新创建docker&#xff0c;也不太方便&…

jmeter常用配置元件介绍总结之断言

系列文章目录 1.windows、linux安装jmeter及设置中文显示 2.jmeter常用配置元件介绍总结之安装插件 3.jmeter常用配置元件介绍总结之线程组 4.jmeter常用配置元件介绍总结之函数助手 5.jmeter常用配置元件介绍总结之取样器 6.jmeter常用配置元件介绍总结之jsr223执行pytho…

OpenLayers教程12_WebGL自定义着色器:实现高级渲染效果

在 OpenLayers 中使用 WebGL 自定义着色器实现高级渲染效果 目录 一、引言二、WebGL 自定义着色器的优势三、示例应用&#xff1a;实现动态渲染效果 1. 项目结构2. 主要代码实现3. 运行与效果 四、代码讲解与扩展 1. 动态圆的半径和填充颜色2. 动态透明度与边框效果 五、总结…

Axure二级菜单下拉交互实例

1.使用boxlabe进行基础布局 2.设置鼠标悬浮和选中状态 3.转换为动态面板 选中所有二级菜单,进行按钮组转换 选中所有二级菜单,进行动态面板转换 4.给用户管理增加显示/隐藏事件 1)选择toggle代表上拉和下拉切换加载 2)勾选Bring to Front,并选择Push/Pull Widgets代表收缩时…