I have two pages that both use the same input box ...
# compose
n
I have two pages that both use the same input box component. This input box component uses
shared element animation
, which animates with a full-screen interface within the app(Not via navigation, just AnimatedVisibility). However, if page A navigates to B (both pages use this input box), the input box from page A will detach from the page and stay on screen, only removing from the screen when navigation to page B completes. In this case, what's a good practice to separate the
rememberSharedContentState key
for this input box? Should I set different keys based on the
navigation destination
? 🤔
Copy code
val lifecycleOwner = LocalLifecycleOwner.current

  Column(
    modifier = Modifier
.thenIf(lifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
        sharedBounds(
          sharedContentState = rememberSharedContentState(TransitionKey.ChatRoot),
          animatedVisibilityScope = this@AnimatedVisibility,
          resizeMode = RemeasureToBounds
        )
      }
  )
This seems to solve the problem for the time being, but there are still a few frames that make the composable momentary twitch (unable to properly maintain the original screen position and navigate with the page)
d
Consider using a data class for the
SharedContentState
key in this case and include the origin as a part of the data class, so that it will used in
.equals
check for the key as well. Here's an example: https://developer.android.com/develop/ui/compose/animation/shared-elements#unique-keys
❤️ 1
n
It seems that creating a
data class
with an origin property based on the
current navigation destination
as a key for
rememberSharedContentState
is a correct approach? 👀 my case is looks like this:
Copy code
@Composable
fun animatedLayout() = Column(
 modifier = Modifier.sharedBounds(
  sharedContentState = rememberSharedContentState(
    key = SharedElementKey(
      origin = navController.currentDestination?.route,
      type = TransitionKey.layoutRoot // enum class
    )
  ),
  animatedVisibilityScope = this@AnimatedVisibility,
  resizeMode = RemeasureToBounds
 )
)

@Composable
fun targetAnimatedLayout() = Column(
 modifier = Modifier.sharedBounds(
  sharedContentState = rememberSharedContentState(
    key = SharedElementKey(
      origin = "route a",
      type = TransitionKey.layoutRoot // enum class
    )
  ),
  animatedVisibilityScope = this@AnimatedVisibility,
  resizeMode = RemeasureToBounds
 ).sharedBounds(
  sharedContentState = rememberSharedContentState(
    key = SharedElementKey(
      origin = "route b",
      type = TransitionKey.layoutRoot // enum class
    )
  ),
  animatedVisibilityScope = this@AnimatedVisibility,
  resizeMode = RemeasureToBounds
 )
)

@Composable
fun A() { animatedLayout() }

@Composable
fun B() { animatedLayout() }

@Composable
fun App() {
  Box {
    NavHost {
      A()
      B()
    }
    targetAnimatedLayout()
  }
}
In the pages of A and B, they can both share elements from the animatedLayout component to targetAnimatedLayout But to navigate from A to B, the animatedLayout component shouldn't have any animations, right
d
Yes. This could work. 🙂