میتوانید کلاس انتزاعی NavigationEventHandler را گسترش دهید تا رویدادهای پیمایش را در پلاتفرمها مدیریت کند. این کلاس روشهایی متناسب با
چرخه حیات اشاره پیمایش ارائه میدهد.
val myHandler = object: NavigationEventHandler<NavigationEventInfo>( initialInfo = NavigationEventInfo.None, isBackEnabled = true ) { override fun onBackStarted(event: NavigationEvent) { // Prepare for the back event } override fun onBackProgressed(event: NavigationEvent) { // Use event.progress for predictive animations } // This is the required method for final event handling override fun onBackCompleted() { // Complete the back event } override fun onBackCancelled() { // Cancel the back event } }
تابع addHandler کنترلکننده را به توزیعکننده متصل میکند:
navigationEventDispatcher.addHandler(myHandler)
برای برداشتن کارپرداز از توزیعکننده، با myHandler.remove() تماس بگیرید:
myHandler.remove()
مدیران براساس اولویت و سپس براساس جدیدترین فراخوانده میشوند. همه
پردازشگرهای PRIORITY_OVERLAY قبلاز هر پردازشگر PRIORITY_DEFAULT
فراخوانی میشوند. در هر گروه اولویت، کنترلکنندهها به ترتیب «آخرین ورودی،
اولین خروجی» (LIFO) فراخوانی میشوند — کنترلکننده اضافهشده در آخرین زمان ابتدا فراخوانی میشود.
جلوگیری از برگشت با Jetpack Compose
برای Jetpack Compose، کتابخانه یک عنصر ترکیبی کاربردی برای مدیریت سلسله مراتب توزیعکننده ارائه میدهد.
ترکیبپذیر NavigationBackHandler یک NavigationEventHandler برای محتوایش ایجاد میکند و آن را به LocalNavigationEventDispatcherOwner پیوند میدهد. این تابع از DisposableEffect در
Compose استفاده میکند تا وقتی عنصر ترکیبی از صفحه خارج میشود، بهطور خودکار روش dispose()
توزیعکننده را فراخوانی کند و منابع را بهطور ایمن مدیریت کند.
@Composable public fun NavigationBackHandler( state: NavigationEventState<out NavigationEventInfo>, isBackEnabled: Boolean = true, onBackCancelled: () -> Unit = {}, onBackCompleted: () -> Unit, ){ }
این تابع به شما امکان میدهد مدیریت رویداد را دقیقاً در زیردرختهای رابط کاربری بومیسازیشده کنترل کنید.
@Composable fun HandlingBackWithTransitionState( onNavigateUp: () -> Unit ) { val navigationState = rememberNavigationEventState( currentInfo = NavigationEventInfo.None ) val transitionState = navigationState.transitionState // React to predictive back transition updates when (transitionState) { is NavigationEventTransitionState.InProgress -> { val progress = transitionState.latestEvent.progress // Use progress (0f..1f) to update UI during the gesture } is NavigationEventTransitionState.Idle -> { // Reset any temporary UI state if the gesture is cancelled } } NavigationBackHandler( state = navigationState, onBackCancelled = { // Called if the back gesture is cancelled }, onBackCompleted = { // Called when the back gesture fully completes onNavigateUp() } ) }
این مثال نشان میدهد که چگونه بهروزرسانیهای اشاره برگشت پیشبینانه را بااستفاده از
NavigationEventTransitionState مشاهده کنید. از مقدار progress میتوان برای
بهروزرسانی عناصر واسط کاربر در پاسخ به اشاره برگشت استفاده کرد، درحالیکه تکمیل
و لغو ازطریق NavigationBackHandler مدیریت میشود.
دسترسی به اشاره برگشتن یا تند کشیدن لبه در «نوشتن»
شکل ۱. پویانمایی اشاره برگشت پیشگویانه که با NavigationEvent و Compose ساخته شده است.
برای پویانمایی صفحه هنگام تند کشیدن کاربر به عقب، باید (الف) بررسی کنید که آیا NavigationEventTransitionState InProgress است یا نه، و (ب) وضعیت لبه تند کشیدن و پیشرفت را با rememberNavigationEventState مشاهده کنید:
-
progress: «شناور» از0.0تا1.0که نشان میدهد کاربر چقدر تند کشیده است. -
swipeEdge: ثابت عدد صحیح (EDGE_LEFTیاEDGE_RIGHT) که نشان میدهد ژست از کجا شروع شده است.
تکهکد زیر نمونه سادهای از نحوه پیادهسازی پویانمایی مقیاس و تغییر است:
object Routes { const val SCREEN_A = "Screen A" const val SCREEN_B = "Screen B" } class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { var state by remember { mutableStateOf(Routes.SCREEN_A) } val backEventState = rememberNavigationEventState<NavigationEventInfo>(currentInfo = NavigationEventInfo.None) when (state) { Routes.SCREEN_A -> { ScreenA(onNavigate = { state = Routes.SCREEN_B }) } else -> { if (backEventState.transitionState is NavigationEventTransitionState.InProgress) { ScreenA(onNavigate = { }) } ScreenB( backEventState = backEventState, onBackCompleted = { state = Routes.SCREEN_A } ) } } } } } @Composable fun ScreenB( backEventState: NavigationEventState<NavigationEventInfo>, onBackCompleted: () -> Unit = {}, ) { val transitionState = backEventState.transitionState val latestEvent = (transitionState as? NavigationEventTransitionState.InProgress) ?.latestEvent val backProgress = latestEvent?.progress ?: 0f val swipeEdge = latestEvent?.swipeEdge ?: NavigationEvent.EDGE_LEFT if (transitionState is NavigationEventTransitionState.InProgress) { Log.d("BackGesture", "Progress: ${transitionState.latestEvent.progress}") } else if (transitionState is NavigationEventTransitionState.Idle) { Log.d("BackGesture", "Idle") } val animatedScale by animateFloatAsState( targetValue = 1f - (backProgress * 0.1f), label = "ScaleAnimation" ) val windowInfo = LocalWindowInfo.current val density = LocalDensity.current val maxShift = remember(windowInfo, density) { val widthDp = with(density) { windowInfo.containerSize.width.toDp() } (widthDp.value / 20f) - 8 } val offsetX = when (swipeEdge) { NavigationEvent.EDGE_LEFT -> (backProgress * maxShift).dp NavigationEvent.EDGE_RIGHT -> (-backProgress * maxShift).dp else -> 0.dp } NavigationBackHandler( state = backEventState, onBackCompleted = onBackCompleted, isBackEnabled = true ) Box( modifier = Modifier .offset(x = offsetX) .scale(animatedScale) ){ // Rest of UI } }