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>
在上述代码中:
- 首先定义了两个
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
,要使其左边缘与父布局的左边缘对齐,可以这样设置:
<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"
表示将textView
的start
(在从左到右的布局语言环境中相当于左侧)边缘与父布局(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"
用于将button
的end
(在从左到右的布局语言环境中相当于右侧)边缘与父布局的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"/>
- 通过将
imageView
的start
边缘与父布局的start
边缘对齐,并且end
边缘与父布局的end
边缘对齐,就可以实现水平居中。
- 对于一个
- 左对齐(start对齐):
- 垂直方向约束关系:
- 顶部对齐(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"
确保了editText
的top
边缘与父布局的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"
实现了linearLayout
的bottom
边缘与父布局的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"/>
- 通过同时将
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;@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对齐):
- 假设要将
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),可以这样设置:
<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_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;@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.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"><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代码中设置水平链式结构:
- 首先,在
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;@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
,然后应用到布局中。
- 首先,在
- 创建水平链式结构(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"><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
):- 垂直链式结构的样式(
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;@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
,然后应用到布局中。
- 首先,在
- 创建垂直链式结构(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"><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
。这里将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;@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);
时,组内的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;@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
方法将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.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代码中实现):- 在
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;@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());
语句将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.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>
标签用于创建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.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"
表示是垂直方向的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.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
的底部与父布局的底部对齐。
- 除了使用百分比(
- 创建水平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;@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的位置(以垂直Guideline为例):
通过使用Guideline
,可以更灵活地控制视图的布局,特别是在需要按照一定比例或者相对于布局边界进行精确布局的情况下,能够大大提高布局的准确性和可维护性。
参考地址
豆包AI
相关文章:
Android ConstraintLayout 基础
Android ConstraintLayout 基础 屏障线 Barrier设置水平和垂直方向的约束关系长宽比链式结构组站位辅助线 参考地址 屏障线 Barrier 以下是使用 ConstraintLayout 在 Android 中实现简单屏障线(Barrier)使用的示例代码,主要步骤如下…...
Ubuntu22.04LTS 部署前后端分离项目
一、安装mysql8.0 1. 安装mysql8.0 # 更新安装包管理工具 sudo apt-get update # 安装 mysql数据库,过程中的选项选择 y sudo apt-get install mysql-server # 启动mysql命令如下 (停止mysql的命令为:sudo service mysql stop࿰…...
【网站推荐】the top trending open-source startups, every quarter
每季度最热门的开源初创公司 我们根据 GitHub 存储库自 2020 年以来的明星增长情况发布热门开源项目,并将其称为 Runa 开源初创公司 (ROSS) 指数。 una Capital actively invests in open-source startups (like Nginx and MariaDB) and considers an active deve…...
Java通过calcite实时读取kafka中的数据
引入maven依赖 <dependency> <groupId>org.apache.calcite</groupId> <artifactId>calcite-kafka</artifactId> <version>1.28.0</version> </dependency> 测试代码 import java.sql.Connection; import java.sql.DriverMan…...
el-table 数据去重后合并表尾合计行,金额千分位分割并保留两位小数,表尾合计行表格合并
问题背景 最近在做后台管理项目el-table 时候需要进行表尾合计,修改合计后文字的样式,合并单元格。 想实现的效果 合并表尾单元格前三列为1格;对某些指定的单元格进行表尾合计;合计后的文本样式加粗;涉及到金额需要千…...
Flutter:RotationTransition旋转动画
配置vsync,需要实现一下with SingleTickerProviderStateMixinclass _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{// 定义 AnimationController late AnimationController _controller;overridevoid initState() {super…...
《Python浪漫的烟花表白特效》
一、背景介绍 烟花象征着浪漫与激情,将它与表白结合在一起,会创造出别具一格的惊喜效果。使用Python的turtle模块,我们可以轻松绘制出动态的烟花特效,再配合文字表白,打造一段专属的浪漫体验。 接下来,让…...
Java面试题分享
1、hashmap的底层设计原理以及扩容规则,是否线程安全,如何线程安全。 jdk1.7以前采用数组加链表结构通过键哈希确定数组下标存键值对。jdk1.8及以后采用数组加链表加红黑树,链表超阈值且数组满足条件会转红黑树,哈希函数先取键 h…...
定时器的小应用
第一个项目 第一步,RCC开启时钟,这个基本上每个代码都是第一步,不用多想,在这里打开时钟后,定时器的基准时钟和整个外设的工作时钟就都会同时打开了 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);第二步&…...
【计算机网络】UDP协议
一、UDP协议格式 1.报头的含义 ① 16位源端口号:自己的端口号 ② 16位目的端口号:对方的端口号 ③ 16位UDP长度:整个数据报(UDP报头UDP有效载荷)的长度,最大64KB 一个UDP最多传64KB的数据,如果要传的数据 > 64K…...
vulhub之log4j
Apache Log4j Server 反序列化命令执行漏洞(CVE-2017-5645) 漏洞简介 Apache Log4j是一个用于Java的日志记录库,其支持启动远程日志服务器。Apache Log4j 2.8.2之前的2.x版本中存在安全漏洞。攻击者可利用该漏洞执行任意代码。 Apache Log4j 在应用程序中添加日志记录最…...
[Unity] 关于引入Google SDK以及使用的方法
在Unity中接入谷歌SDK(如Google Play Games SDK或Firebase SDK等)通常涉及几个关键步骤,包括下载SDK、导入Unity项目、配置项目设置、编写必要的代码以及测试集成。以下是一个基于Firebase SDK接入Unity的示例,同时涵盖了Google P…...
集群聊天服务器(13)redis环境安装和发布订阅命令
目录 环境安装订阅redis发布-订阅的客户端编程环境配置客户端编程 功能测试 环境安装 sudo apt-get install redis-server 先启动redis服务 /etc/init.d/redis-server start默认在6379端口上 redis是存键值对的,还可以存链表、数组等等复杂数据结构 而且数据是在…...
第R4周:LSTM-火灾温度预测(pytorch版)
>- **🍨 本文为[🔗365天深度学习训练营]中的学习记录博客** >- **🍖 原作者:[K同学啊]** 往期文章可查阅: 深度学习总结 任务说明:数据集中提供了火灾温度(Tem1)、一氧化碳浓度…...
基于SpringBoot和uniapp开发的医护上门系统上门护理小程序
项目分析 一、市场需求分析 人口老龄化趋势:随着全球及中国人口老龄化的加剧,老年人口数量显著增加,对医疗护理服务的需求也随之增长。老年人由于身体机能下降,更需要便捷、高效的医护服务,而医护上门服务恰好满足了这…...
js批量输入地址获取经纬度
使用js调用高德地图的接口批量输入地址获取经纬度。 以下的请求接口的key请换成你的key。 创建key:我的应用 | 高德控制台 ,服务平台选择《Web服务》。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-…...
Python自动化测试实践中pytest用到的功能dependency和parametrize
Python自动化测试中pytest用到的功能 1、pytest之@pytest.mark.dependency装饰器设置测试用例之间的依赖关系 1.1说明: 1、这是一个pytest第三方插件,主要解决用例之间的依赖关系。如果依赖的上下文测试用例失败后续的用例会被标识为跳过执行,相当于执行了 pytest.mark.s…...
json-bigint处理前端精度丢失问题
问题描述:前后端调试过程中,有时候会遇到精度丢失的问题,比如后端给过来的id超过16位,就会出现精度丢失的情况,前端拿到的id与后端给过来的不一致。 解决方案: 1、安装 npm i json-bigint 2、在axios中配置…...
神经网络10-Temporal Fusion Transformer (TFT)
Temporal Fusion Transformer (TFT) 是一种专为时序数据建模而设计的深度学习模型,它结合了Transformer架构和其他技术,旨在有效地处理和预测时序数据中的复杂模式。TFT 于 2020 年由 Google Research 提出,旨在解决传统模型在时序预测中的一…...
django基于django的民族服饰数据分析系统的设计与实现
摘 要 随着网络科技的发展,利用大数据分析对民族服饰进行管理已势在必行;该平台将帮助企业更好地理解服饰市场的趋势,优化服装款式,提高服装的质量。 本文讲述了基于python语言开发,后台数据库选择MySQL进行数据的存储…...
html数据类型
数据类型是字面含义,表示各种数据的类型。在任何语言中都存在数据类型,因为数据是各式各样。 1.数值类型 number let a 1; let num 1.1; // 整数小数都是数字值 // 数字肯定有个范围 正无穷大和负无穷大 // Infinity 正无穷大 // -Infinity 负…...
Springboot启动异常 错误: 找不到或无法加载主类 xxx.Application异常
Springboot启动异常 错误: 找不到或无法加载主类 xxx.Application异常 报错提示 Connected to the target VM, address: 127.0.0.1:57210, transport: socket 错误:找不到或无法加载主类 global.hh.manage.HHMicroCloudProviderApplication Disconnected from the target VM, …...
哋它亢SEO技术分析:如何提升网站在搜索引擎中的可见性
文章目录 哋它亢SEO技术分析:如何提升网站在搜索引擎中的可见性网站的基本情况SEO优化分析与建议1. 元数据优化2. 关键词优化3. URL结构4. 图像优化5. 移动端优化6. 网站速度7. 结构化数据(Schema Markup)8. 内链与外链9. 社交分享 哋它亢SEO…...
web——upload-labs——第十一关——黑名单验证,双写绕过
还是查看源码, $file_name str_ireplace($deny_ext,"", $file_name); 该语句的作用是:从 $file_name 中去除所有出现在 $deny_ext 数组中的元素,替换为空字符串(即删除这些元素)。str_ireplace() 在处理时…...
ElasticSearch7.x入门教程之中文分词器 IK(二)
文章目录 前言一、内置分词器二、中文IK分词器(第三方)三、本地自定义四、远程词库总结 前言 ElasticSearch 核心功能就是数据检索,首先通过索引将文档写入 es。 查询分析则主要分为两个步骤: 1、词条化:分词器将输入…...
体积全息及平面全息图的衍射效率
一、体积全息 当记录材料的厚度是条纹间距的若干倍时,则在记录材料体积内将记录下干涉全息图的三维空间分布,就形成了体积全息。 按物光和参考光入射方向和再现方式的不同体积全息可以分为两种。 一种是物光和参考光在记录介质的同一侧入射,得…...
【常用组件整理】
xgplayer 字节开发的前端视频播放器 xgplayer是一个由字节跳动开发的强大的前端视频播放器,具有稳定性高、文档清晰、支持弹幕和移动端优化 等特点。相较于VideoJs,xgplayer的文档更简洁,自定义插件更为便捷。xgplayer还提供了丰富的插件来扩…...
用指针函数寻找数组中的最大值与次大值
#include <stdio.h>// 函数用于找出数组中的最大值和次大值 void LargestTow(int a[], int n, int *pfirst, int *psecond) {*pfirst a[0];*psecond a[1];if (*psecond > *pfirst) {// 如果初始的次大值大于最大值,交换它们int temp *pfirst;*pfirst *…...
原生微信小程序在顶部胶囊左侧水平设置自定义导航兼容各种手机模型
无论是在什么手机机型下,自定义的导航都和右侧的胶囊水平一条线上。如图下 以上图iphone12,13PRo 以上图是没有带黑色扇帘的机型 以下是调试器看的wxml的代码展示 注意:红色阔里的是自定义导航(或者其他的logo啊,返回之…...
Android Gradle自定义任务在打包任务执行完成后执行cmd命令
背景 在每次打包之后需要做某事,例如每次打包后我都会安装某个目录下的一个apk。这个apk是通过一堆shell命令过滤得到一个apk的地址,然后把执行的几个shell命令何必成一个alias指令,在打包后只需要执行alias指令实现功能。当然也可以直接写在…...
http自动发送请求工具(自动化测试http请求)
点击下载《http自动发送请求工具(自动化测试http请求)》 前言 在现代软件开发过程中,HTTP 请求的自动化测试是确保应用程序稳定性和可靠性的关键环节。为了满足这一需求,我开发了一款功能强大且易于使用的自动化 HTTP 请求发送工具。该工具基于 C# 开发…...
解决Docker环境变量的配置的通用方法
我们部署的很多服务都是以Docker容器的形式存在的。 在运行Docker容器前,除了设置网络、数据卷之外,还需要设置各种各样的环境变量。 有时候,由于容器版本的问题,一些文档没有及时更新,可能同时存在多个新旧版本的环…...
SpringBoot3整合Hutool-captcha实现图形验证码
文章目录 验证码需求分析:项目创建import方式的使用说明exclude方式定义接口:接口定义定义 CaptchaController前端代码在整合技术框架的时候,想找一个图形验证码相关的框架,看到很多验证码不在更新了或者是在中央仓库下载不下来,还需要多引入依赖。后面看到了Hutool **图形…...
Spring Boot核心概念:日志管理
日志记录是软件开发的重要组成部分,它帮助开发人员了解应用程序运行时的状态,以及在故障排查和性能监控时提供关键信息。Spring Boot通过提供默认的日志配置,简化了日志管理。 Spring Boot默认日志框架 Spring Boot默认使用Logback作为日志…...
selenium grid 远程webdriver添加上网代理
################## selenium grid config start ####################### # UI自动化测试策略 Grid/Local UIAutomation_TestStrategy Grid selenium_grid_url http://172.16.99.131:4444/wd/hub # Windows XP / linux grid_platformName linux # windows capabilities win…...
Flutter踩坑记录(一)debug运行生成的项目,不能手动点击运行
问题 IOS14设备,切后台划掉,二次启动崩溃。 原因 IOS14以上 flutter 不支持debugger模式下的二次启动 。 要二次启动需要以release方式编译工程安装至手机。 操作步骤 清理项目:在命令行中运行flutter clean来清理之前的构建文件。重新构…...
Spring Boot 项目 myblog 整理
myblog 项目是一个典型的 Spring Boot 项目,主要包括用户注册、登录、文章管理(创建、查询、更新、删除)等功能。 1. 项目结构与依赖设置 项目初始化与依赖 使用 Spring Initializr 创建项目。引入必要的依赖包: Spring Boot W…...
【前端知识】nodejs项目配置package.json深入解读
package.json详细解读 文件解读一、文件结构二、字段详解三、使用场景四、注意事项 组件版本匹配规则 文件解读 package.json 文件是 Node.js 项目中的一个核心配置文件,它位于项目的根目录下,并包含项目的基本信息、依赖关系、脚本、版本等内容。以下是…...
51c嵌入式~IO合集2
我自己的原文哦~ https://blog.51cto.com/whaosoft/11697814 一、STM32串口通信基本原理 通信接口背景知识 设备之间通信的方式 一般情况下,设备之间的通信方式可以分成并行通信和串行通信两种。并行与串行通信的区别如下表所示。 串行通信的分类 1、按照数据传…...
在应用启动时,使用 UniApp 提供的 API 检查和请求权限。
在使用 UniApp 开发 App 时,如果你需要在应用启动时提示用户获取本地媒体权限,可以按照以下步骤操作: 1. 明确需要的权限 要访问本地媒体(如相机、麦克风或文件存储),需要申请以下权限: Andr…...
前端知识点---伪数组是什么 , 伪数组如何转换为真数组(Javascript)
伪数组是什么 , 伪数组如何转换为真数组(Javascript) 在 JavaScript 中,伪数组对象是具有类似数组特性的对象,但并不是数组(即不继承 Array.prototype)。这些对象通常有一个 length 属性以及以数字索引为键的属性,但不…...
嵌入式 UI 开发的开源项目推荐
嵌入式开发 UI 难吗?你的痛点我懂!作为嵌入式开发者,你是否也有以下困扰?设备资源太少,功能和美观只能二选一?调试效率低,每次调整都要反复烧录和测试?开发周期太长,让你…...
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
在 C编程的世界里,智能指针无疑是管理内存资源的得力助手。它们为我们自动处理内存的分配与释放,极大地减少了因手动管理内存而可能引发的诸如内存泄漏、悬空指针等棘手问题。然而,就像任何工具都有其两面性一样,智能指针在带来便…...
28.<Spring博客系统⑤(部署的整个过程(CentOS))>
引入依赖 Spring-boot-maven-plugin 用maven进行打包的时候必须用到这个插件。看看自己pom.xml中有没有这个插件 并且看看配置正确不正常。 注:我们这个项目打的jar包在30MB左右。 <plugin><groupId>org.springframework.boot</groupId><artif…...
mongodb多表查询,五个表查询
需求是这样的,而数据是从mysql导入进来的,由于mysql不支持数组类型的数据,所以有很多关联表。药剂里找药物,需要药剂与药物的关联表,然后再找药物表。从药物表里再找药物与成分关联表,最后再找成分表。 这里…...
服务器端渲染 (SSR) 与客户端渲染 (CSR)
嘿程序员!我们都知道,新时代的 Javascript 已经彻底改变了现代网站的结构和用户体验。如今,网站的构建更像是一个应用程序,伪装成一个能够发送电子邮件、通知、聊天、购物、支付等的网站。今天的网站是如此先进、互动,…...
【已解决】“EndNote could not connect to the online sync service”问题的解决
本人不止一次在使用EndNote软件时遇到过“EndNote could not connect to the online sync service”这个问题。 过去遇到这个问题都是用这个方法来解决: 这个方法虽然能解决,但工程量太大,每次做完得歇半天身体才能缓过来。 后来再遇到该问…...
HTML5拖拽API学习 托拽排序和可托拽课程表
文章目录 前言拖拽API核心概念拖拽式使用流程例子注意事项综合例子🌰 可拖拽课程表拖拽排序 前言 前端拖拽功能让网页元素可以通过鼠标或触摸操作移动。HTML5 提供了标准的拖拽API,简化了拖放操作的实现。以下是拖拽API的基本使用指南: 拖拽…...
sed使用扩展正则表达式时, -i 要写在 -r 或 -E 的后面
sed使用扩展正则表达式时, -i 要写在 -r 或 -E 的后面 前言 -r 等效 -E , 启用扩展正则表达式 -E是新叫法,更统一,能增强可移植性 , 但老系统,比如 CentOS-7 的 sed 只能用 -r ### Ubuntu24.04-E, -r, --regexp-extendeduse extended regular expressions in the script(fo…...
CSS中Flex布局应用实践总结
① 两端对齐 比如 要求ul下的li每行四个,中间间隔但是需要两段对齐,如下图所示: 这是除了基本的flex布局外,还需要用到:nth-of-type伪类来控制每行第一个与第四个的padding。 .hl_list{width: 100%;display: flex;align-items…...