CoordinatorLayout基本使用与分析——水平偏移(Horizontal Bias)

ini 复制代码
<?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">

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.25" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.50" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.75" />

    <TextView
        android:id="@+id/left"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:background="@color/color_10"
        android:gravity="center"
        android:text="A"
        android:textSize="48sp"
        app:layout_constraintBottom_toBottomOf="@+id/guideline1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/right"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:background="@color/color_10"
        android:gravity="center"
        android:text="B"
        android:textSize="48sp"
        app:layout_constraintBottom_toBottomOf="@+id/guideline1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <TextView
        android:id="@+id/t1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/color_3"
        android:gravity="center"
        android:text="bias=0.5"
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/right"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@id/left"
        app:layout_constraintTop_toTopOf="@id/left"
        app:layout_constraintWidth_min="120dp" />

    <TextView
        android:id="@+id/t2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/color_3"
        android:gravity="center"
        android:text="bias=0"
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/right"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintStart_toEndOf="@id/left"
        app:layout_constraintTop_toBottomOf="@id/t1"
        app:layout_constraintWidth_min="120dp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/color_3"
        android:gravity="center"
        android:text="bias=1"
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/right"
        app:layout_constraintHorizontal_bias="1"
        app:layout_constraintStart_toEndOf="@id/left"
        app:layout_constraintTop_toBottomOf="@id/t2"
        app:layout_constraintWidth_min="120dp" />


    <TextView
        android:id="@+id/left1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/color_11"
        android:gravity="center"
        android:textSize="48sp"
        app:layout_constraintBottom_toBottomOf="@+id/guideline2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/guideline1"
        app:layout_constraintWidth_percent="0.5" />

    <TextView
        android:id="@+id/right1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/color_11"
        android:gravity="center"
        android:textSize="48sp"
        app:layout_constraintBottom_toBottomOf="@+id/guideline2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@id/guideline1"
        app:layout_constraintWidth_percent="0.5" />

    <TextView
        android:id="@+id/t12"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/color_7"
        android:gravity="center"
        android:text="bias====0.5"
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/right1"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@id/left1"
        app:layout_constraintTop_toTopOf="@id/left1"
        app:layout_constraintWidth_min="120dp" />


    <TextView
        android:id="@+id/t22"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:background="@color/color_7"
        android:gravity="center"
        android:text="bias====0"
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/right1"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintStart_toEndOf="@id/left1"
        app:layout_constraintTop_toBottomOf="@id/t12"
        app:layout_constraintWidth_min="120dp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:background="@color/color_7"
        android:gravity="center"
        android:text="bias====1"
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/right1"
        app:layout_constraintHorizontal_bias="1"
        app:layout_constraintStart_toEndOf="@id/left1"
        app:layout_constraintTop_toBottomOf="@id/t22"
        app:layout_constraintWidth_min="120dp" />

    <TextView
        android:id="@+id/left2"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:background="@color/color_12"
        android:gravity="center"
        android:text="A"
        android:textSize="48sp"
        app:layout_constraintBottom_toBottomOf="@id/guideline3"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/guideline2" />

    <TextView
        android:id="@+id/right2"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:background="@color/color_12"
        android:gravity="center"
        android:text="B"
        android:textSize="48sp"
        app:layout_constraintBottom_toBottomOf="@id/guideline3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@id/guideline2" />

    <TextView
        android:id="@+id/t13"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/color_7"
        android:gravity="center"
        android:singleLine="true"
        android:text="bias=0.5"
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/right2"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@id/left2"
        app:layout_constraintTop_toTopOf="@id/left2"
        app:layout_constraintWidth_min="120dp" />

    <TextView
        android:id="@+id/t23"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:background="@color/color_7"
        android:gravity="center"
        android:singleLine="true"
        android:text="bias=0"
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/right2"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintStart_toEndOf="@id/left2"
        app:layout_constraintTop_toBottomOf="@id/t13"
        app:layout_constraintWidth_min="120dp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:background="@color/color_7"
        android:gravity="center"
        android:maxLines="1"
        android:text="========bias=1==========="
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/right2"
        app:layout_constraintHorizontal_bias="1"
        app:layout_constraintStart_toEndOf="@id/left2"
        app:layout_constraintTop_toBottomOf="@id/t23"
        app:layout_constraintWidth_min="120dp" />


    <TextView
        android:id="@+id/left3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/color_1"
        android:gravity="center"
        android:text="A"
        android:textSize="48sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/guideline3"
        app:layout_constraintWidth_percent="0.5" />


    <TextView
        android:id="@+id/t14"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/color_3"
        android:gravity="center"
        android:text="bias=0"
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/left3"
        app:layout_constraintHorizontal_bias="0.582"
        app:layout_constraintStart_toEndOf="@id/left3"
        app:layout_constraintTop_toTopOf="@id/left3"
        app:layout_constraintWidth_min="120dp" />

    <TextView
        android:id="@+id/t24"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/color_3"
        android:gravity="center"
        android:text="bias=0"
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/left3"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintStart_toEndOf="@id/left3"
        app:layout_constraintTop_toBottomOf="@id/t14"
        app:layout_constraintWidth_min="120dp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/color_3"
        android:gravity="center"
        android:text="bias=1"
        android:textSize="32sp"
        app:layout_constraintEnd_toStartOf="@id/left3"
        app:layout_constraintHorizontal_bias="1"
        app:layout_constraintStart_toEndOf="@id/left3"
        app:layout_constraintTop_toBottomOf="@id/t24"
        app:layout_constraintWidth_min="120dp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/color_8"
        android:gravity="center"
        android:text="锚点相同,bias无效"
        android:textSize="32sp"
        app:layout_constraintEnd_toEndOf="@id/left3"
        app:layout_constraintHorizontal_bias="1"
        app:layout_constraintStart_toEndOf="@id/left3"
        app:layout_constraintTop_toBottomOf="@id/t24"
        app:layout_constraintWidth_min="120dp" />

