Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to arrange elements inside a Row, where one element has infinite width?

I'm trying to translate the following layout to Compose:

enter image description here

As you can see, the text on the left can be long, but it's allowed to wrap - the important thing is that it leaves enough space for the text on the right to be rendered. Here's what it looks like in XML:

<?xml version="1.0" encoding="utf-8"?>
<merge 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"
    tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"
    >
  <TextView
      android:id="@+id/stock_name"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginEnd="16dp"
      android:textAppearance="@style/TextAppearance.AppCompat.Medium"
      app:layout_constraintEnd_toStartOf="@+id/holding_quantity"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      tools:text="Vanguard Total Stock Market Index Fund ETF Shares"
      />
  <TextView
      android:id="@+id/holding_quantity"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textAppearance="@style/TextAppearance.AppCompat.Display1"
      android:textColor="?attr/colorAccent"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      tools:text="10"
      />
</merge>

I'm struggling to find the right Row configuration that would work:

@Composable fun HoldingView() {
  Row {
    val typography = MaterialTheme.typography
    Text("Vanguard Total Stock Market Index Fund ETF Shares", style = typography.body1)
    Spacer(Modifier.preferredWidth(16.dp))
    Text("10", style = typography.h4, color = MaterialTheme.colors.secondary)
  }
}

Without any extra modifiers, this simply pushes the text on the right out of bounds:

enter image description here

Things I've tried without any luck:

  • Playing with various Arrangement options, such as SpaceBetween
  • Assigning a Modifier.weight(1f) to the second Text

Neither of these had any effect on how the views are laid out. Is there a configuration that would work for this use case?

like image 632
Egor Avatar asked Jan 02 '21 03:01

Egor


1 Answers

The solution is to use Modifier.weight(1f) (which is available on the RowScope within the Row{ ... }) on the Text that you want to fill available space after all the other elements are laid out (that is, in your case, the first one).

So your example would look like:

Row {
    val typography = MaterialTheme.typography
    Text(
        "Vanguard Total Stock Market Index Fund ETF Shares",
        style = typography.body1,
        modifier = Modifier.weight(1f)
    )
    Spacer(Modifier.preferredWidth(16.dp))
    Text("10", style = typography.h4, color = MaterialTheme.colors.secondary)
}

which renders as (poor cropping on my screenshot messing with the margins on the edges notwithstanding) screenshot of "Vanguard Total Stock Market Index Fund ETF Shares" and "10" both visible in a row

like image 70
Ryan M Avatar answered Oct 03 '22 23:10

Ryan M