뒤로 탐색 예측 애니메이션 지원 추가

System Back API를 사용하면 인앱 애니메이션을 수신하고 맞춤 전환을 지원하도록 선택할 수 있습니다.

동영상 1: 뒤로 탐색 예측 애니메이션

선택 후에는 앱에 홈으로 돌아가기, 교차 활동 및 교차 작업을 위한 애니메이션이 표시됩니다.

이 동영상은 Android 설정 앱을 사용하는 교차 활동 및 홈으로의 이동을 위한 뒤로 탐색 예측 애니메이션의 간단한 예를 보여줍니다.

  1. 애니메이션에서 사용자는 뒤로 스와이프하여 이전 설정 화면으로 돌아갑니다(교차 활동 애니메이션의 예).
  2. 이제 이전 화면에서 사용자가 두 번째로 뒤로 스와이프하기 시작하면 배경화면으로 홈 화면의 미리보기가 표시됩니다. 이는 홈으로 돌아가기 애니메이션의 예입니다.
  3. 사용자가 계속해서 오른쪽으로 스와이프하면서 홈 화면의 아이콘으로 축소되는 애니메이션을 보여줍니다.
  4. 이제 사용자가 홈 화면으로 완전히 돌아왔습니다.

뒤로 탐색 예측 동작 지원을 추가하는 방법을 자세히 알아보세요.

맞춤 인앱 전환 및 애니메이션 추가

Compose 또는 뷰를 사용하여 맞춤 인앱 속성 애니메이션과 전환, 맞춤 교차 활동 애니메이션, 뒤로 탐색 예측 동작이 있는 맞춤 교차 프래그먼트 애니메이션을 만들 수 있습니다. 뷰를 사용하여 전환을 만드는 방법을 알아보려면 뷰에서 뒤로 탐색 예측 애니메이션 지원 추가를 참고하세요.

Jetpack Compose에서 맞춤 전환 추가

PredictiveBackHandler를 사용하여 Jetpack Compose에서 뒤로 탐색 예측 동작을 처리하여 맞춤 인앱 전환을 만들 수 있습니다. 이 기능은 androidx.activity:activity-compose:1.8.0-alpha01 이상에서 사용할 수 있습니다.

PredictiveBackHandler는 사용자가 가장자리에서 뒤로 스와이프할 때 이벤트를 내보내는 Flow<BackEventCompat>을 노출하는 콜백 람다를 제공합니다. 이러한 이벤트는 사용자 터치 위치, 스와이프 가장자리, 가장 중요한 progress에 관한 정보를 제공하며, 이는 뒤로 동작을 처리하는 과정에서 구성요소를 애니메이션으로 이동하는 데 사용할 수 있습니다.

다음 스니펫은 PredictiveBackHandler을 사용하여 Surface의 크기를 줄이고 제스처 진행과 함께 멀리 이동하는 애니메이션을 적용하는 예를 보여줍니다.

@Composable
fun DetailScreen(onBack: () -> Unit) {
    var scale by remember { mutableFloatStateOf(1f) }
    var xOffset by remember { mutableFloatStateOf(0f) }
    val scope = rememberCoroutineScope()

    PredictiveBackHandler { progressFlow ->
        try {
            progressFlow.collectLatest { backEvent ->
                scale = 1f - backEvent.progress
                xOffset = backEvent.progress * 100f
            }
            // User completed gesture.
            onBack()
        } catch (e: CancellationException) {
            // User cancelled gesture.
            // Animate scale and xOffset back to 1f and 0f respectively.
            scope.launch {
                animate(scale, 1f) { value, _ -> scale = value }
            }
            scope.launch {
                animate(xOffset, 0f) { value, _ -> xOffset = value }
            }
        }
    }
    Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Surface(
            modifier = Modifier
                .size(200.dp)
                .scale(scale)
                .offset { IntOffset(x = xOffset.dp.roundToPx(), y = 0) },
            color = Color.Blue
        ) {}
    }
}