공유 요소 전환 애니메이션이 실행되는 방식을 맞춤설정하려면 공유 요소 전환 방식을 변경하는 데 사용할 수 있는 몇 가지 매개변수가 있습니다.
애니메이션 사양
크기 및 위치 이동에 사용되는 애니메이션 사양을 변경하려면 Modifier.sharedElement()
에서 다른 boundsTransform
매개변수를 지정하면 됩니다.
이렇게 하면 초기 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
사양을 사용합니다.
크기 조절 모드
두 개의 공유 경계 간에 애니메이션을 적용할 때 resizeMode
매개변수를 RemeasureToBounds
또는 ScaleToBounds
로 설정할 수 있습니다. 이 매개변수는 공유 요소가 두 상태 간에 전환되는 방식을 결정합니다. ScaleToBounds
는 먼저 룩아헤드 (또는 타겟) 제약 조건으로 하위 레이아웃을 측정합니다. 그런 다음 자식의 안정적인 레이아웃이 공유 경계 내에 들어맞도록 크기가 조정됩니다.
ScaleToBounds
은 상태 간의 '그래픽 눈금'으로 생각할 수 있습니다.
반면 RemeasureToBounds
는 대상 크기를 기반으로 애니메이션이 적용된 고정된 제약 조건으로 sharedBounds
의 하위 레이아웃을 다시 측정하고 다시 레이아웃합니다. 재측정은 경계 크기 변경으로 트리거되며, 이는 프레임마다 발생할 수 있습니다.
Text
컴포저블의 경우 ScaleToBounds
를 사용하는 것이 좋습니다. 그러면 텍스트가 다른 줄로 재레이아웃되고 다시 흐르지 않기 때문입니다. 가로세로 비율이 다른 경계이고 두 공유 요소 간에 원활한 연속성을 원하는 경우 RemeasureToBounds
를 사용하는 것이 좋습니다.
두 가지 크기 조절 모드의 차이는 다음 예에서 확인할 수 있습니다.
|
|
---|---|
최종 레이아웃으로 건너뛰기
기본적으로 두 레이아웃 간에 전환할 때 레이아웃 크기는 시작 상태와 최종 상태 간에 애니메이션 처리됩니다. 텍스트와 같은 콘텐츠에 애니메이션을 적용할 때는 원치 않는 동작일 수 있습니다.
다음 예는 설명 텍스트 'Lorem Ipsum'이 두 가지 방법으로 화면에 표시되는 것을 보여줍니다. 첫 번째 예에서는 컨테이너 크기가 커질 때 텍스트가 들어가면서 리플로우되고, 두 번째 예에서는 텍스트가 커질 때 리플로우되지 않습니다. Modifier.skipToLookaheadSize()
를 추가하면 크기가 커질 때 리플로가 방지됩니다.
Modifier.skipToLookahead() 없음 - 'Lorem Ipsum' 텍스트가 다시 흐름 처리됨 |
Modifier.skipToLookahead() - 'Lorem Ipsum' 텍스트가 애니메이션 시작 시 최종 상태를 유지합니다. |
---|---|
클립 및 오버레이
Compose에서 공유 요소를 만들 때 중요한 개념은 공유 요소를 서로 다른 컴포저블 간에 공유하려면 전환이 대상에서 일치하는 요소로 시작될 때 컴포저블의 렌더링이 레이어 오버레이로 승격된다는 것입니다. 이렇게 하면 상위 요소의 경계와 레이어 변환 (예: 알파 및 크기)이 이스케이프됩니다.
공유되지 않은 다른 UI 요소 위에 렌더링되며 전환이 완료되면 요소가 오버레이에서 자체 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 )
공유된 요소가 상위 컨테이너 외부에서 렌더링되지 않도록 하려면 sharedElement()
에서 clipInOverlayDuringTransition
를 설정하면 됩니다. 기본적으로 중첩된 공유 경계의 경우 clipInOverlayDuringTransition
는 상위 sharedBounds()
의 클립 경로를 사용합니다.
공유 요소 전환 중에 하단 막대나 플로팅 작업 버튼과 같은 특정 UI 요소를 항상 맨 위에 유지하려면 Modifier.renderInSharedTransitionScopeOverlay()
를 사용하세요. 기본적으로 이 수정자는 공유 전환이 활성 상태인 동안 오버레이에 콘텐츠를 유지합니다.
예를 들어 Jetsnack에서는 화면이 표시되지 않을 때까지 BottomAppBar
를 공유 요소 위에 배치해야 합니다. 컴포저블에 수정자를 추가하면 컴포저블이 계속 올라갑니다.
|
다음으로 서명됨: |
---|---|
공유되지 않은 컴포저블이 애니메이션으로 사라지면서 전환 전에 다른 컴포저블 위에 유지되도록 하려는 경우가 있습니다. 이 경우 renderInSharedTransitionScopeOverlay().animateEnterExit()
를 사용하여 공유 요소 전환이 실행될 때 컴포저블을 애니메이션 처리합니다.
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
공유된 요소가 오버레이에서 렌더링되지 않도록 하려면 드물지만 sharedElement()
의 renderInOverlayDuringTransition
를 false로 설정하면 됩니다.
공유 요소 크기 변경사항을 상위 요소 레이아웃에 알림
기본적으로 sharedBounds()
및 sharedElement()
는 레이아웃 전환 시 크기 변경사항을 상위 컨테이너에 알리지 않습니다.
전환 시 상위 컨테이너에 크기 변경사항을 전파하려면 placeHolderSize
매개변수를 PlaceHolderSize.animatedSize
로 변경합니다. 이렇게 하면 항목이 커지거나 작아집니다. 레이아웃의 다른 모든 항목이 변경사항에 반응합니다.
|
(한 항목이 커지면서 목록의 다른 항목이 아래로 이동하는 것을 볼 수 있습니다.) |
---|---|