Egor
Egor

Reputation: 40193

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:

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

Upvotes: 6

Views: 531

Answers (1)

Ryan M
Ryan M

Reputation: 20119

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

Upvotes: 7

Related Questions