Chinthaka Devinda
Chinthaka Devinda

Reputation: 1085

Aligning Text View with constraint Layout

I am trying to align my textview in the constraint layout without using margins so the layout can be responsive in all the devices but so far I am stuck in positioning. Here is my code and expected output attached in the image. I just want to make the amount align slightly with currency text. This is the expected output

<?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="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

     <TextView
         android:id="@+id/year_bar_chart_total"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="Total"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
         />
     <TextView
         android:id="@+id/yearBarChartCurrency"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="RM"
         app:layout_constraintEnd_toEndOf="@+id/yearBarChartAmount"
         app:layout_constraintHorizontal_bias="0.17"
         app:layout_constraintStart_toStartOf="@id/year_bar_chart_total"
         app:layout_constraintTop_toBottomOf="@id/year_bar_chart_total"
         tools:text="RM"/>
     <TextView
         android:id="@+id/yearBarChartAmount"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="tOTAL"
         app:layout_constraintHorizontal_bias="0.17"
         app:layout_constraintStart_toEndOf="@id/yearBarChartCurrency"
         app:layout_constraintTop_toBottomOf="@id/year_bar_chart_total"
         tools:text="233.34"/>

</android.support.constraint.ConstraintLayout>

Upvotes: 2

Views: 2900

Answers (2)

Cheticamp
Cheticamp

Reputation: 62831

I assume you want to align the tops of the text.

A TextView has an internal structure based upon the typography of the font. "Android 101: Typography" has a good explanation of Android typography. This diagram is particularly useful.

So, the following layout looks like this in design view. As you can see, the tops of the text do not line up.

enter image description here

activity_main.xml

<android.support.constraint.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#4778C5"
    android:orientation="vertical"
    tools:context=".MainActivity">


    <TextView
        android:id="@+id/year_bar_chart_total"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:alpha="0.7"
        android:text="Balance"
        android:textColor="@android:color/white"
        android:textSize="24sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/yearBarChartCurrency"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="RM"
        android:textColor="@android:color/white"
        android:textSize="24sp"
        app:layout_constraintStart_toStartOf="@+id/year_bar_chart_total"
        app:layout_constraintTop_toBottomOf="@+id/year_bar_chart_total"
        tools:text="RM" />

    <TextView
        android:id="@+id/yearBarChartAmount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="4sp"
        android:paddingLeft="4sp"
        android:text="233.34"
        android:textColor="@android:color/white"
        android:textSize="36sp"
        android:textStyle="bold"
        app:layout_constraintStart_toEndOf="@+id/yearBarChartCurrency"
        app:layout_constraintTop_toTopOf="@+id/yearBarChartCurrency" />

</android.support.constraint.ConstraintLayout>

Although the fonts of the TextViews are the same, the different font sizes prevent alignment of the tops of the actual text even though the TextViews have their tops align. This is because the metrics differ.

So, to align the actual tops of the text, we need to determine how far below the TextView tops the actual text starts and shift the text by those amounts. The following code does this. Comments are in the code.

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView yearBarChartAmount = findViewById(R.id.yearBarChartAmount);
        TextView yearBarChartCurrency = findViewById(R.id.yearBarChartCurrency);
        yearBarChartCurrency.setTranslationY(-getTopOfText(yearBarChartCurrency));
        yearBarChartAmount.setTranslationY(-getTopOfText(yearBarChartAmount));
    }

    private int getTopOfText(TextView textView) {
        // Force measure of text pre-layout.
        textView.measure(0, 0);

        // bounds will store the rectangle that will circumscribe the text.
        Rect bounds = new Rect();

        // Get the bounds for the text. Top and bottom are measured from the baseline. Left
        // and right are measured from 0.
        String text = (String) textView.getText();
        textView.getPaint().getTextBounds(text, 0, text.length(), bounds);
        return textView.getBaseline() + bounds.top;
    }
}

The following is what is displayed:

enter image description here

There may be other considerations, but this is the gist of the solution. It may be worthwhile to encapsulate this into a custom TextView.

Upvotes: 2

Tamir Abutbul
Tamir Abutbul

Reputation: 7661

You can use guidelines to achieve this :

<androidx.constraintlayout.widget.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="match_parent">

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_percent="0.1" />

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.1" />

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.25" />

<TextView
    android:id="@+id/textView4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="balance"
    app:layout_constraintBottom_toTopOf="@+id/textView5"
    app:layout_constraintStart_toStartOf="@+id/guideline3" />

<TextView
    android:id="@+id/textView5"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="RM"
    app:layout_constraintBottom_toTopOf="@+id/guideline2"
    app:layout_constraintStart_toStartOf="@+id/guideline3" />

<TextView
    android:id="@+id/textView8"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="233.34"
    app:layout_constraintEnd_toStartOf="@+id/guideline4"
    app:layout_constraintStart_toEndOf="@+id/textView5"
    app:layout_constraintTop_toBottomOf="@+id/textView4" />

It will look like this:

enter image description here

I must emphasize one thing that really bothered me:

"margins so the layout can be responsive in all the devices" - this is not true and let me explain.

what makes your screen responsive to all screen sizes is constraintLayout and how you use it, I agree that a large number of margin in dp will make your screen not responsive but small margins are recommended to use in google material design - it will actually give your app better look and prevent your views from being attached directly to the parent border.

Upvotes: 2

Related Questions