Чтобы настроить анимацию перехода общих элементов, можно использовать несколько параметров, которые изменят способ перехода общих элементов.
Спецификация анимации
Чтобы изменить спецификацию анимации, используемую для перемещения размера и положения, вы можете указать другой параметр boundsTransform
в Modifier.sharedElement()
. Это обеспечивает начальную позицию Rect
и целевую позицию Rect
.
Например, чтобы текст в предыдущем примере двигался по дуге, укажите параметр boundsTransform
для использования спецификации keyframes
:
val textBoundsTransform = BoundsTransform { initialBounds, targetBounds -> keyframes { durationMillis = boundsAnimationDurationMillis initialBounds at 0 using ArcMode.ArcBelow using FastOutSlowInEasing targetBounds at boundsAnimationDurationMillis } } Text( "Cupcake", fontSize = 28.sp, modifier = Modifier.sharedBounds( rememberSharedContentState(key = "title"), animatedVisibilityScope = animatedVisibilityScope, boundsTransform = textBoundsTransform ) )
Вы можете использовать любой AnimationSpec
. В этом примере используется спецификация keyframes
.
boundsTransform
Режим изменения размера
При анимации между двумя общими границами можно задать параметр resizeMode
как RemeasureToBounds
или ScaleToBounds
. Этот параметр определяет, как общий элемент переходит между двумя состояниями. ScaleToBounds
сначала измеряет дочерний макет с помощью ограничений lookahead (или target). Затем стабильный макет дочернего элемента масштабируется, чтобы вписаться в общие границы. ScaleToBounds
можно рассматривать как «графическую шкалу» между состояниями.
Напротив, RemeasureToBounds
повторно измеряет и повторно размещает дочерний макет sharedBounds
с анимированными фиксированными ограничениями на основе целевого размера. Повторное измерение запускается изменением размера границ, что потенциально может происходить в каждом кадре.
Для Text
компоновочных элементов ScaleToBounds
рекомендуется, так как он позволяет избежать перекомпоновки и переформатирования текста на разные строки. RemeasureToBounds
рекомендуется для границ с разными соотношениями сторон, а также если вам нужна плавная непрерывность между двумя общими элементами.
Разницу между двумя режимами изменения размера можно увидеть в следующих примерах:
| |
---|---|
Перейти к окончательному макету
По умолчанию при переходе между двумя макетами размер макета анимируется между начальным и конечным состоянием. Это может быть нежелательным поведением при анимации контента, такого как текст.
Следующий пример иллюстрирует текст описания "Lorem Ipsum", поступающий на экран двумя разными способами. В первом примере текст перестраивается по мере того, как контейнер увеличивается в размерах. Во втором примере текст не перестраивается по мере увеличения. Добавление Modifier.skipToLookaheadSize()
предотвращает перестройку по мере увеличения.
Нет | |
---|---|
Клип и накладки
Для того, чтобы общие элементы могли совместно использоваться различными компонуемыми, рендеринг компонуемого повышается до слоя наложения, когда начинается переход к его совпадению в месте назначения. Эффект этого заключается в том, что он избежит границ родителя и его преобразований слоя (например, альфа и масштаб).
Он будет отображаться поверх других неразделяемых элементов пользовательского интерфейса. После завершения перехода элемент будет перемещен из наложения в его собственную DrawScope
.
Чтобы обрезать общий элемент по форме, используйте стандартную функцию Modifier.clip()
. Поместите ее после sharedElement()
:
Image( painter = painterResource(id = R.drawable.cupcake), contentDescription = "Cupcake", modifier = Modifier .size(100.dp) .sharedElement( rememberSharedContentState(key = "image"), animatedVisibilityScope = this@AnimatedContent ) .clip(RoundedCornerShape(16.dp)), contentScale = ContentScale.Crop )
Если вам нужно гарантировать, что общий элемент никогда не будет отображаться за пределами родительского контейнера, вы можете установить clipInOverlayDuringTransition
на sharedElement()
. По умолчанию для вложенных общих границ clipInOverlayDuringTransition
использует путь обрезки из родительского sharedBounds()
.
Для поддержки сохранения определенных элементов пользовательского интерфейса, таких как нижняя панель или плавающая кнопка действия, всегда наверху во время перехода общего элемента, используйте Modifier.renderInSharedTransitionScopeOverlay()
. По умолчанию этот модификатор сохраняет содержимое в наложении во время активности общего перехода.
Например, в Jetsnack BottomAppBar
необходимо разместить поверх общего элемента до тех пор, пока экран не станет невидимым. Добавление модификатора к компонуемому элементу сохраняет его приподнятым.
Без | С |
---|---|
Вы можете захотеть, чтобы ваш неразделяемый компонуемый анимировался, а также оставался поверх других компонуемых перед переходом. В таких случаях используйте renderInSharedTransitionScopeOverlay().animateEnterExit()
для анимации компонуемого выхода, пока выполняется переход общего элемента:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
В редких случаях, когда вы не хотите, чтобы ваш общий элемент отображался в наложении, вы можете установить renderInOverlayDuringTransition
в sharedElement()
в значение false.
Уведомлять родственные макеты об изменениях размера общего элемента
По умолчанию sharedBounds()
и sharedElement()
не уведомляют родительский контейнер об изменениях размера при переходах макета.
Чтобы распространить изменения размера на родительский контейнер при его переходе, измените параметр placeHolderSize
на PlaceHolderSize.animatedSize
. Это приведет к увеличению или уменьшению элемента. Все остальные элементы в макете реагируют на изменение.
| (Обратите внимание, как другие элементы в списке перемещаются вниз в ответ на рост одного элемента) |
---|---|
Чтобы настроить анимацию перехода общих элементов, можно использовать несколько параметров, которые изменят способ перехода общих элементов.
Спецификация анимации
Чтобы изменить спецификацию анимации, используемую для перемещения размера и положения, вы можете указать другой параметр boundsTransform
в Modifier.sharedElement()
. Это обеспечивает начальную позицию Rect
и целевую позицию Rect
.
Например, чтобы текст в предыдущем примере двигался по дуге, укажите параметр boundsTransform
для использования спецификации keyframes
:
val textBoundsTransform = BoundsTransform { initialBounds, targetBounds -> keyframes { durationMillis = boundsAnimationDurationMillis initialBounds at 0 using ArcMode.ArcBelow using FastOutSlowInEasing targetBounds at boundsAnimationDurationMillis } } Text( "Cupcake", fontSize = 28.sp, modifier = Modifier.sharedBounds( rememberSharedContentState(key = "title"), animatedVisibilityScope = animatedVisibilityScope, boundsTransform = textBoundsTransform ) )
Вы можете использовать любой AnimationSpec
. В этом примере используется спецификация keyframes
.
boundsTransform
Режим изменения размера
При анимации между двумя общими границами можно задать параметр resizeMode
как RemeasureToBounds
или ScaleToBounds
. Этот параметр определяет, как общий элемент переходит между двумя состояниями. ScaleToBounds
сначала измеряет дочерний макет с помощью ограничений lookahead (или target). Затем стабильный макет дочернего элемента масштабируется, чтобы вписаться в общие границы. ScaleToBounds
можно рассматривать как «графическую шкалу» между состояниями.
Напротив, RemeasureToBounds
повторно измеряет и повторно размещает дочерний макет sharedBounds
с анимированными фиксированными ограничениями на основе целевого размера. Повторное измерение запускается изменением размера границ, что потенциально может происходить в каждом кадре.
Для Text
компоновочных элементов ScaleToBounds
рекомендуется, так как он позволяет избежать перекомпоновки и переформатирования текста на разные строки. RemeasureToBounds
рекомендуется для границ с разными соотношениями сторон, а также если вам нужна плавная непрерывность между двумя общими элементами.
Разницу между двумя режимами изменения размера можно увидеть в следующих примерах:
| |
---|---|
Перейти к окончательному макету
По умолчанию при переходе между двумя макетами размер макета анимируется между начальным и конечным состоянием. Это может быть нежелательным поведением при анимации контента, такого как текст.
Следующий пример иллюстрирует текст описания "Lorem Ipsum", поступающий на экран двумя разными способами. В первом примере текст перестраивается по мере того, как контейнер увеличивается в размерах. Во втором примере текст не перестраивается по мере увеличения. Добавление Modifier.skipToLookaheadSize()
предотвращает перестройку по мере увеличения.
Нет | |
---|---|
Клип и накладки
Для того, чтобы общие элементы могли совместно использоваться различными компонуемыми, рендеринг компонуемого повышается до слоя наложения, когда начинается переход к его совпадению в месте назначения. Эффект этого заключается в том, что он избежит границ родителя и его преобразований слоя (например, альфа и масштаб).
Он будет отображаться поверх других неразделяемых элементов пользовательского интерфейса. После завершения перехода элемент будет перемещен из наложения в его собственную DrawScope
.
Чтобы обрезать общий элемент по форме, используйте стандартную функцию Modifier.clip()
. Поместите ее после sharedElement()
:
Image( painter = painterResource(id = R.drawable.cupcake), contentDescription = "Cupcake", modifier = Modifier .size(100.dp) .sharedElement( rememberSharedContentState(key = "image"), animatedVisibilityScope = this@AnimatedContent ) .clip(RoundedCornerShape(16.dp)), contentScale = ContentScale.Crop )
Если вам нужно гарантировать, что общий элемент никогда не будет отображаться за пределами родительского контейнера, вы можете установить clipInOverlayDuringTransition
на sharedElement()
. По умолчанию для вложенных общих границ clipInOverlayDuringTransition
использует путь обрезки из родительского sharedBounds()
.
Для поддержки сохранения определенных элементов пользовательского интерфейса, таких как нижняя панель или плавающая кнопка действия, всегда наверху во время перехода общего элемента, используйте Modifier.renderInSharedTransitionScopeOverlay()
. По умолчанию этот модификатор сохраняет содержимое в наложении во время активности общего перехода.
Например, в Jetsnack BottomAppBar
необходимо разместить поверх общего элемента до тех пор, пока экран не станет невидимым. Добавление модификатора к компонуемому элементу сохраняет его приподнятым.
Без | С |
---|---|
Вы можете захотеть, чтобы ваш неразделяемый компонуемый анимировался, а также оставался поверх других компонуемых перед переходом. В таких случаях используйте renderInSharedTransitionScopeOverlay().animateEnterExit()
для анимации компонуемого выхода, пока выполняется переход общего элемента:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
В редких случаях, когда вы не хотите, чтобы ваш общий элемент отображался в наложении, вы можете установить renderInOverlayDuringTransition
в sharedElement()
в значение false.
Уведомлять родственные макеты об изменениях размера общего элемента
По умолчанию sharedBounds()
и sharedElement()
не уведомляют родительский контейнер об изменениях размера при переходах макета.
Чтобы распространить изменения размера на родительский контейнер при его переходе, измените параметр placeHolderSize
на PlaceHolderSize.animatedSize
. Это приведет к увеличению или уменьшению элемента. Все остальные элементы в макете реагируют на изменение.
| (Обратите внимание, как другие элементы в списке перемещаются вниз в ответ на рост одного элемента) |
---|---|