تتيح ميزة "تقسيم المحتوى إلى صفحات" للمستخدمين التمرير سريعًا بشكل أفقي أو عمودي بين صفحات منفصلة بملء الشاشة على أجهزة Wear OS. وتشمل حالات الاستخدام الشائعة التمرير سريعًا بين مقاييس التمرين وعناصر التحكّم في الوسائط في تطبيق رياضي، أو التنقّل بين التدفقات المتعددة الصفحات.
في Compose for Wear OS Material 3، ينسّق HorizontalPagerScaffold وVerticalPagerScaffold تخطيط أداة عرض الصفحات، ويحدّدان تلقائيًا موضع مؤشر الصفحة ويديران عمليات الانتقال باستخدام TimeText.
يتم تضمين كل صفحة في عنصر AnimatedPage قابل للإنشاء، ويتم تطبيق تأثيرات تغيير الحجم وتغيير شكل الزوايا المستديرة وتأثيرات التعتيم أثناء انتقال الصفحات على الشاشة الدائرية.
تعرض الصورة المتحركة التالية كيفية HorizontalPagerScaffoldAnimatedPage
تغيير حجم الصفحات وتحريكها أثناء التمرير السريع أفقيًا:
التسلسل الهرمي للرمز الأولي الخاص بالتقسيم إلى صفحات
عند تصميم تنسيقات شاشة مقسّمة إلى صفحات في Material 3، سواء كان ذلك من خلال التمرير السريع لليسار أو لليمين (HorizontalPager) أو للأعلى أو للأسفل (VerticalPager)، استخدِم التسلسل الهرمي التالي للمكوّنات من الحاوية الخارجية إلى المحتوى الداخلي:
AppScaffold: الحاوية الخارجية في جذر تطبيقك (استخدِم حاوية واحدة فقط لكل تطبيق). يتم تثبيت تراكبTimeTextالشامل حتى تظل الساعة ثابتة في أعلى الشاشة أثناء عمليات انتقال الصفحات وإيماءات التمرير السريع للإغلاق.HorizontalPagerScaffoldأوVerticalPagerScaffold: يتم وضعها داخلAppScaffoldعلى مستوى أداة تقسيم المحتوى إلى صفحات. وينسّق عمليات الانتقال بينTimeTextوHorizontalPageIndicatorأوVerticalPageIndicator.-
HorizontalPagerأوVerticalPager: حاوية أداة عرض الصفحات الأساسية التي تدير إيماءات التمرير السريع، وقوانين الفيزياء الخاصة بالحركة السريعة، وميزة المحاذاة عند استخدام أداة التحكم الدوّارة من خلالPagerStateمشترَك. -
AnimatedPage: يتم وضعها داخل دالة lambda الخاصة بمحتوى صفحة أداة التقسيم إلى صفحات. وهي تغلف كل صفحة على حدة لتطبيق رسوم متحركة للانتقال في Material 3 (تأثيرات التوسيع والتعتيم) استنادًا إلى موضع الصفحة فيPagerState. ScreenScaffold: يتم وضعها داخلAnimatedPageلكل صفحة فردية. بما أنّ كل صفحة يمكن أن تحتوي على قائمة قابلة للتمرير عموديًا (مثلTransformingLazyColumn) أوEdgeButton، يضمن تضمينScreenScaffoldداخل كل صفحة أنّ مؤشرات التمرير العمودي والأزرار على الحواف وcontentPaddingتنتمي إلى تلك الصفحة المحدّدة وتتحرّك بسلاسة معها.
AppScaffold (1 per app: anchors global TimeText)
└── HorizontalPagerScaffold / VerticalPagerScaffold (manages PageIndicator)
└── HorizontalPager / VerticalPager (manages PagerState & fling behavior)
└── AnimatedPage (applies scaling & scrim transitions per page)
└── ScreenScaffold (1 per page: ScrollIndicator & EdgeButton)
└── Page Content (Column or TransformingLazyColumn)
تنفيذ أداة عرض الصفحات الأفقية
لتنفيذ أداة عرض صفحات أفقية في Material 3، يجب تضمين HorizontalPagerScaffold وHorizontalPager وAnimatedPage وScreenScaffold داخل AppScaffold في تطبيقك.
استخدِم PagerScaffoldDefaults.snapWithSpringFlingBehavior من أجل
flingBehavior لتطبيق فيزياء حركة النوابض في Material 3 وتفعيل ميزة المحاذاة التلقائية للصفحات المتجاوبة (HighSnapPositionalThreshold). بشكلٍ تلقائي، يؤدي HorizontalPager إلى إيقاف
التمرير الدائري للصفحات (rotaryScrollableBehavior = null)، ما يتيح استخدام
التاج الدوّار أو الإطار الدوّار للتمرير في القوائم العمودية (مثل
TransformingLazyColumn) داخل الصفحة النشطة.
يوضّح المثال التالي عملية إعداد HorizontalPagerScaffold كاملة:
@Composable fun HorizontalPagerScaffoldSample(navigateBack: () -> Unit) { AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPagerScaffold(pagerState = pagerState) { HorizontalPager( state = pagerState, flingBehavior = PagerScaffoldDefaults.snapWithSpringFlingBehavior( state = pagerState ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { Text(text = "Page #$page") Spacer(modifier = Modifier.height(8.dp)) Text(text = "Swipe left and right") if (page == 0) { Spacer(modifier = Modifier.height(16.dp)) Button(onClick = navigateBack) { Text("Exit") } } } } } } } } }
إذا كانت صفحة داخل أداة التمرير الأفقي تحتوي على TransformingLazyColumn، أنشئ rememberTransformingLazyColumnState() منفصلاً داخل نطاق تلك الصفحة، ومرِّره إلى ScreenScaffold وTransformingLazyColumn الداخليين:
AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPagerScaffold(pagerState = pagerState) { HorizontalPager( state = pagerState, flingBehavior = PagerScaffoldDefaults.snapWithSpringFlingBehavior( state = pagerState ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { val columnState = rememberTransformingLazyColumnState() val transformationSpec = rememberTransformationSpec() ScreenScaffold( scrollState = columnState, ) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding, ) { item { ListHeader( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding( ListHeaderDefaults.minimumTopListContentPadding ), transformation = SurfaceTransformation(transformationSpec), ) { Text(text = "Pager sample") } } item { Card( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding( CardDefaults.minimumVerticalListContentPadding ), transformation = SurfaceTransformation(transformationSpec), ) { if (page == 0) { Text(text = "Page #$page. Swipe right") } else { Text(text = "Page #$page. Swipe left and right") } } } } } } } } }
تنفيذ أداة عرض الصفحات الرأسية
يتيح جهاز عرض الصفحات العمودي للمستخدمين التمرير سريعًا للأعلى وللأسفل بين الصفحات أو التنقّل بينها باستخدام الزر الجانبي الدوّار أو الإطار الدوّار في الساعة.
على عكس HorizontalPager، تتيح VerticalPager إمكانية محاذاة الصفحات الدوّارة تلقائيًا (RotaryScrollableDefaults.snapBehavior(state)). مرِّر PagerScaffoldDefaults.snapWithSpringFlingBehavior إلى flingBehavior، ثم ضع كل صفحة بين AnimatedPage وScreenScaffold:
@Composable fun VerticalPagerScaffoldSample() { AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPagerScaffold(pagerState = pagerState) { VerticalPager( state = pagerState, flingBehavior = PagerScaffoldDefaults.snapWithSpringFlingBehavior( state = pagerState ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { Text(text = "Page #$page") Spacer(modifier = Modifier.height(8.dp)) Text(text = "Swipe up and down") } } } } } } }
تخصيص سلوك أداة تقسيم الصفحات
يمكنك تخصيص حساسية المحاذاة في HorizontalPagerScaffold وVerticalPagerScaffold لتناسب احتياجات التفاعل في تطبيقك.
ضبط حساسية الالتقاط للتمارين
أثناء التمارين أو الأنشطة التي تتطلّب حركة كبيرة وتكون فيها قدرة المستخدم على التحكّم في الحركات الكبيرة محدودة، يمكن أن تؤدي اللمسات العرضية أو الدوران الطفيف لزر الساعة إلى التبديل بين الصفحات بدون قصد. بالنسبة إلى هذه الشاشات، اضبط جهاز النداء على حساسية منخفضة للالتقاط:
- مرِّر
PagerDefaults.snapFlingBehaviorمعmaxFlingPages = 0وsnapPositionalThreshold = PagerScaffoldDefaults.LowSnapPositionalThreshold، لذا يجب السحب عمدًا على جزء أكبر من الشاشة للانتقال إلى الصفحة التالية. - في حال تفعيل ميزة "محاذاة الصفحة الدوّارة"، اضبط قيمة
snapSensitivity = RotaryScrollableDefaults.LowSnapSensitivityفيRotaryScrollableDefaults.snapBehaviorلطلب المزيد من التدوير قبل المحاذاة مع الصفحة التالية.
@Composable fun HorizontalPagerScaffoldWithLowSensitivitySample(navigateBack: () -> Unit) { AppScaffold { val pagerState = rememberPagerState(pageCount = { 3 }) HorizontalPagerScaffold(pagerState = pagerState) { HorizontalPager( state = pagerState, flingBehavior = PagerDefaults.snapFlingBehavior( state = pagerState, maxFlingPages = 0, snapPositionalThreshold = PagerScaffoldDefaults.LowSnapPositionalThreshold, ), rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior( pagerState = pagerState, snapSensitivity = RotaryScrollableDefaults.LowSnapSensitivity, ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold { // Page content } } } } } }
للاطّلاع على نماذج كاملة لعمليات التنفيذ، راجِع Pager.kt في مستودع android/snippets وPagerScaffoldSample.kt في مستودع AndroidX.