بکشید تا تازه شود

کامپوننت pull to refresh به کاربران اجازه می‌دهد تا در ابتدای محتوای برنامه به سمت پایین بکشند تا داده‌ها به‌روزرسانی شوند.

سطح API

از کامپوننت PullToRefreshBox برای پیاده‌سازی pull-to-refresh استفاده کنید، که به عنوان یک ظرف برای محتوای قابل پیمایش شما عمل می‌کند. پارامترهای کلیدی زیر رفتار و ظاهر refresh را کنترل می‌کنند:

  • isRefreshing : یک مقدار بولی که نشان می‌دهد آیا عمل به‌روزرسانی در حال انجام است یا خیر.
  • onRefresh : یک تابع لامبدا که زمانی که کاربر یک refresh را آغاز می‌کند، اجرا می‌شود.
  • indicator : نشانگری را که سیستم هنگام بازخوانی (pull-to-refresh) ترسیم می‌کند، سفارشی می‌کند.

مثال پایه

این قطعه کد، کاربرد اولیه‌ی 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) })
            }
        }
    }
}

نکات کلیدی در مورد کد

  • PullToRefreshBox یک LazyColumn را در بر می‌گیرد که لیستی از رشته‌ها را نمایش می‌دهد.
  • PullToRefreshBox به پارامترهای isRefreshing و onRefresh نیاز دارد.
  • محتوای درون بلوک PullToRefreshBox نشان‌دهنده محتوای قابل اسکرول است.

نتیجه

این ویدیو پیاده‌سازی اولیه‌ی pull-to-refresh را از کد قبلی نشان می‌دهد:

شکل ۱. پیاده‌سازی اولیه‌ی pull-to-refresh روی لیستی از آیتم‌ها.

مثال پیشرفته: سفارشی‌سازی رنگ نشانگر

@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) })
            }
        }
    }
}

نکات کلیدی در مورد کد

  • رنگ نشانگر از طریق ویژگی‌های containerColor و color در پارامتر indicator ، سفارشی‌سازی می‌شود.
  • rememberPullToRefreshState() وضعیت عمل به‌روزرسانی را مدیریت می‌کند. شما از این وضعیت همراه با پارامتر indicator استفاده می‌کنید.

نتیجه

این ویدیو پیاده‌سازی قابلیت pull-to-refresh را با یک نشانگر رنگی نشان می‌دهد:

شکل ۲. پیاده‌سازی pull-to-refresh با یک سبک سفارشی.

مثال پیشرفته: ایجاد یک اندیکاتور کاملاً سفارشی

شما می‌توانید با استفاده از composableها و انیمیشن‌های موجود، شاخص‌های سفارشی پیچیده ایجاد کنید. این قطعه کد نحوه ایجاد یک شاخص کاملاً سفارشی را در پیاده‌سازی pull-to-refresh نشان می‌دهد:

@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.pullToRefresh(
            state = state,
            isRefreshing = isRefreshing,
            threshold = PositionalThreshold,
            onRefresh = {

            }
        ),
        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
                        }
                )
            }
        }
    }
}

نکات کلیدی در مورد کد

  • قطعه کد قبلی از Indicator ارائه شده توسط کتابخانه استفاده می‌کرد. این قطعه کد یک اندیکاتور سفارشی قابل ترکیب با نام MyCustomIndicator ایجاد می‌کند. در این ترکیب، اصلاح‌کننده pullToRefreshIndicator موقعیت‌یابی و راه‌اندازی یک به‌روزرسانی را مدیریت می‌کند.
  • همانند قطعه کد قبلی، این مثال نمونه‌ی PullToRefreshState را استخراج می‌کند، بنابراین می‌توانید همان نمونه را هم به PullToRefreshBox و هم به pullToRefreshModifier ارسال کنید.
  • این مثال از رنگ کانتینر و آستانه موقعیت از کلاس PullToRefreshDefaults استفاده می‌کند. به این ترتیب، می‌توانید از رفتار و سبک‌بندی پیش‌فرض از کتابخانه Material دوباره استفاده کنید، در حالی که فقط عناصر مورد نظر خود را سفارشی می‌کنید.
  • MyCustomIndicator از Crossfade برای جابجایی بین یک آیکون ابر و یک CircularProgressIndicator استفاده می‌کند. آیکون ابر با کشیدن کاربر بزرگ می‌شود و با شروع عمل به‌روزرسانی به یک CircularProgressIndicator منتقل می‌شود.
    • targetState از isRefreshing برای تعیین اینکه کدام حالت نمایش داده شود (آیکون ابر یا نشانگر پیشرفت دایره‌ای) استفاده می‌کند.
    • animationSpec یک انیمیشن tween برای گذار تعریف می‌کند که مدت زمان مشخصی برابر با CROSSFADE_DURATION_MILLIS دارد.
    • state.distanceFraction نشان می‌دهد که کاربر تا چه حد به پایین کشیده شده است، که از 0f (بدون کشیدن) تا 1f (کاملاً کشیده شده) متغیر است.
    • اصلاح‌کننده‌ی graphicsLayer مقیاس و شفافیت را تغییر می‌دهد.

نتیجه

این ویدیو نشانگر سفارشی از کد قبلی را نشان می‌دهد:

شکل ۳. پیاده‌سازی pull-to-refresh با یک نشانگر سفارشی.

منابع اضافی