Search code examples
androidandroid-layoutandroid-linearlayoutandroid-constraintlayout

How to get even spacing between TextView in ConstraintLayout?


I got this issue here, which is easily fixed if I would use nested linearlayout like this:

<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout android:layout_marginTop="32dp" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content">
        <ImageView/>
        <TexView/>
    </LinearLayout>

    <LinearLayout android:layout_marginTop="32dp" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content">
        <ImageView/>
        <TexView/>
    </LinearLayout>

    <LinearLayout android:layout_marginTop="32dp" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content">
        <ImageView/>
        <TexView/>
    </LinearLayout>
</LinearLayout>

But is there a way to solve this in constraints layout? In the image, the square represents a fixed size imageview, the rectangle is a textview which can 1 line (smaller height than imageview) or multiline (height is larger than imageview)

I tried constraints spacing each imageview with xDp, it is ok if ALL textviews are not higher than the imageview, but if a textview is higher than a imageview, it will overlap. I also tried to do spacing from ImageView to TextView, but then if the TextView is smaller than the ImageView, the spacing will be wrong again.

Is there a way to solve this in ConstraintLayout?

enter image description here

This is how it looks in Editor enter image description here

and its layout xml

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


        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_timer_black_24dp"
            app:layout_constraintEnd_toEndOf="@+id/imageView3"
            android:layout_marginTop="24dp"
            app:layout_constraintTop_toBottomOf="@+id/imageView3" />

        <ImageView
            android:id="@+id/imageView4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_timer_black_24dp"
            app:layout_constraintEnd_toEndOf="@+id/imageView"
            android:layout_marginTop="24dp"
            app:layout_constraintTop_toBottomOf="@+id/imageView" />

        <ImageView
            android:id="@+id/imageView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_timer_black_24dp"
            tools:layout_editor_absoluteX="40dp"
            tools:layout_editor_absoluteY="32dp" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:fontFamily="@font/source_sans"
            android:text="This text is a lot longer and overlaps the one below which is bad."
            android:textColor="@color/primary_text"
            android:textSize="24sp"
            android:typeface="normal"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/imageView"
            app:layout_constraintTop_toTopOf="@+id/imageView" />

        <TextView
            android:id="@+id/textView4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:fontFamily="@font/source_sans"
            android:text="This is a normal length text and that makes it."
            android:textColor="@color/primary_text"
            android:textSize="24sp"
            android:typeface="normal"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/imageView4"
            app:layout_constraintTop_toTopOf="@+id/imageView4"
            app:layout_constraintHorizontal_bias="0.0" />

        <TextView
            android:id="@+id/textView8"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:fontFamily="@font/source_sans"
            android:text="Small Text"
            android:textColor="@color/primary_text"
            android:textSize="24sp"
            android:typeface="normal"
            app:layout_constraintTop_toTopOf="@+id/imageView3"
            app:layout_constraintStart_toEndOf="@+id/imageView3"
            android:layout_marginStart="16dp" />

    </android.support.constraint.ConstraintLayout>

Solution

  • for information i am posting this answer will be useful for future reference I think that was ConstarintLayout problem with wrap_content data handling where this is now easy from new ConstraintLayout version which is now in beta

    It introduced new feature by using this we can tackle this wrap_content problem, also @kazhiu's answer will do workaround here because of fixed height of ImageView it will not work if ImageView have an wrap_content or dynamic height so in this case constraint.Barrier is useful. for setup bet ContraintLayout we have to do following

    add maven support in project gradle file as below

    allprojects {
        repositories {
            maven { url 'https://maven.google.com' }
            jcenter()
        }
    }
    

    then in app gardle dependencies add ConstarintLayout library dependency

    compile 'com.android.support.constraint:constraint-layout:1.1.0-beta1'
    

    Here is the same @kazhiu's code using constraint.Barrier

    <android.support.constraint.ConstraintLayout
        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:layout_margin="20dp">
    
    
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="48dp"
            android:layout_height="48dp"
            app:srcCompat="@mipmap/ic_launcher"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_marginLeft="0dp"
            android:layout_marginTop="0dp" />
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:text="Lorem ipsum"
            app:layout_constraintLeft_toRightOf="@+id/imageView"
            app:layout_constraintRight_toRightOf="parent"
            android:layout_marginStart="16dp"
            app:layout_constraintTop_toTopOf="@+id/imageView" />
    
        <ImageView
            android:id="@+id/imageView2"
            android:layout_width="48dp"
            android:layout_height="48dp"
            app:srcCompat="@mipmap/ic_launcher"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/barrierone"
            android:layout_marginLeft="0dp"
            android:layout_marginTop="16dp" />
    
        <TextView
            android:id="@+id/textView2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. "
            app:layout_constraintLeft_toRightOf="@+id/imageView2"
            app:layout_constraintRight_toRightOf="parent"
            android:layout_marginStart="16dp"
            app:layout_constraintTop_toTopOf="@+id/imageView2" />
    
        <ImageView
            android:id="@+id/imageView4"
            android:layout_width="48dp"
            android:layout_height="48dp"
            app:srcCompat="@mipmap/ic_launcher"
            android:layout_marginLeft="0dp"
            app:layout_constraintLeft_toLeftOf="parent"
            android:layout_marginTop="16dp"
            app:layout_constraintTop_toBottomOf="@+id/barrierone2" />
    
        <TextView
            android:id="@+id/textView4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. "
            app:layout_constraintRight_toRightOf="parent"
            android:layout_marginRight="0dp"
            app:layout_constraintLeft_toRightOf="@+id/imageView4"
            android:layout_marginLeft="16dp"
            app:layout_constraintTop_toTopOf="@+id/imageView4"
            android:layout_marginTop="0dp" />
    
        <android.support.constraint.Barrier
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:id="@+id/barrierone"
            app:layout_constraintTop_toBottomOf="@+id/imageView"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:constraint_referenced_ids="imageView,textView"
            app:barrierDirection="bottom" />
    
        <android.support.constraint.Barrier
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:id="@+id/barrierone2"
            app:layout_constraintTop_toBottomOf="@+id/imageView2"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:constraint_referenced_ids="imageView2,textView2"
            app:barrierDirection="bottom" />
    
    </android.support.constraint.ConstraintLayout>
    

    Design and blue print

    enter image description here

    in android.support.constraint.Barrier

    app:constraint_referenced_ids="id1,id2"
    

    will contain the id's of views which are wrap_content on top of other views, also we can create horizontal barrier by replacing height to match_constraint(0dp) and width to wrap_content