34

In my Fragment I have a ConstraintLayout with layout_height="wrap_content" and I would like to have a margin between my two buttons at the bottom of the view.

When I add this margin as layout_marginBottom to the upper button (button_welcome_signup) it seems to work fine. However, if I try to add it to the bottom button (button_welcome_signin) as layout_marginTop it doesn't work.

Does anybody know what the issues here is / if am doing something wrong?

(Please note there is a reason why I am using wrap_content and also that I would seriously like to use the margin on the bottom button, so I can add some margin to its style for better UI consistency within my project).

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:MyAppApp="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:background="@color/white"
    android:minHeight="@dimen/min_height_welcome_frame"
    android:padding="@dimen/margin_all_frame_inner">

    <ImageView
        android:id="@+id/imageview_welcome_logo"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        android:src="@drawable/logo_header"
        MyAppApp:layout_constraintTop_toTopOf="parent"
        MyAppApp:layout_constraintLeft_toLeftOf="parent"
        MyAppApp:layout_constraintRight_toRightOf="parent" />

    <TextView
        android:id="@+id/textiew_welcome_title"
        style="@style/MyAppTextViewTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/margin_all_component_l"
        android:text="@string/welcome_title"
        MyAppApp:layout_constraintTop_toBottomOf="@id/imageview_welcome_logo" />

    <TextView
        android:id="@+id/textview_welcome_text"
        style="@style/MyAppTextViewText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/welcome_message"
        MyAppApp:layout_constraintTop_toBottomOf="@id/textiew_welcome_title" />

    <Button
        android:id="@+id/button_welcome_signin"
        style="@style/MyAppSubButton"
        android:layout_width="match_parent"
        android:layout_height="46dp"
        android:layout_marginTop="@dimen/margin_all_component_s" 
        android:text="@string/welcome_sign_in"
        MyAppApp:layout_constraintBottom_toBottomOf="parent" />

    <Button
        android:id="@+id/button_welcome_signup"
        style="@style/MyAppButton"
        android:layout_width="match_parent"
        android:layout_height="46dp"
        android:layout_marginTop="@dimen/margin_all_component_l"
        android:text="@string/welcome_sign_up"
        MyAppApp:layout_constraintBottom_toTopOf="@id/button_welcome_signin"
        MyAppApp:layout_constraintTop_toBottomOf="@id/textview_welcome_text"
        MyAppApp:layout_constraintVertical_bias="1" />

</android.support.constraint.ConstraintLayout>

styles.xml:

<style name="MyAppButton" parent="Widget.AppCompat.Button">
    <item name="android:background">@drawable/button_selector_blue</item>
    <item name="android:textSize">@dimen/textsize_all_l</item>
    <item name="android:textColor">@color/white</item>
    <item name="fontFamily">@font/my_sans_serif_regular</item>
</style>

<style name="MyAppSubButton" parent="Widget.AppCompat.Button">
    <item name="android:background">@drawable/button_selector_transparent</item>
    <item name="android:textSize">@dimen/textsize_all_l</item>
    <item name="android:textColor">@color/turquoise_blue</item>
    <item name="fontFamily">@font/my_sans_serif_regular</item>
</style>
Arulkumar
  • 12,966
  • 14
  • 47
  • 68
Simon Mayrshofer
  • 1,264
  • 1
  • 11
  • 18

8 Answers8

57

Within a ConstraintLayout, side margins for a child view will only take effect if that side is constrained to another view. In your original example, bottom margin on the top button works because the top button has a bottom constraint:

MyAppApp:layout_constraintBottom_toTopOf="@id/button_welcome_signin"

However, top margin on the bottom button doesn't work because the bottom button has no constraint for its top.

If you would like to use top margin on the bottom button, add this constraint:

MyAppApp:layout_constraintTop_toBottomOf="@+id/button_welcome_signup"

Note that you will also have to update the chain style (since this new constraint creates a chain) by adding this attribute to the top button:

