android xml布局如何定义view的层级

892 阅读3分钟

在 Android 的 XML 布局文件中,定义 View 的层级主要通过以下几种方式来实现,以确定不同视图之间的相对布局和层级顺序。

1. 通过 ViewGroup 容器定义层级

在 XML 中,ViewGroup(例如 LinearLayoutRelativeLayoutConstraintLayout 等)是用来嵌套和排列其他 View 的容器。容器中的 View 按照定义的顺序逐层显示,从上到下叠加,顺序就是层级关系。

xml
复制代码
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- 第一层 View -->
    <TextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="First Layer" />

    <!-- 第二层 View -->
    <ImageView
        android:id="@+id/image1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/sample_image" />
</LinearLayout>

在上面的例子中,TextViewImageView 之上显示(层级更高)。

2. 使用 FrameLayout 实现视图叠加

FrameLayout 是一种特殊的布局,通常用来叠加视图,它的层级顺序由定义顺序决定。后定义的 View 会覆盖在前面的 View 之上。

xml
复制代码
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 第一层 View -->
    <ImageView
        android:id="@+id/background_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/background_image" />

    <!-- 第二层 View 覆盖在第一层上 -->
    <TextView
        android:id="@+id/overlay_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Overlay Text"
        android:layout_gravity="center" />
</FrameLayout>

在这里,TextView 会叠加在 ImageView 上,因为 TextView 是后定义的。

3. 使用 ConstraintLayout 定义层级

ConstraintLayout 支持 View 的层级管理,通过 android:translationZlayout_constraintZ 属性设置不同 ViewZ 轴位置。数值越大,View 就显示在越高的层级。

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

    <!-- 第一层 View,层级最低 -->
    <ImageView
        android:id="@+id/image_background"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:src="@drawable/sample_image" />

    <!-- 第二层 View,覆盖在 ImageView 上 -->
    <TextView
        android:id="@+id/text_overlay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:text="Overlay Text"
        android:translationZ="10dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

4. 使用 Viewelevation 属性

在 API 21 及以上版本,elevation 可以控制 ViewZ 轴上的高度,数值越大,显示越在上层。例如:

xml
复制代码
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/image_background"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/sample_image"
        android:elevation="1dp" />

    <TextView
        android:id="@+id/overlay_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Overlay Text"
        android:elevation="5dp" />
</RelativeLayout>

在上面的例子中,TextViewelevation 更大,因此显示在 ImageView 之上。

ConstraintLayout 中,translationZ 和动态添加的 View 的层级关系是由它们的 Z 轴位置以及 ViewGroup 中的添加顺序共同决定的。

层级规则

  1. translationZ 属性:决定了 ViewZ 轴的相对高度。较高的 translationZ 值会让 View 显示在较低的 translationZ 值之上。
  2. 添加顺序:如果 translationZ 值相同,动态添加的 View 会默认覆盖在布局文件中定义的 View 之上(即后添加的层级更高)。

示例分析

假设在已有布局中动态添加一个 View,如下:

kotlin
复制代码
// 动态创建一个新 View
val newView = TextView(context).apply {
    text = "Dynamically Added View"
    translationZ = 15f // 设置较高的 translationZ 值
}

// 将新 View 添加到 ConstraintLayout 中
constraintLayout.addView(newView)

层级结果

  • 如果 newViewtranslationZ 值高于布局中的 View,那么它会覆盖其他 View
  • 如果 newViewtranslationZ 值低于现有 View,即使动态添加顺序在后,仍然会被已有 View 覆盖。
  • 如果 translationZ 值相同,动态添加的 View 会显示在已有的 View 之上,因为添加顺序晚于其他 View

总结

ConstraintLayout 中,如果你设置了动态添加 ViewtranslationZ 比其他 View 更高,那么它会显示在其他 View 之上。