</androidx.constraintlayout.widget.ConstraintLayout>

这个布局是一个展示 ConstraintLayout水平偏移(Horizontal Bias) 特性的示例,通过多条水平辅助线将屏幕分为四个区域,每个区域展示不同条件下偏移值对控件位置的影响。以下是详细解析:

1. 根布局与辅助线(Guideline)

xml

xml 复制代码
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 3条水平辅助线,将屏幕垂直分为4个区域 -->
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline1"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.25" />  <!-- 25%高度处 -->

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.50" />  <!-- 50%高度处 -->

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline3"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.75" />  <!-- 75%高度处 -->
    ...
</androidx.constraintlayout.widget.ConstraintLayout>
  • 辅助线作用:将屏幕垂直方向等分为 4 个区域(0~25%、25%~50%、50%~75%、75%~100%),每个区域用于演示不同场景下的偏移效果。
  • 百分比定位:确保在任何屏幕尺寸下,区域比例保持一致。

2. 核心概念:水平偏移(Horizontal Bias)

app:layout_constraintHorizontal_bias 是控制控件在水平方向上偏移的关键属性,取值范围为 0~1

  • bias=0:控件偏向约束的起始端(左侧)
  • bias=0.5:默认值,控件在约束范围内居中
  • bias=1:控件偏向约束的结束端(右侧)

生效条件 :控件必须同时设置 Start_toXXXEnd_toXXX 约束(即左右都有锚点),形成一个水平范围,偏移值才会影响位置。

3. 各区域布局解析

(1)第一区域(0~25% 高度):基础偏移演示

xml

xml 复制代码
<!-- 左侧锚点A -->
<TextView
    android:id="@+id/left"
    android:layout_width="wrap_content"  <!-- 宽度自适应 -->
    android:layout_height="0dp"  <!-- 高度填充区域(父顶到guideline1) -->
    android:text="A"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="@+id/guideline1"
    app:layout_constraintStart_toStartOf="parent" />

<!-- 右侧锚点B -->
<TextView
    android:id="@+id/right"
    ...
    android:text="B"
    app:layout_constraintEnd_toEndOf="parent"  <!-- 右对齐父布局 -->
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="@+id/guideline1" />

<!-- 偏移演示控件 -->
<TextView
    android:id="@+id/t1"
    android:text="bias=0.5"  <!-- 居中 -->
    app:layout_constraintStart_toEndOf="@id/left"  <!-- 左锚点:A的右侧 -->
    app:layout_constraintEnd_toStartOf="@id/right"  <!-- 右锚点:B的左侧 -->
    app:layout_constraintHorizontal_bias="0.5" />

<TextView
    android:id="@+id/t2"
    android:text="bias=0"  <!-- 靠左 -->
    app:layout_constraintHorizontal_bias="0" />

<TextView
    android:text="bias=1"  <!-- 靠右 -->
    app:layout_constraintHorizontal_bias="1" />
  • 效果 :三个文本控件均在 A 和 B 之间的范围内,分别根据 bias 值展示居中、靠左、靠右效果。

(2)第二区域(25%~50% 高度):固定比例宽的锚点

xml

xml 复制代码
<!-- 左侧锚点(占屏幕50%宽) -->
<TextView
    android:id="@+id/left1"
    android:layout_width="0dp"  <!-- 宽度由约束决定 -->
    android:layout_height="0dp"  <!-- 高度填充区域 -->
    app:layout_constraintWidth_percent="0.5"  <!-- 宽度为父布局的50% -->
    app:layout_constraintTop_toTopOf="@id/guideline1"
    app:layout_constraintBottom_toBottomOf="@+id/guideline2" />

