I want to create a layout where there are multiple lines with various lengths of text. All the texts are centered. The starting point of the centered longest text will serve as a basis. Then, the other texts, which are shorter, will no longer be centered but will be aligned left to the starting point of the longest text.
To achieve this in a ConstraintLayout, I have created a LinearLayout that is centered and has a width of wrap_content
. Then, inside the LinearLayout, I have multiple TextView
s also with width wrap_content
. I expect the LinearLayout to expand itself (in width), up to the width of the ConstraintLayout (which has the width of the device), to ensure that its children TextView
s do not wrap unless the text is longer that the screen width (which, in my particular case, is impossible). The preview of the Android Studio editor shows that this happens as I expected. However, upon running on my device and using Tools > Layout Inspector
on Android Studio, the LinearLayout does not expand itself in width even when there is much space remaining.
Here is my XML code for the layout.
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="user"
type="com.mobile.githubuser.model.GithubUser" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/act_details_toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height"
android:background="?attr/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:title="@string/act_user_details_toolbar_title"
app:titleTextAppearance="@style/TextAppearance.Toolbar" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/shapeableImageView"
style="@style/Widget.GithubUser.ShapeableImageView.Circular"
android:layout_width="@dimen/user_details_avatar_size"
android:layout_height="@dimen/user_details_avatar_size"
android:layout_marginTop="@dimen/keyline_5"
android:src="@{user.avatar}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/act_details_toolbar" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/keyline_4"
android:layout_marginTop="@dimen/keyline_4"
android:layout_marginEnd="@dimen/keyline_4"
android:text="@{user.name}"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceHeadline2"
android:textColor="?attr/colorOnBackground"
app:layout_constraintTop_toBottomOf="@+id/shapeableImageView"
tools:layout_editor_absoluteX="16dp"
tools:text="April Ludgate" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/keyline_4"
android:layout_marginTop="@dimen/keyline_2"
android:layout_marginEnd="@dimen/keyline_4"
android:text="@{`@` + user.username}"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceSubtitle2"
android:textColor="?attr/colorOnBackground"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView"
tools:text="\@april_ludgate" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/keyline_4"
android:layout_marginTop="@dimen/keyline_5"
android:layout_marginEnd="@dimen/keyline_4"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView2">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/drawable_company"
android:drawablePadding="@dimen/keyline_2"
android:text="@{`Company\t\t: ` + user.company}"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView2"
tools:text="\Company\t\t: Google, Inc." />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/keyline_0"
android:drawableStart="@drawable/drawable_location"
android:drawablePadding="@dimen/keyline_2"
android:text="@{`Location\t\t\t: ` + user.location}"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView3"
tools:text="Location\t\t\t: Pittsburgh, PA, USA" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/keyline_0"
android:drawableStart="@drawable/drawable_repository"
android:drawablePadding="@dimen/keyline_2"
android:text="@{`Repository\t: ` + user.repository}"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView4"
tools:text="Repository\t: 2" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/keyline_0"
android:drawableStart="@drawable/drawable_follower"
android:drawablePadding="@dimen/keyline_2"
android:text="@{`Followers\t\t: `}"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
addNumberToText="@{user.followers}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView5"
tools:text="Followers\t\t: 1029" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/keyline_0"
android:drawableStart="@drawable/drawable_following"
android:drawablePadding="@dimen/keyline_2"
android:text="@{`Following\t\t: `}"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
addNumberToText="@{user.following}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView6"
tools:text="Following\t\t: 101" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Here is what my editor preview is showing (what I want).
Here is the tool inspector showing the problem.
As you can see on the second image, the TextView
wrap to two lines when there is space (to the left and right) of the LinearLayout
. I expect the LinearLayout
to take as much space as possible but the least amount of space possible to still display all the TextView
in one line each. Using android:maxLines=1
and android:singleLine=true
causes the text to be cut off and to be ellipsis-ed respectively; I do not want this. What is causing this problem? If achieving what I want this way is impossible, how can I achieve what I described (without using a fixed value, e.g. margin and guideline to align the TextView
s)?
Not related to question: why doesn't my MaterialTextView
display properly in my Android Studio eidtor preview?
As mentioned in @Pawel Laskowski's comment, it is the tab character (\t
) that is causing problems in the layout. Simply erasing the tab characters and replacing them with several spaces work. However, as the font I am using is not monospaced, the colon part isn't aligned perfectly.
An alternative solution is to separate the one TextView per line into two TextViews. This also works in my favor because now, I can provide a string literal (e.g. Company
, Location
, etc.) in multiple languages and add the dynamically generated content (from the data-binding user
) to the overall displayed text. Then, after all the separations, place the TextViews inside a ConstraintLayout, replacing the original LinearLayout. Now, our structure is the following (for the problematic section).
ConstraintLayout
|__ TextView (first part for row 1)
|__ TextView (second part for row 1)
|__ ...
|__ TextView (first part for row n)
|__ TextView (second part for row n)
Then, create a barrier with the direction end
referencing all the first parts of each row. Position all the second parts of each row relative to the barrier and add some marginStart
to create space between the first part and the second part. The second part contains the colon and the dynamically-generated content.
Here's the final XML.
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="user"
type="com.mobile.githubuser.model.GithubUser" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/act_details_toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height"
android:background="?attr/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:title="@string/act_user_details_toolbar_title"
app:titleTextAppearance="@style/TextAppearance.Toolbar" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/shapeableImageView"
style="@style/Widget.GithubUser.ShapeableImageView.Circular"
android:layout_width="@dimen/user_details_avatar_size"
android:layout_height="@dimen/user_details_avatar_size"
android:layout_marginTop="@dimen/keyline_5"
android:src="@{user.avatar}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/act_details_toolbar" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/keyline_4"
android:layout_marginTop="@dimen/keyline_4"
android:layout_marginEnd="@dimen/keyline_4"
android:text="@{user.name}"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceHeadline2"
android:textColor="?attr/colorOnBackground"
app:layout_constraintTop_toBottomOf="@+id/shapeableImageView"
tools:layout_editor_absoluteX="16dp"
tools:text="April Ludgate" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/keyline_4"
android:layout_marginTop="@dimen/keyline_2"
android:layout_marginEnd="@dimen/keyline_4"
android:text="@{`@` + user.username}"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceSubtitle2"
android:textColor="?attr/colorOnBackground"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView"
tools:text="\@april_ludgate" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/keyline_4"
android:layout_marginTop="@dimen/keyline_5"
android:layout_marginEnd="@dimen/keyline_4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView2">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/drawable_company"
android:drawablePadding="@dimen/keyline_2"
android:text="@string/company_label"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/keyline_0"
android:drawableStart="@drawable/drawable_location"
android:drawablePadding="@dimen/keyline_2"
android:text="@string/location_label"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView3" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/keyline_0"
android:drawableStart="@drawable/drawable_repository"
android:drawablePadding="@dimen/keyline_2"
android:text="@string/repository_label"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView4" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/keyline_0"
android:drawableStart="@drawable/drawable_follower"
android:drawablePadding="@dimen/keyline_2"
android:text="@string/followers_label"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView5" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/keyline_0"
android:drawableStart="@drawable/drawable_following"
android:drawablePadding="@dimen/keyline_2"
android:text="@string/following_label"
android:textAlignment="center"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialTextView6" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="materialTextView3,materialTextView4,materialTextView5,materialTextView6,materialTextView7"/>
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/keyline_2"
android:text="@{`: ` + user.company}"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintBottom_toBottomOf="@+id/materialTextView3"
app:layout_constraintStart_toEndOf="@id/barrier2"
app:layout_constraintTop_toTopOf="@+id/materialTextView3"
tools:text=": Google, Inc." />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/keyline_2"
android:text="@{`: ` + user.location}"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintBottom_toBottomOf="@+id/materialTextView4"
app:layout_constraintStart_toEndOf="@id/barrier2"
app:layout_constraintTop_toTopOf="@+id/materialTextView4"
tools:text=": Pittsburgh, PA, U.S.A." />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView10"
formatNumberToTextWithColon="@{user.repository}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/keyline_2"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintBottom_toBottomOf="@+id/materialTextView5"
app:layout_constraintStart_toEndOf="@id/barrier2"
app:layout_constraintTop_toTopOf="@+id/materialTextView5"
tools:text=": 1,234" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/materialTextView11"
formatNumberToTextWithColon="@{user.followers}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/keyline_2"
android:layout_marginBottom="2dp"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintBottom_toBottomOf="@+id/materialTextView6"
app:layout_constraintStart_toEndOf="@id/barrier2"
app:layout_constraintTop_toTopOf="@+id/materialTextView6"
tools:text=": 304" />
<com.google.android.material.textview.MaterialTextView
formatNumberToTextWithColon="@{user.following}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/keyline_2"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?attr/colorOnBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier2"
app:layout_constraintTop_toTopOf="@+id/materialTextView7"
tools:text=": 1" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>