MyAppApp:layout_constraintVertical_chainStyle="packed"
Ben P.
  • 52,661
  • 6
  • 95
  • 123
  • Perfect. Thanks so much, this is exactly what i needed to know. Furthermore - the code seems to work fine without adding the chain style. Should I still add it for "best practice" reasons or do I only need it if I intend to put a bias on my packed chain? – Simon Mayrshofer Jan 04 '18 at 10:14
  • 1
    @g-mac no need to add it if it works without. I forgot that you were using wrap_content, so there's no difference between spread (the default) and packed. – Ben P. Jan 04 '18 at 15:45
  • I returned to this same answer after over a year as I had forgotten the solution (I only needed to set he top and bottom constraints of all the views but without setting the vertical chainStyle it worked). I shall bookmark this page now. Thanks for the answer. – Sufian Mar 20 '19 at 09:44
  • 1
    Thanks, helpful ("side margins for a child view will only take effect if that side is constrained to another view") – ror Jul 06 '19 at 20:41
  • @BenP. I wonder if it is documented in ConstraintLayout class. – DYS Mar 05 '20 at 06:26
2

try this

<Button
    android:id="@+id/button_welcome_signin"
    style="@style/MyAppSubButton"
    android:layout_width="match_parent"
    android:layout_height="46dp"
    android:layout_marginTop="16dp"
    android:text="@string/welcome_sign_in"
    MyAppApp:layout_constraintBottom_toBottomOf="parent"
    MyAppApp:layout_constraintEnd_toEndOf="parent"
    MyAppApp:layout_constraintStart_toStartOf="parent"
    MyAppApp:layout_constraintTop_toBottomOf="@+id/button_welcome_signup" />
1

It took me a while to figure out I was thinking about this the wrong way, so maybe it will help someone else.

In a ConstraintLayout, it is making a margin from the constraint.

In other words, let's say you have two buttons next to each other.

The one on the right is constrained StartToEnd, TopToTop, and BottomToBottom to the one on the left.

If you give the right one a marginBottom, it's not going to push things below it down, it's going to push itself up from the bottom of the first button. The margin is between its bottom line and the bottom line of the thing it's constrained to, not between all views on the screen.

DjSh
  • 2,776
  • 2
  • 19
  • 32
0

First image am removed margins on Your code ,

enter image description here

Second image added margin on left,right,top,bottom

enter image description here

  • I think @g-mac knows how to set margins, he is interested why layout_marginTop does not work on **button_welcome_signin** – Misha Akopov Jan 03 '18 at 18:13
  • i don't know exactly , "wrap_content" is not fixed size and the size is depend upon the content, but "match_parent" is fixed size if the content more then the size it won't display. if any thing wrong tell me, i will correct it – Poovarasan Selvaraj Jan 03 '18 at 18:22
  • Taken from [here](https://developer.android.com/training/constraint-layout/index.html#adjust-the-view-size): "You cannot use match_parent for any view in a ConstraintLayout. Instead use "match constraints" (0dp)" – Eugene Brusov Jan 03 '18 at 22:44
0
<Button
        android:id="@+id/SaveBtnId"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/Save"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginLeft="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginRight="16dp"
        app:layout_constraintRight_toRightOf="parent"
         />

enter image description here

Akbar Khan
  • 2,215
  • 19
  • 27
0

In case someone has the same problem I was having, trying to have a View(RecyclerView) as match_parent at the bottom of another View (which is an ImageView). But the RecycleView was overlapping my ImageView even tho I was putting a top_margin in my RecyclerView of my ImageView height size.

Solution: Set the - android:layout_height="0dp" - works great for me. The explanation is bellow.

MATCH_PARENT not working

<View
    android:id="@+id/view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"/>

Any view should apply the attribute rules of its parent ViewGroup. ConstraintLayout supports the “0dp” value (match_constraint) instead of “match_parent” to get the match parent behavior. So, NEVER EVER use “match_parent” with ConstraintLayout!

I got from here... https://medium.com/@jemli.idea/constraintlayout-never-ever-97c121286100

0

I was using android:margin_vertical and android:margin_top at the same time, here margin_vertical takes precedence.

issue can occur with android:margin as well

Rahul Tiwari
  • 6,851
  • 3
  • 49
  • 78
-3

android:layout_marginTop="@dimen/_10sdp"

Messi
  • 25
  • 1