Kéo để làm mới

Thành phần kéo để làm mới cho phép người dùng kéo xuống ở đầu nội dung của ứng dụng để làm mới dữ liệu.

Nền tảng API

Sử dụng thành phần kết hợp PullToRefreshBox để triển khai tính năng kéo để làm mới. Tính năng này đóng vai trò là vùng chứa cho nội dung có thể cuộn. Các tham số chính sau đây kiểm soát hành vi làm mới và giao diện:

  • isRefreshing: Giá trị boolean cho biết liệu thao tác làm mới có đang diễn ra hay không.
  • onRefresh: Hàm lambda thực thi khi người dùng bắt đầu làm mới.
  • indicator: Tuỳ chỉnh chỉ báo được vẽ khi kéo để làm mới.

Ví dụ cơ bản

Đoạn mã này minh hoạ cách sử dụng cơ bản của PullToRefreshBox:

@Composable
fun PullToRefreshBasicSample(
    items: List<String>,
    isRefreshing: Boolean,
    onRefresh: () -> Unit,
    modifier: Modifier = Modifier
) {
    PullToRefreshBox(
        isRefreshing = isRefreshing,
        onRefresh = onRefresh,
        modifier = modifier
    ) {
        LazyColumn(Modifier.fillMaxSize()) {
            items(items) {
                ListItem({ Text(text = it) })
            }
        }
    }
}

Các điểm chính về mã

  • PullToRefreshBox gói LazyColumn, hiển thị danh sách các chuỗi.
  • PullToRefreshBox yêu cầu các tham số isRefreshingonRefresh.
  • Nội dung trong khối PullToRefreshBox đại diện cho nội dung có thể cuộn.

Kết quả

Video này minh hoạ cách triển khai cơ bản tính năng kéo để làm mới từ mã trước đó:

Hình 1. Cách triển khai cơ bản tính năng kéo để làm mới trên danh sách các mục.

Ví dụ nâng cao: Tuỳ chỉnh màu chỉ báo

@Composable
fun PullToRefreshCustomStyleSample(
    items: List<String>,
    isRefreshing: Boolean,
    onRefresh: () -> Unit,
    modifier: Modifier = Modifier
) {
    val state = rememberPullToRefreshState()

    PullToRefreshBox(
        isRefreshing = isRefreshing,
        onRefresh = onRefresh,
        modifier = modifier,
        state = state,
        indicator = {
            Indicator(
                modifier = Modifier.align(Alignment.TopCenter),
                isRefreshing = isRefreshing,
                containerColor = MaterialTheme.colorScheme.primaryContainer,
                color = MaterialTheme.colorScheme.onPrimaryContainer,
                state = state
            )
        },
    ) {
        LazyColumn(Modifier.fillMaxSize()) {
            items(items) {
                ListItem({ Text(text = it) })
            }
        }
    }
}

Các điểm chính về mã

  • Màu sắc của chỉ báo được tuỳ chỉnh thông qua các thuộc tính containerColorcolor trong tham số indicator.
  • rememberPullToRefreshState() quản lý trạng thái của thao tác làm mới. Bạn sử dụng trạng thái này cùng với tham số indicator.

Kết quả

Video này cho thấy cách triển khai tính năng kéo để làm mới bằng chỉ báo có màu:

Hình 2. Cách triển khai tính năng kéo để làm mới bằng kiểu tuỳ chỉnh.

Ví dụ nâng cao: Tạo chỉ báo được tuỳ chỉnh hoàn toàn

Bạn có thể tạo các chỉ báo tuỳ chỉnh phức tạp bằng cách tận dụng các thành phần kết hợp và ảnh động hiện có.Đoạn mã này minh hoạ cách tạo một chỉ báo tuỳ chỉnh hoàn toàn trong quá trình triển khai tính năng kéo để làm mới:

