Để lật nội dung theo cách trái và phải hoặc lên và xuống, bạn có thể sử dụng
thời gian
HorizontalPager
và
VerticalPager
thành phần kết hợp tương ứng. Các thành phần kết hợp này có chức năng tương tự như ViewPager
trong hệ thống thành phần hiển thị. Theo mặc định, HorizontalPager
chiếm toàn bộ chiều rộng của màn hình, VerticalPager
chiếm toàn bộ chiều cao và trình phân trang chỉ hất một trang tại một thời điểm. Bạn có thể định cấu hình tất cả các giá trị mặc định này.
HorizontalPager
Để tạo chế độ phân trang cuộn sang trái và phải theo chiều ngang, hãy sử dụng
HorizontalPager
:
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
VerticalPager
Để tạo một chế độ phân trang cuộn lên và xuống, hãy sử dụng VerticalPager
:
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
Tạo từng phần
Các trang trong cả HorizontalPager
và VerticalPager
đều được thành phần hiển thị một cách lười biếng và bố trí khi cần. Với tư cách là người dùng
cuộn qua các trang, thành phần kết hợp sẽ xoá mọi trang không còn
là bắt buộc.
Tải thêm trang ngoài màn hình
Theo mặc định, trình phân trang chỉ tải các trang hiển thị trên màn hình. Để tải thêm trang ngoài màn hình, hãy đặt beyondBoundsPageCount
thành một giá trị lớn hơn 0.
Di chuyển đến một mục trong chế độ phân trang
Để cuộn đến một trang nhất định trong trình phân trang, hãy tạo một
PagerState
đối tượng đang sử dụng
rememberPagerState()
và truyền dưới dạng tham số state
tới trình phân trang. Bạn có thể gọi PagerState#scrollToPage()
ở trạng thái này, bên trong CoroutineScope
:
val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier .fillMaxWidth() .height(100.dp) ) } // scroll to page val coroutineScope = rememberCoroutineScope() Button(onClick = { coroutineScope.launch { // Call scroll to on pagerState pagerState.scrollToPage(5) } }, modifier = Modifier.align(Alignment.BottomCenter)) { Text("Jump to Page 5") }
Nếu bạn muốn tạo ảnh động cho trang, hãy sử dụng
PagerState#animateScrollToPage()
hàm:
val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier .fillMaxWidth() .height(100.dp) ) } // scroll to page val coroutineScope = rememberCoroutineScope() Button(onClick = { coroutineScope.launch { // Call scroll to on pagerState pagerState.animateScrollToPage(5) } }, modifier = Modifier.align(Alignment.BottomCenter)) { Text("Jump to Page 5") }
Nhận thông báo về các thay đổi trạng thái trang
PagerState
có 3 thuộc tính kèm theo thông tin về trang:
currentPage
,
settledPage
,
và
targetPage
.
currentPage
: Trang gần vị trí chụp nhanh nhất. Theo mặc định, ảnh chụp nhanh vị trí là ở đầu bố cục.settledPage
: Số trang khi không có ảnh động hoặc tính năng cuộn nào đang chạy. Chiến dịch này khác với thuộc tínhcurrentPage
ở chỗcurrentPage
cập nhật ngay lập tức nếu trang đủ gần với vị trí chụp, nhưngsettledPage
vẫn giữ nguyên cho đến khi tất cả ảnh động chạy xong.targetPage
: Vị trí dừng đề xuất cho chuyển động cuộn.
Bạn có thể sử dụng hàm snapshotFlow
để quan sát các thay đổi đối với các biến này và phản hồi các thay đổi đó. Ví dụ: để gửi một sự kiện Analytics trên mỗi thay đổi trang,
bạn có thể làm như sau:
val pagerState = rememberPagerState(pageCount = { 10 }) LaunchedEffect(pagerState) { // Collect from the a snapshotFlow reading the currentPage snapshotFlow { pagerState.currentPage }.collect { page -> // Do something with each page change, for example: // viewModel.sendPageSelectedEvent(page) Log.d("Page change", "Page changed to $page") } } VerticalPager( state = pagerState, ) { page -> Text(text = "Page: $page") }
Thêm chỉ báo trang
Để thêm chỉ báo vào một trang, hãy sử dụng đối tượng PagerState
để lấy thông tin
về trang nào được chọn trong số các trang và vẽ biểu đồ tuỳ chỉnh
chỉ báo.
Ví dụ: nếu muốn có chỉ báo vòng tròn đơn giản, bạn có thể lặp lại số lần
vòng tròn và thay đổi màu vòng tròn dựa trên việc trang có được chọn hay không, sử dụng
pagerState.currentPage
:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, modifier = Modifier.fillMaxSize() ) { page -> // Our page content Text( text = "Page: $page", ) } Row( Modifier .wrapContentHeight() .fillMaxWidth() .align(Alignment.BottomCenter) .padding(bottom = 8.dp), horizontalArrangement = Arrangement.Center ) { repeat(pagerState.pageCount) { iteration -> val color = if (pagerState.currentPage == iteration) Color.DarkGray else Color.LightGray Box( modifier = Modifier .padding(2.dp) .clip(CircleShape) .background(color) .size(16.dp) ) } }
Áp dụng hiệu ứng cuộn mục cho nội dung
Một trường hợp sử dụng phổ biến là sử dụng vị trí cuộn để áp dụng hiệu ứng cho các mục của trình phân trang. Để tìm hiểu khoảng cách từ một trang đến trang hiện được chọn, bạn có thể
sử dụng
PagerState.currentPageOffsetFraction
.
Sau đó, bạn có thể áp dụng các hiệu ứng biến đổi cho nội dung dựa trên khoảng cách
khỏi trang đã chọn.
Ví dụ: để điều chỉnh độ mờ của các mục dựa trên khoảng cách của các mục đó với tâm, hãy thay đổi alpha
bằng cách sử dụng Modifier.graphicsLayer
trên một mục bên trong trình phân trang:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager(state = pagerState) { page -> Card( Modifier .size(200.dp) .graphicsLayer { // Calculate the absolute offset for the current page from the // scroll position. We use the absolute value which allows us to mirror // any effects for both directions val pageOffset = ( (pagerState.currentPage - page) + pagerState .currentPageOffsetFraction ).absoluteValue // We animate the alpha, between 50% and 100% alpha = lerp( start = 0.5f, stop = 1f, fraction = 1f - pageOffset.coerceIn(0f, 1f) ) } ) { // Card content } }
Kích thước trang tuỳ chỉnh
Theo mặc định, HorizontalPager
và VerticalPager
chiếm toàn bộ chiều rộng hoặc
chiều cao đầy đủ tương ứng. Bạn có thể đặt biến pageSize
để có
Fixed
,
Fill
(mặc định) hoặc phép tính kích thước tuỳ chỉnh.
Ví dụ: để đặt một trang có chiều rộng cố định là 100.dp
:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, pageSize = PageSize.Fixed(100.dp) ) { page -> // page content }
Để định kích thước trang dựa trên kích thước khung nhìn, hãy sử dụng kích thước trang tuỳ chỉnh
phép tính. Tạo một đối tượng PageSize
tuỳ chỉnh và chia availableSpace
cho 3, có tính đến khoảng cách giữa các mục:
private val threePagesPerViewport = object : PageSize { override fun Density.calculateMainAxisPageSize( availableSpace: Int, pageSpacing: Int ): Int { return (availableSpace - 2 * pageSpacing) / 3 } }
Khoảng đệm nội dung
HorizontalPager
và VerticalPager
đều hỗ trợ thay đổi khoảng đệm nội dung,
cho phép bạn tác động đến kích thước tối đa và căn chỉnh trang.
Ví dụ: việc đặt khoảng đệm start
sẽ căn chỉnh các trang theo hướng cuối:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(start = 64.dp), ) { page -> // page content }
Việc đặt cả khoảng đệm start
và end
thành cùng một giá trị sẽ căn giữa mục theo chiều ngang:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(horizontal = 32.dp), ) { page -> // page content }
Việc đặt khoảng đệm end
sẽ căn chỉnh các trang theo hướng bắt đầu:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(end = 64.dp), ) { page -> // page content }
Bạn có thể đặt giá trị top
và bottom
để đạt được hiệu ứng tương tự cho
VerticalPager
. Giá trị 32.dp
chỉ được dùng ở đây để minh hoạ; bạn có thể đặt từng kích thước khoảng đệm thành bất kỳ giá trị nào.
Tuỳ chỉnh hành vi cuộn
Các thành phần kết hợp HorizontalPager
và VerticalPager
mặc định sẽ chỉ định cách thức
cử chỉ cuộn hoạt động với trình phân trang. Tuy nhiên, bạn có thể tuỳ chỉnh và thay đổi
các giá trị mặc định như pagerSnapDistance
hoặc flingBehavior
.
Khoảng cách chụp
Theo mặc định, HorizontalPager
và VerticalPager
đặt số lượng tối đa
các trang mà cử chỉ hất có thể cuộn qua một trang mỗi lần. Để thay đổi
cái này, đặt
pagerSnapDistance
vào flingBehavior
:
val pagerState = rememberPagerState(pageCount = { 10 }) val fling = PagerDefaults.flingBehavior( state = pagerState, pagerSnapDistance = PagerSnapDistance.atMost(10) ) Column(modifier = Modifier.fillMaxSize()) { HorizontalPager( state = pagerState, pageSize = PageSize.Fixed(200.dp), beyondViewportPageCount = 10, flingBehavior = fling ) { PagerSampleItem(page = it) } }
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- ConstraintLayout trong Compose
- Đối tượng sửa đổi đồ hoạ
- Di chuyển
CoordinatorLayout
sang Compose