Phân trang cho phép người dùng vuốt theo chiều ngang hoặc chiều dọc giữa các trang riêng biệt, toàn màn hình trên thiết bị Wear OS. Các trường hợp sử dụng phổ biến bao gồm vuốt giữa các chỉ số tập luyện và chế độ điều khiển nội dung nghe nhìn trong một ứng dụng tập thể dục, hoặc chuyển qua các luồng nhiều trang.
Trong Compose cho Wear OS Material 3, HorizontalPagerScaffold và VerticalPagerScaffold sẽ điều phối bố cục trình phân trang, tự động định vị chỉ báo trang và quản lý các hiệu ứng chuyển đổi bằng TimeText.
Mỗi trang được bao bọc trong một thành phần kết hợp AnimatedPage, áp dụng hiệu ứng thu phóng, biến đổi góc bo tròn và hiệu ứng lớp phủ khi các trang chuyển đổi trên màn hình tròn.
Ảnh động sau đây cho thấy cách HorizontalPagerScaffold và AnimatedPage điều chỉnh tỷ lệ và tạo hiệu ứng cho các trang trong quá trình vuốt ngang:
Hệ phân cấp giàn giáo để phân trang
Khi thiết kế bố cục màn hình phân trang trong Material 3 – cho dù vuốt sang trái hay phải (HorizontalPager) hoặc lên hay xuống (VerticalPager) – hãy sử dụng hệ phân cấp thành phần sau đây từ vùng chứa bên ngoài đến nội dung bên trong:
AppScaffold: Vùng chứa ngoài cùng ở gốc của ứng dụng (chỉ sử dụng một vùng chứa cho mỗi ứng dụng). Thao tác này sẽ cố định lớp phủTimeTextchung để đồng hồ vẫn đứng yên ở đầu màn hình trong quá trình chuyển đổi trang và cử chỉ vuốt để đóng.HorizontalPagerScaffoldhoặcVerticalPagerScaffold: Đặt bên trongAppScaffoldở cấp trình phân trang. Thành phần này điều phối các hiệu ứng chuyển đổi giữaTimeTextvàHorizontalPageIndicatorhoặcVerticalPageIndicator.HorizontalPagerhoặcVerticalPager: Vùng chứa trình phân trang cơ sở quản lý cử chỉ vuốt, vật lý hất và thao tác nhập xoay bằng cách sử dụngPagerStatedùng chung.AnimatedPage: Được đặt bên trong hàm lambda nội dung trang của trình phân trang. Thành phần này bao bọc từng trang riêng lẻ để áp dụng các hiệu ứng chuyển đổi Material 3 (hiệu ứng thu phóng và lớp phủ) dựa trên độ lệch của trang trongPagerState.ScreenScaffold: Được đặt bên trongAnimatedPagecho từng trang riêng lẻ. Vì mỗi trang có thể chứa danh sách riêng có thể cuộn theo chiều dọc (chẳng hạn nhưTransformingLazyColumn) hoặcEdgeButtonriêng, việc lồngScreenScaffoldbên trong mỗi trang đảm bảo rằng các chỉ báo cuộn theo chiều dọc, nút cạnh vàcontentPaddingthuộc về trang cụ thể đó và chuyển động mượt mà cùng với trang.
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)
Triển khai chế độ phân trang ngang
Để triển khai một trình phân trang ngang trong Material 3, hãy lồng HorizontalPagerScaffold, HorizontalPager, AnimatedPage và ScreenScaffold bên trong AppScaffold của ứng dụng.
Sử dụng PagerScaffoldDefaults.snapWithSpringFlingBehavior cho flingBehavior để áp dụng vật lý chuyển động lò xo Material 3 và tính năng chụp nhanh trang thích ứng (HighSnapPositionalThreshold). Theo mặc định, HorizontalPager sẽ tắt tính năng cuộn trang bằng thao tác xoay (rotaryScrollableBehavior = null), cho phép thao tác xoay núm vặn hoặc viền để cuộn danh sách dọc (chẳng hạn như TransformingLazyColumn) bên trong trang đang hoạt động.
Mẫu sau đây minh hoạ chế độ thiết lập HorizontalPagerScaffold hoàn chỉnh:
@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") } } } } } } } } }
Nếu một trang bên trong trình phân trang ngang của bạn chứa TransformingLazyColumn, hãy tạo một rememberTransformingLazyColumnState() riêng biệt trong phạm vi của trang đó và truyền nó đến ScreenScaffold và TransformingLazyColumn bên trong:
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") } } } } } } } } }
Triển khai chế độ phân trang dọc
Trình phân trang dọc cho phép người dùng vuốt lên và xuống giữa các trang hoặc chuyển qua các trang bằng cách sử dụng nút bên xoay hoặc viền xoay của đồng hồ.
Không giống như HorizontalPager, VerticalPager cho phép chế độ chụp nhanh trang xoay theo mặc định (RotaryScrollableDefaults.snapBehavior(state)). Truyền PagerScaffoldDefaults.snapWithSpringFlingBehavior đến flingBehavior và bao bọc từng trang trong AnimatedPage và 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") } } } } } } }
Tuỳ chỉnh hành vi của trình phân trang
Bạn có thể tuỳ chỉnh độ nhạy của tính năng căn chỉnh nhanh HorizontalPagerScaffold và VerticalPagerScaffold cho phù hợp với nhu cầu tương tác của ứng dụng.
Điều chỉnh độ nhạy của tính năng chụp nhanh cho bài tập
Trong quá trình tập luyện hoặc các hoạt động có nhiều chuyển động mà khả năng kiểm soát vận động thô của người dùng bị hạn chế, các thao tác chạm vô tình hoặc xoay núm vặn nhẹ có thể vô tình chuyển đổi trang. Đối với những màn hình này, hãy định cấu hình bộ phân trang với độ nhạy thấp khi di chuyển nhanh:
- Truyền
PagerDefaults.snapFlingBehaviorbằngmaxFlingPages = 0vàsnapPositionalThreshold = PagerScaffoldDefaults.LowSnapPositionalThreshold, do đó, bạn phải kéo một cách có chủ ý trên một phần lớn hơn của màn hình để chuyển trang. - Nếu bạn bật tính năng chụp nhanh trang xoay, hãy đặt
snapSensitivity = RotaryScrollableDefaults.LowSnapSensitivitytrongRotaryScrollableDefaults.snapBehaviorđể yêu cầu xoay nhiều hơn trước khi chụp nhanh sang trang tiếp theo.
@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 } } } } } }
Để xem các cách triển khai mẫu đầy đủ, hãy xem Pager.kt trong kho lưu trữ android/snippets và PagerScaffoldSample.kt trong kho lưu trữ AndroidX.