Eugene Brusov
Eugene Brusov

Reputation: 17846

Problems with ConstraintLayout - ImageView 16:9 inappropriate top margin

I want to build the following layout using ConstraintLayout:

Mockup

I use this source for layout:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@color/colorAccent">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleType="centerCrop"
            app:srcCompat="@android:color/darker_gray"
            app:layout_constraintDimensionRatio="h,16:9"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toTopOf="@+id/textView1" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            android:text="Title"
            android:textAppearance="@style/TextAppearance.AppCompat.Headline"
            app:layout_constraintTop_toBottomOf="@+id/imageView"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toTopOf="@+id/textView2" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            android:layout_marginBottom="24dp"
            android:text="Subtle"
            app:layout_constraintTop_toBottomOf="@+id/textView1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toBottomOf="parent" />

    </android.support.constraint.ConstraintLayout>
</FrameLayout>

And unfortunately get this result:

Result view

As you can see there's an unnecessary margin on the top of ImageView, though layout indicates marginTop=0.

Upvotes: 0

Views: 1366

Answers (5)

Nicolas Roard
Nicolas Roard

Reputation: 8449

The gist of it is to use a packed chain, with a vertical bias of 0, so that the content of the chain will be at the top. Also, I'm not sure why you are using a FrameLayout -- you probably don't need to.

enter image description here

With 1.1.0-beta2:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:scaleType="centerCrop"
        app:layout_constraintBottom_toTopOf="@+id/textView1"
        app:layout_constraintDimensionRatio="h,16:9"
        app:layout_constraintVertical_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed"
        app:srcCompat="@android:color/darker_gray" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:text="Title"
        android:textAppearance="@style/TextAppearance.AppCompat.Headline"
        app:layout_constraintTop_toBottomOf="@+id/imageView"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toTopOf="@+id/textView2" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginBottom="24dp"
        android:text="Subtle"
        app:layout_constraintTop_toBottomOf="@+id/textView1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

</android.support.constraint.ConstraintLayout>

Upvotes: 1

Cheticamp
Cheticamp

Reputation: 62831

The first two answer will work. You can also add app:layout_constraintVertical_chainStyle="spread_inside" to the top ImageView if you want to maintain your vertical chain.

Here is an image after adding this statement (but not changing anything else.)

enter image description here

Here is the XML:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@color/colorAccent">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleType="centerCrop"
            app:srcCompat="@android:color/darker_gray"
            app:layout_constraintDimensionRatio="h,16:9"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintVertical_chainStyle="spread_inside"
            app:layout_constraintBottom_toTopOf="@+id/textView1" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            android:text="Title"
            android:textAppearance="@style/TextAppearance.AppCompat.Headline"
            app:layout_constraintTop_toBottomOf="@+id/imageView"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toTopOf="@+id/textView2" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            android:layout_marginBottom="24dp"
            android:text="Subtle"
            app:layout_constraintTop_toBottomOf="@+id/textView1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toBottomOf="parent" />

    </android.support.constraint.ConstraintLayout>
</FrameLayout>

Update: So the above doesn't work on API 23 with ConstraintLayout version 1.0.2. Try the following instead:

Remove android:layout_marginTop="16dp" from textView2 and add android:layout_marginBottom="16dp" to textView1. This makes a difference.

Upvotes: 1

Eugene Brusov
Eugene Brusov

Reputation: 17846

Based on answers and comments posted in reply to this question and considering the fact constraint-layout v1.1.0 is still in beta, the best solution at this moment would be to use app:layout_constraintVertical_chainStyle="packed":

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleType="centerCrop"
            app:srcCompat="@android:color/darker_gray"
            app:layout_constraintDimensionRatio="h,16:9"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toTopOf="@+id/textView1"
            app:layout_constraintVertical_chainStyle="packed"/>

        <TextView
            android:id="@+id/textView1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            android:text="Title"
            android:textAppearance="@style/TextAppearance.AppCompat.Headline"
            app:layout_constraintTop_toBottomOf="@+id/imageView"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toTopOf="@+id/textView2" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            android:layout_marginBottom="24dp"
            android:text="Subtle"
            app:layout_constraintTop_toBottomOf="@+id/textView1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toBottomOf="parent" />

    </android.support.constraint.ConstraintLayout>
</FrameLayout>

Upvotes: 0

Anurag
Anurag

Reputation: 1170

I need to get rid of this top margin

For this,just Remove this line

app:layout_constraintBottom_toTopOf="@+id/textView1"

from your ImageView

Upvotes: 1

Gioan Le
Gioan Le

Reputation: 1168

Try this one -> I removed app:layout_constraintBottom_toTopOf="@+id/textView1" in the ImageView and it works fine.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@color/colorAccent">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleType="centerCrop"
            app:srcCompat="@android:color/darker_gray"
            app:layout_constraintDimensionRatio="h,16:9"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            android:text="Title"
            android:textAppearance="@style/TextAppearance.AppCompat.Headline"
            app:layout_constraintTop_toBottomOf="@+id/imageView"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toTopOf="@+id/textView2" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            android:layout_marginBottom="24dp"
            android:text="Subtle"
            app:layout_constraintTop_toBottomOf="@+id/textView1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toBottomOf="parent" />

    </android.support.constraint.ConstraintLayout>
</FrameLayout>

Upvotes: 0

Related Questions