0

The entire text is seperated in three tet view. First date, "-", second date

I would like to align it to have every element below each other. For example every dash should be exactly below each other. first date - second date Longer example - Longer second date

I have tried using guide lines, but on small phones it doesn't work well. I have changed it programmatically regarding to the screen, but it is not proper. I also used table row, but it doesn't give the effect. What could be a solution for it? Also is it possible if the second date textview doesn't fit to the right part of the screen it goes below?

my_recycler_item

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="wrap_content"
    android:id="@+id/constraint_layout_1">

    <TextView
        android:id="@+id/tv_my_assignments_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:paddingVertical="4dp"
        android:text="Monday 17"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

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

    <TextView
        android:id="@+id/tv_my_assignments_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:paddingVertical="4dp"
        android:text=" - "
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
        app:layout_constraintEnd_toEndOf="@id/gl_2"
        app:layout_constraintStart_toEndOf="@+id/gl_1"
        app:layout_constraintTop_toTopOf="parent" />

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

    <TextView
        android:id="@+id/tv_my_assignments_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:paddingVertical="4dp"
        android:text="Tuesday 18 okt 2022"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
        app:layout_constraintStart_toEndOf="@+id/gl_2"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Wrong approach below

Chris
  • 63
  • 6

2 Answers2

0

If you want to align all dashes for dates one under the another, you will need to determine the longest first date string in your data. See this for some clues on how to measure text. You would use the Paint from the TextView.

Once you have the longest first date length, you would set the width of those TextViews to that longest length when you create your view holders. The center TextView holding the dash will then fall in line. (You could also place a GuideLine given the length of the longest TextView.)

That leaves the rightmost TextView. If the second date is too long for its TextView, you need to decide if you want to truncate it, scroll it or wrap it to another line. That is a design consideration you will have to think through.

This all assumes that you have access to all dates before the RecyclerView is populated. Of course, if any dates change while the RecyclerView is laid out such that it will change the above calculation, you will need to make adjustments.

Another approach would be to determine the longest date you will ever see given your font and setting the TextView to that width.

Cheticamp
  • 61,413
  • 10
  • 78
  • 131
  • The problem is in one phone the longest String i 70% of view i the another one it is 35%. – Chris Oct 04 '22 at 15:07
  • Then it doesn't fit. You will have to make a decision about what to do. You can reduce the font size so it fits, truncate the view, scroll it or continue it on a second line. Unfortunately, that is just the reality of it. – Cheticamp Oct 04 '22 at 17:08
0

Like Cheticamp says, this is more of a design issue than anything. Just to get this out of the way - a Guideline can't help you here, because what you want to do is constrain/align views * across multiple layouts*. With a RecyclerView, you have a handful of ViewHolder objects, and each one has its own inflated layout hierarchy (created through onCreateViewHolder).

Even though they're all generated from the same layout XML, the results are all completely independent collections of Views and they have no way to communicate, and negotiate some overall shared position for the Guideline in each ViewHolder. They can't all work out who has the longest line of text currently, and all update to reflect that. Besides, maybe you're not even displaying the longest one yet, maybe it comes later in your data? What should happen then, does everything on the screen jump to the side to accomodate the new big width?


You could do a whole lot of work handling this in code, calculating stuff, informing all your layouts how they should re-constrain themselves... but honestly, rethinking your design would probably be better. Especially when you're already running into the issue of some screens (or font-size settings) being bigger or smaller or others.

I'd probably do it this way - centre your dash in its own TextView, then constrain the two time TextViews in the space either side of it. That way the dash is always in the same place, right in the middle, which looks nice and consistent:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:tools="http://schemas.android.com/tools"
    android:minHeight="72dp"
    android:padding="8dp"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:id="@+id/separator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingHorizontal="8dp"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
        android:text="—"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        />

    <TextView
        android:id="@+id/startTime"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
        tools:text="Tue 30 Aug 2016, 0:00"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/separator"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        />

    <TextView
        android:id="@+id/endTime"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
        tools:text="Thu 22 Sep 2022, 23:59"
        android:gravity="end"
        app:layout_constraintStart_toEndOf="@id/separator"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

The list item layout with a centred dash, and the times either side, justified to either edge of the parent

The same image as above but with constraints visible

Obviously you can adjust the justification (gravity) to whatever you want, so you could have it up against the dash so everything is centred, rather than against the edges. Depends what kind of look you prefer!


The other advantage of this approach is it adapts to different sizes well. We've pretty much defined one thing - the separator goes in the middle, and everything else goes either side of that (and the containing layout's height is wrap_content with a minHeight so it can expand if it needs to). This means you can go to extremes, like a very small watch screen:

The same layout on a small square watch screen - the time text breaks over multiple lines, but it still looks consistent

and it's not just neat and readable, it looks like the same design right? There are always compromises when things have to fit different spaces and ideally look decent while they do it, but I feel like this is pretty ok! I'm no designer so it could definitely be tweaked, but the basic idea for the layout is a typical one, because it works. No need to get complicated with workarounds in your code, unless that's something you really want to do!

cactustictacs
  • 17,935
  • 2
  • 14
  • 25