Android ConstraintLayout - Put one view on top of another view

AndroidAndroid LayoutAndroid Constraintlayout

Android Problem Overview


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();

Android Solutions


Solution 1 - Android

Set an elevation on the ProgressBar; 2dp seems to work.

android:elevation="2dp"

You could also try setting translationZ as suggested in the accepted answer to a similar question.

I also came across this answer as an alternative.

Solution 2 - Android

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.

Solution 3 - Android

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.

Solution 4 - Android

In Constraint layout you should use

traslationz

higher than view that you want to below .

Solution 5 - Android

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>

Solution 6 - Android

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

Solution 7 - Android

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)

Solution 8 - Android

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"

Solution 9 - Android

You can wrap it like below Use framelayout as parent and put porogress bar outside constraint layout. This will overlap button

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAdam JohnsView Question on Stackoverflow
Solution 1 - AndroidCheticampView Answer on Stackoverflow
Solution 2 - AndroidIshan FernandoView Answer on Stackoverflow
Solution 3 - AndroidCristanView Answer on Stackoverflow
Solution 4 - AndroidWaqas YousafView Answer on Stackoverflow
Solution 5 - AndroidAbhiView Answer on Stackoverflow
Solution 6 - AndroidPRANAV SINGHView Answer on Stackoverflow
Solution 7 - AndroidRefaelView Answer on Stackoverflow
Solution 8 - AndroidMohammed AlaaView Answer on Stackoverflow
Solution 9 - AndroidRohan SharmaView Answer on Stackoverflow