2

A ConstraintLayout with two TextViews

In the image above I have two TextViews aligned using ConstraintLayout's layout_constraintBaseline_toBaselineOf property. But what I actually want is the the smaller TextView on the left is aligned with the middle (vertically) of the first line of the TextView on the right (rather than with its baseline). I.e. I want the TextView on the left to be about 2dp higher in this particular case.

My xml is:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="wrap_content"
    android:layout_marginBottom="8dp"
    android:layout_marginEnd="12dp"
    android:layout_marginLeft="12dp"
    android:layout_marginRight="12dp"
    android:layout_marginStart="12dp"
    android:layout_marginTop="8dp"
    android:background="@android:color/white">

    <TextView
        android:id="@+id/tvElapsedTime"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="12dp"
        android:layout_marginRight="12dp"
        android:textColor="@color/grey"
        android:textSize="8sp"
        app:customTypeface="@string/my_typeface"
        app:layout_constraintBaseline_toBaselineOf="@+id/tvHeadline"
        app:layout_constraintEnd_toEndOf="@id/headlineStart"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="@id/headlineStart"
        app:layout_constraintStart_toStartOf="parent"
        tools:text="3 min ago" />

    <android.support.constraint.Guideline
        android:id="@+id/headlineStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.2" />

     <TextView
        android:id="@+id/tvHeadline"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="14sp"
        app:customTypeface="@string/my_bold_typeface"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintLeft_toRightOf="@id/headlineStart"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintStart_toEndOf="@id/headlineStart"
        tools:text="Things happened that you would not believe even if I told you." />

</android.support.constraint.ConstraintLayout>

How can I make it so that "3 mins ago" aligns (vertically) with the middle of the first line of "Things happened.."?

(P.S. I have seen this question: Align top two textviews with different font sizes but I believe my question is different)

Villa
  • 459
  • 7
  • 17
  • If you would like for both of them to be centered, that is that left one is in the middle of the right one, just center them vertically. – Gotiasits Apr 17 '18 at 11:30
  • I've edited my question above: I want "3 min ago" to align with the middle of the *first line* of the TextView on the right (I don't want it to align with the middle of the entire TextView on the right) – Villa Apr 17 '18 at 12:50
  • So you basically would like for "3 min ago" to be in same place regardless of number of lines in of the right text view? If this is the case than just make left text to bi at "fixed" (dp) distance from the parent. Or you could use `app:layout_constraintHeight_percent` ... – Gotiasits Apr 17 '18 at 12:56
  • Thanks for the reply @Gotiasits. I think your answer is similar to what Cheticamp suggested below: worth noting his extra piece of advice to set the layout_marginTop in sp to handle the case of the user resizing the text. – Villa Apr 17 '18 at 15:47

3 Answers3

1

Try the following XML for the elapsed time TextView:

<TextView
    android:id="@+id/tvElapsedTime"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginEnd="12dp"
    android:layout_marginRight="12dp"
    android:textColor="@android:color/darker_gray"
    android:textSize="8sp"
    app:layout_constraintTop_toTopOf="@id/tvHeadline"
    android:layout_marginTop="4sp"
    app:layout_constraintEnd_toEndOf="@id/headlineStart"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="@id/headlineStart"
    app:layout_constraintStart_toStartOf="parent"
    tools:text="3 min ago" />

Ideally, you could constrain the baseline of this text view to the baseline of the headline text view and the top to the top and let it center. Unfortunately, once you tie the baselines that is it: Centering is no longer an option.

This method constrains the top of the elapsed time text view to the top of the headline text view and applies a 4sp margin to the top. This aligns the elapsed time to the center (or nearly center) of the top line of the headline. This placement is invariant whether the headline is one line or many lines. This solution is dependent upon the text sizes that you select.

I use 4sp instead of 4dp because you will want the margin to size appropriately if the font is scaled by the user.

Here is the effect:

enter image description here

Cheticamp
  • 61,413
  • 10
  • 78
  • 131
  • Nice, that works. As you observed, the key problem here is that once you use constraintBaseline that's it... there's no way to adjust it from that point. This solution seems to be the best solution; my one reservation is that if we use multiple dimension sets for larger / smaller screens, then we have another variable (margin top) to add for each dimension set. But it's definitely good enough for what I need now, thanks for your help @Cheticamp – Villa Apr 17 '18 at 15:11
0

Try below code for "3 min ago" TextView :

<TextView
    android:id="@+id/tvElapsedTime"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp"
    android:layout_marginEnd="8dp"
    android:layout_marginLeft="8dp"
    android:layout_marginRight="8dp"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    android:textColor="@android:color/darker_gray"
    android:textSize="8sp"
    app:layout_constraintBottom_toBottomOf="@+id/tvHeadline"
    app:layout_constraintEnd_toStartOf="@+id/tvHeadline"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="@+id/tvHeadline"
    tools:text="3 min ago" />
immodi
  • 607
  • 1
  • 6
  • 21
  • This centres the elapsedTime TextView with the middle of the other TextView. But what I'm looking for is to have it centred with the middle of the *first line* of the headline TextView. – Villa Apr 17 '18 at 12:43
  • @Villa, I think you have to set manually margin at top of TextView for your problem – immodi Apr 17 '18 at 13:05
  • I tried adding margin and padding but they get ignored; I think app:layout_constraintBaseline_toBaselineOf supersedes both margin and padding settings. – Villa Apr 17 '18 at 14:48
0
<TextView
    android:id="@+id/tvElapsedTime"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_marginEnd="12dp"
    android:layout_marginRight="12dp"
    android:textColor="@color/grey"
    android:textSize="8sp"
    android:gravity="center"
    app:customTypeface="@string/my_typeface"
    app:layout_constraintEnd_toEndOf="@id/headlineStart"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintRight_toRightOf="@id/headlineStart"
    app:layout_constraintStart_toStartOf="parent"
    tools:text="3 min ago" />
Kabilan
  • 191
  • 10
  • This centres the elapsedTime TextView with the middle of the other TextView. But what I'm looking for is to have it centred with the middle of the *first line* of the headline TextView. – Villa Apr 17 '18 at 12:42