Android ConstraintLayout - Put one view on top of another view

Viewed 95195

I'm trying to add a ProgressBar on top of a Button (both are inside a 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"/>

But even after calling bringToFront on the ProgressBar in onCreate, it always stays behind the Button.

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

We need to use android:elevation to control this.

android:elevation="10dp"

This elevation attribute only work in API level >= 21. But In below that it will behave normally. If we add Progress below the Button view it show the view which is in the bottom at the top of the other view.

You can simply define the view which you want on top after the one which should appear below it.

With buttons, note that their elevation is governed by their stateListAnimator. The stateListAnimator of Widget.MaterialComponents.Button has a default elevation of @dimen/mtrl_btn_elevation (2dp). So if you want to show a view on top of a Button, it should have an elevation of at least 2dp.

In Constraint layout you should use

traslationz

higher than view that you want to below .

Although android:elevation="4dp" or traslationz will work, but for that API level should at least 21. If for some reason you can't do that, make sure the view you want on top is mentioned after other views. For example, if I want progressBar on top of ImageView:

<?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>

Using elevation is working but it has some limitations like it requires api level 21+ and also if elevation is less(in my case it was 2dp) then view become invisible while doing long click therefore you can use a trick simply replace button with "View" or "TextView" you can do everything with these views which can be done with buttonView

Updated answer for Android Sutdio 3.5:

In the updated Layout Editor it's now much easier to choose which View will be in front as demonstrated in the Android Studio release notes

.. 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

Even easier, If you drag the View up (copy paste or from the Component Tree in the layout editor) it will get lower priority (so it will be behind the other views)

Button by default have TranslationZ set , so you have two options

1 - make progress bar TranslationZ greater than button elevation

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

2 - make button TranslateZ to 0 so the views Appear above each other in order in your Constraint Layout , you can achieve this by Setting Style to button

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