Mahdi-Malv
Mahdi-Malv

Reputation: 19240

Change layout direction of a Composable

I want to set a direction of a specific composable to be RTL


@Composable
fun ViewToBeChanged() {
  Row {
     Image()
     Column {
        Text("Title")
        Text("Subtitle")
    }
  }
}

Is it possible?

Jetpack compose Layout documentation mentions LocalLayoutDirection

Change the layout direction of a composable by changing the LocalLayoutDirection compositionLocal.

But I have no idea how to use it in a composable to take effect.

Upvotes: 44

Views: 17678

Answers (6)

Azade Rahmati
Azade Rahmati

Reputation: 207

if you need to change all activity direction, you can wrap your surface component by:

CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl){
                Surface(color = MaterialTheme.colorScheme.background) {
                   
                   
                }

            }

Upvotes: 1

LazyBee
LazyBee

Reputation: 71

Using CompositionLocalProvider to change orientation has the potential risk of causing all child layouts to change orientation, which may not be what we expect. And using LazyColumn or LazyRow can invert the layout but the functionality of the child layouts will be limited and there are some strange restrictions, so here is my solution

@Composable
fun ReversibleRow(
    modifier: Modifier = Modifier,
    horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
    verticalAlignment: Alignment.Vertical = Alignment.Top,
    reverseLayout: Boolean = false,
    content: @Composable RowScope.() -> Unit
) {
    val originDirection = LocalLayoutDirection.current
    val direction = when {
        reverseLayout -> when (originDirection) {
            LayoutDirection.Rtl -> LayoutDirection.Ltr
            else -> LayoutDirection.Rtl
        }
        else -> originDirection
    }
    CompositionLocalProvider(LocalLayoutDirection provides direction) {
        Row(modifier, horizontalArrangement, verticalAlignment) {
            CompositionLocalProvider(LocalLayoutDirection provides originDirection) {
                content()
            }
        }
    }
}

Use ReversibleRow to replace Row. same for Column

Upvotes: 7

fstanis
fstanis

Reputation: 5534

For a Row specifically, you can influence the RTL / LTR behavior using the horizontalArrangement parameter. The default is Arrangement.Start which takes into account layout direction. Using one of Arrangement.Absolute allows you to give an arrangement that ignores layout direction.

In your example:

@Composable
fun ViewToBeChanged() {
  Row(horizontalArrangement = Arrangement.Right) {
     Image()
     Column {
        Text("Title")
        Text("Subtitle")
    }
  }
}

Upvotes: 4

Super Symmetry
Super Symmetry

Reputation: 2875

As a generalisation of the other answers, if this is needed in different Composables we can define the following

@Composable
fun RightToLeftLayout(content: @Composable () -> Unit) {
    CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
        content()
    }
}

then simply use

RightToLeftLayout {
    ViewToBeChanged()
}

or

RightToLeftLayout {
    Row {
        ...
    }
}
   

Upvotes: 5

Gabriele Mariotti
Gabriele Mariotti

Reputation: 364005

You can use the CompositionLocalProvider to provide a custom LocalLayoutDirection.

Something like:

CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl ) {
    Column(Modifier.fillMaxWidth()) {
        Text("Title")
        Text("Subtitle")
    }
}

Upvotes: 77

CommonsWare
CommonsWare

Reputation: 1006924

Since I did not have your image, I tweaked your composable to:

@Composable
fun ViewToBeChanged() {
  Row {
    Text("Foo", modifier = Modifier.padding(end = 8.dp))

    Column {
      Text("Title")
      Text("Subtitle")
    }
  }
}

That gives us:

ViewToBeChanged() rendering

One way to switch to RTL is to use CompositionLocalProvider and LocalLayoutDirection:

@Composable
fun RtlView() {
  CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
    Row {
      Text("Foo", modifier = Modifier.padding(end = 8.dp))

      Column {
        Text("Title")
        Text("Subtitle")
      }
    }
  }
}

Here, we are saying that we are overriding the CompositionLocal for layout direction for the contents of the trailing lambda supplied to CompositionLocalProvider(). This gives us:

RtlView() rendering

This changes the layout direction used by this branch of the composable tree, for the composables itself. English is still a LTR language, so the text is unaffected.

Upvotes: 17

Related Questions