When in ColumnScope for example, if I need to have...
# compose
s
When in ColumnScope for example, if I need to have a AnimatedVisibility, for the contents of it, they don’t “inherit” this column scope, and they are laid out on top of each other. To mitigate that you need to have another column in there to make it work as you want it to. Something like this:
Copy code
Column {
  Stuff()
  AnimatedVisibility(shouldShow) {
    Column {
      Text()
      Spacer(Modifier.width(8.dp))
      Icon()
    }
  }
}
But when doing this with CompositionLocalProvider like this:
Copy code
Column {
  Stuff()
  CompositionLocalProvider(LocalContentColor provides LocalContentColor.current.copy(alpha = ContentAlpha.medium)) {
    Text()
    Spacer(Modifier.width(8.dp))
    Icon()
  }
}
You don’t need to do this, it just works. Why is this the case?
CompositionLocalProvider
isn’t even inline or something like that, nor is it an extension on ColumnScope for it to work due to that. So how does it work? What am I missing here?
👀 2
z
I would guess that its due to AnimatedVisibility putting the content into some kind of container/layout, whereas CompositionLocalProvider just ensures that the provided values are present when the content block is invoked.
Copy code
@Composable
@OptIn(InternalComposeApi::class)
fun CompositionLocalProvider(vararg values: ProvidedValue<*>, content: @Composable () -> Unit) {
    currentComposer.startProviders(values)
    content()
    currentComposer.endProviders()
}
Copy code
@ExperimentalAnimationApi
@Composable
private inline fun AnimatedEnterExitImpl(
    transition: Transition<EnterExitState>,
    modifier: Modifier,
    enter: EnterTransition,
    exit: ExitTransition,
    content: @Composable AnimatedVisibilityScope.() -> Unit
) {
    if (transition.currentState == EnterExitState.Visible ||
        transition.targetState == EnterExitState.Visible
    ) {
        val scope = remember(transition) { AnimatedVisibilityScopeImpl(transition) }
        Layout(
            content = { scope.content() },
            modifier = modifier.then(transition.createModifier(enter, exit, "Built-in")),
            measurePolicy = remember { AnimatedEnterExitMeasurePolicy(scope) }
        )
    }
}
l
Modifiers in ColumnScope are only visible to the direct children, as they all emits ParentDataModifierNode, where only the direct parent can receive the data. AnimatedContent however, wraps the content inside a Box, so the content isn't the direct child of the Column.