Android ConstraintLayout - 将一个视图放在另一个视图之上

Android ConstraintLayout - Put one view on top of another view

我正在尝试在 Button 之上添加一个 ProgressBar(两者都在 ConstraintLayout 内)。

<Button
    android:id="@+id/sign_in_button"
    android:layout_width="280dp"
    android:layout_height="75dp"
    android:layout_marginBottom="75dp"
    android:layout_marginTop="50dp"
    android:text="@string/sign_in"
    android:textColor="@color/white"
    android:textSize="22sp"
    android:textStyle="bold"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/passwordEditText"
    app:layout_constraintVertical_bias="0.0"/>

<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toTopOf="@+id/sign_in_button"
    android:layout_marginTop="8dp"
    app:layout_constraintBottom_toBottomOf="@+id/sign_in_button"
    android:layout_marginBottom="8dp"
    app:layout_constraintVertical_bias="0.5"
    android:layout_marginLeft="8dp"
    app:layout_constraintLeft_toLeftOf="@+id/sign_in_button"
    android:layout_marginRight="8dp"
    app:layout_constraintRight_toRightOf="@+id/sign_in_button"/>

但即使在 onCreate 中的 ProgressBar 上调用 bringToFront 之后,它也始终停留在 Button 之后。

ProgressBar progressBar = (ProgressBar)findViewById(R.id.progressBar);
progressBar.bringToFront();

设置海拔 ProgressBar2dp 似乎有效。

android:elevation="2dp"

您也可以尝试按照 similar question.

的已接受答案中的建议设置 translationZ

我也遇到了 this answer 作为替代方案。

我们需要使用android:elevation来控制它。

android:elevation="10dp"

此海拔属性仅在 API 等级 >= 21 时有效。但在该等级以下它会正常运行。如果我们在 Button 视图下方添加 Progress,它会显示位于另一个视图顶部底部的视图。

您可以简单地定义您希望在其下方显示的视图之后的视图。

对于按钮,请注意它们的高度由它们的 stateListAnimator 控制。 Widget.MaterialComponents.Button 的 stateListAnimator 的默认高度为 @dimen/mtrl_btn_elevation (2dp)。所以如果你想在按钮顶部显示一个视图,它应该至少有 2dp 的高度。

Android Sutdio 3.5 的更新答案:

在更新的布局编辑器中,现在可以更轻松地选择哪个视图位于前面,如 Android Studio 发行说明

中所示

.. In addition, a blue overlay now highlights the target of the constraint. This highlighting is particularly useful when attempting to constrain to a component that overlaps with another.

https://developer.android.com/studio/releases

更简单, 如果向上拖动视图(复制粘贴或从布局编辑器中的组件树),它将获得较低的优先级(因此它将位于其他视图之后)

在约束布局中你应该使用

翻译

高于您想要低于的视图。

你可以像下面这样包装它使用framelayout作为父级并将进度条放在约束布局之外。这将重叠按钮

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
 //your all view inside it with button
 <Button/>......
  .........
 </androidx.constraintlayout.widget.ConstraintLayout>

 <ProgressBar
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</FrameLayout>

按钮默认设置了 TranslationZ,因此您有两个选择

1 - 使进度条 TranslationZ 大于按钮高度

ViewCompat.setTranslationZ(progressBar, 5)// to support older api <21

2 - 将按钮 TranslateZ 设置为 0,以便视图在您的约束布局中按顺序显示在彼此之上,您可以通过将样式设置为按钮来实现此目的

style="@style/Widget.AppCompat.Button.Borderless"

虽然 android:elevation="4dp"traslationz 会起作用,但是 API 级别至少应达到 21。如果由于某种原因您不能这样做,请确保您的视图want on top 是在其他观点之后提到的。例如,如果我想要 ImageView 顶部的 progressBar:

<?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=".ImageActivity">

<ImageView
   android:id="@+id/image_view"
   android:layout_width="0dp"
   android:layout_height="0dp"
   app:layout_constraintBottom_toBottomOf="parent"
   app:layout_constraintDimensionRatio="6:4"
   app:layout_constraintEnd_toEndOf="parent"
   app:layout_constraintStart_toStartOf="parent"
   app:layout_constraintTop_toTopOf="parent" />

<ProgressBar
   android:id="@+id/progress_bar"
   style="?android:attr/progressBarStyle"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   app:layout_constraintBottom_toBottomOf="parent"
   app:layout_constraintEnd_toEndOf="parent"
   app:layout_constraintStart_toStartOf="parent"
   app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

使用海拔是有效的,但它有一些限制,比如它需要 api 级别 21+ 而且如果海拔较低(在我的例子中是 2dp)那么在长按时视图变得不可见因此你可以简单地使用一个技巧将按钮替换为“View”或“TextView”你可以用这些视图做所有可以用 buttonView

完成的事情