<!-- 右侧锚点(占屏幕50%宽) -->
<TextView
    android:id="@+id/right1"
    ...
    app:layout_constraintWidth_percent="0.5"
    app:layout_constraintEnd_toEndOf="parent" />

<!-- 偏移演示控件 -->
<TextView
    android:id="@+id/t12"
    android:text="bias====0.5"
    app:layout_constraintStart_toEndOf="@id/left1"
    app:layout_constraintEnd_toStartOf="@id/right1"
    app:layout_constraintHorizontal_bias="0.5" />
<!-- t22(bias=0)和第三个控件(bias=1)逻辑相同 -->
  • 特点 :左右锚点(left1、right1)各占屏幕 50% 宽度,中间区域的控件依然通过 bias 控制偏移,展示在固定比例宽的锚点之间的偏移效果。

(3)第三区域(50%~75% 高度):长文本的偏移限制

xml

xml 复制代码
<!-- 左侧锚点A和右侧锚点B(与第一区域类似) -->
<TextView android:id="@+id/left2" ... android:text="A" />
<TextView android:id="@+id/right2" ... android:text="B" />

<!-- 偏移演示控件 -->
<TextView
    android:id="@+id/t13"
    android:text="bias=0.5"  <!-- 居中 -->
    ... />

<TextView
    android:id="@+id/t23"
    android:text="bias=0"  <!-- 靠左 -->
    ... />

<TextView
    android:text="========bias=1==========="  <!-- 长文本 -->
    app:layout_constraintHorizontal_bias="1" />
  • 关键观察 :当控件文本较长(如最后一个控件),即使 bias=1(靠右),也不会超出左右锚点的范围(会被左侧锚点和右侧锚点限制),确保控件始终在约束范围内。

(4)第四区域(75%~100% 高度):偏移无效的场景

xml

xml 复制代码
<!-- 左侧锚点A(占50%宽) -->
<TextView
    android:id="@+id/left3"
    android:layout_width="0dp"
    app:layout_constraintWidth_percent="0.5"
    app:layout_constraintTop_toTopOf="@id/guideline3"
    app:layout_constraintBottom_toBottomOf="parent" />

<!-- 偏移演示控件 -->
<TextView
    android:id="@+id/t14"
    android:text="bias=0"
    app:layout_constraintStart_toEndOf="@id/left3"  <!-- 左锚点:A的右侧 -->
    app:layout_constraintEnd_toStartOf="@id/left3"  <!-- 右锚点:A的左侧(与左锚点冲突) -->
    app:layout_constraintHorizontal_bias="0.582" />  <!-- 偏移值无效 -->

<TextView
    android:text="锚点相同,bias无效"  <!-- 提示文本 -->
    ... />
  • 关键逻辑t14 的左右锚点均指向 left3(左锚点为 left3 的右侧,右锚点为 left3 的左侧),形成 冲突的约束范围 (实际是一个无效范围),此时 bias 值无论设为多少都无效,控件会默认显示在左锚点位置。
  • 结论 :只有当左右锚点形成有效范围(左锚点在右锚点左侧)时,bias 才会生效。

布局核心总结

  1. 水平偏移(Horizontal Bias) 是控制控件在左右约束范围内位置的关键属性,取值 0~1 分别对应靠左、居中、靠右。
  2. 生效条件 :必须同时设置 Start_toXXXEnd_toXXX 约束,且左锚点在右锚点左侧(形成有效范围)。
  3. 边界限制:即使设置了偏移,控件也不会超出左右锚点的范围(长文本会被截断或换行,而非超出)。
  4. 无效场景:当左右锚点冲突(如指向同一控件的两侧),偏移值无效。

这个布局通过对比不同场景下的偏移效果,清晰展示了 bias 属性的工作原理,是理解 ConstraintLayout 定位机制的典型示例。

相关推荐
從南走到北1 天前
JAVA国际版同城跑腿源码快递代取帮买帮送同城服务源码支持Android+IOS+H5
android·java·ios·微信小程序
2501_915918411 天前
如何解析iOS崩溃日志:从获取到符号化分析
android·ios·小程序·https·uni-app·iphone·webview
Entropless1 天前
OkHttp 深度解析(一) : 从一次完整请求看 OkHttp 整体架构
android·okhttp
v***91301 天前
Spring+Quartz实现定时任务的配置方法
android·前端·后端
wilsend1 天前
Android Studio 2024版新建java项目和配置环境下载加速
android
兰琛1 天前
Android Compose展示PDF文件
android·pdf
走在路上的菜鸟1 天前
Android学Dart学习笔记第四节 基本类型
android·笔记·学习
百锦再1 天前
第21章 构建命令行工具
android·java·图像处理·python·计算机视觉·rust·django
skyhh1 天前
Android Studio 最新版汉化
android·ide·android studio
路人甲ing..1 天前
Android Studio 快速的制作一个可以在 手机上跑的app
android·java·linux·智能手机·android studio