@Composable
fun PullToRefreshCustomIndicatorSample(
    items: List<String>,
    isRefreshing: Boolean,
    onRefresh: () -> Unit,
    modifier: Modifier = Modifier
) {
    val state = rememberPullToRefreshState()

    PullToRefreshBox(
        isRefreshing = isRefreshing,
        onRefresh = onRefresh,
        modifier = modifier,
        state = state,
        indicator = {
            MyCustomIndicator(
                state = state,
                isRefreshing = isRefreshing,
                modifier = Modifier.align(Alignment.TopCenter)
            )
        }
    ) {
        LazyColumn(Modifier.fillMaxSize()) {
            items(items) {
                ListItem({ Text(text = it) })
            }
        }
    }
}

// ...
@Composable
fun MyCustomIndicator(
    state: PullToRefreshState,
    isRefreshing: Boolean,
    modifier: Modifier = Modifier,
) {
    Box(
        modifier = modifier.pullToRefreshIndicator(
            state = state,
            isRefreshing = isRefreshing,
            containerColor = PullToRefreshDefaults.containerColor,
            threshold = PositionalThreshold
        ),
        contentAlignment = Alignment.Center
    ) {
        Crossfade(
            targetState = isRefreshing,
            animationSpec = tween(durationMillis = CROSSFADE_DURATION_MILLIS),
            modifier = Modifier.align(Alignment.Center)
        ) { refreshing ->
            if (refreshing) {
                CircularProgressIndicator(Modifier.size(SPINNER_SIZE))
            } else {
                val distanceFraction = { state.distanceFraction.coerceIn(0f, 1f) }
                Icon(
                    imageVector = Icons.Filled.CloudDownload,
                    contentDescription = "Refresh",
                    modifier = Modifier
                        .size(18.dp)
                        .graphicsLayer {
                            val progress = distanceFraction()
                            this.alpha = progress
                            this.scaleX = progress
                            this.scaleY = progress
                        }
                )
            }
        }
    }
}

Các điểm chính về mã

  • Đoạn mã trước đã sử dụng Indicator do thư viện cung cấp. Đoạn mã này tạo một thành phần kết hợp chỉ báo tuỳ chỉnh có tên là MyCustomIndicator. Trong thành phần kết hợp này, đối tượng sửa đổi pullToRefreshIndicator xử lý việc định vị và kích hoạt thao tác làm mới.
  • Như trong đoạn mã trước, thực thể PullToRefreshState đã được trích xuất, vì vậy, bạn có thể truyền cùng một thực thể cho cả PullToRefreshBoxpullToRefreshModifier.
  • Màu vùng chứa và ngưỡng vị trí được sử dụng từ lớp PullToRefreshDefaults. Bằng cách này, bạn có thể sử dụng lại hành vi và kiểu mặc định từ thư viện Material, đồng thời chỉ tuỳ chỉnh các phần tử mà bạn quan tâm.
  • MyCustomIndicator sử dụng Crossfade để chuyển đổi giữa biểu tượng đám mây và CircularProgressIndicator. Biểu tượng đám mây sẽ mở rộng khi người dùng kéo và chuyển đổi thành CircularProgressIndicator khi thao tác làm mới bắt đầu.
    • targetState sử dụng isRefreshing để xác định trạng thái cần hiển thị (biểu tượng đám mây hoặc chỉ báo tiến trình hình tròn).
    • animationSpec xác định ảnh động tween cho hiệu ứng chuyển đổi, với thời lượng được chỉ định là CROSSFADE_DURATION_MILLIS.
    • state.distanceFraction thể hiện khoảng cách người dùng đã kéo xuống, dao động từ 0f (không kéo) đến 1f (kéo hết).
    • Đối tượng sửa đổi graphicsLayer sửa đổi tỷ lệ và độ trong suốt.

Kết quả

Video này cho thấy chỉ báo tuỳ chỉnh trong mã trước đó:

Hình 3. Cách triển khai tính năng kéo để làm mới bằng chỉ báo tuỳ chỉnh.

Tài nguyên khác