شاخص های پیشرفت

نشانگرهای پیشرفت، وضعیت یک عملیات را به صورت بصری نشان می‌دهند. آن‌ها از حرکت برای جلب توجه کاربر به میزان نزدیک بودن به اتمام فرآیند، مانند بارگیری یا پردازش داده‌ها، استفاده می‌کنند. آن‌ها همچنین می‌توانند بدون اشاره به میزان نزدیک بودن به اتمام، نشان دهند که پردازش در حال انجام است.

این سه مورد استفاده را در نظر بگیرید که در آنها می‌توانید از نشانگر پیشرفت استفاده کنید:

  • بارگیری محتوا : هنگام دریافت محتوا از شبکه، مانند بارگیری تصویر یا داده برای نمایه کاربر.
  • آپلود فایل : به کاربر بازخورد دهید که آپلود چقدر ممکن است طول بکشد.
  • پردازش طولانی : در حالی که یک برنامه در حال پردازش حجم زیادی از داده‌ها است، به کاربر اطلاع دهید که چه مقدار از کل داده‌ها تکمیل شده است.

در طراحی متریال، دو نوع نشانگر پیشرفت وجود دارد:

  • تعیین‌شده : دقیقاً میزان پیشرفت را نشان می‌دهد.
  • نامشخص : بدون توجه به پیشرفت، به طور مداوم متحرک است.

به همین ترتیب، یک شاخص پیشرفت می‌تواند یکی از دو شکل زیر را داشته باشد:

  • خطی : یک نوار افقی که از چپ به راست پر می‌شود.
  • دایره‌ای : دایره‌ای که طول خط آن افزایش می‌یابد تا زمانی که تمام محیط دایره را در بر بگیرد.
یک نشانگر پیشرفت خطی در کنار یک نشانگر پیشرفت دایره‌ای.
شکل ۱. دو نوع شاخص پیشرفت.

سطح API

اگرچه چندین ترکیب‌پذیر وجود دارد که می‌توانید برای ایجاد شاخص‌های پیشرفت سازگار با طراحی متریال از آنها استفاده کنید، پارامترهای آنها تفاوت چندانی با هم ندارند. از جمله پارامترهای کلیدی که باید در نظر داشته باشید موارد زیر است:

  • progress : پیشرفت فعلی که نشانگر نمایش می‌دهد. یک Float بین 0.0 و 1.0 وارد کنید.
  • color : رنگ شاخص واقعی. یعنی بخشی از مؤلفه که پیشرفت را منعکس می‌کند و وقتی پیشرفت کامل شد، مؤلفه را به طور کامل در بر می‌گیرد.
  • trackColor : رنگ مسیری که اندیکاتور روی آن رسم شده است.

شاخص‌ها را تعیین کنید

یک نشانگر قطعی دقیقاً میزان تکمیل یک عمل را نشان می‌دهد. از ترکیب‌های LinearProgressIndicator یا CircularProgressIndicator استفاده کنید و مقداری را برای پارامتر progress ارسال کنید.

قطعه کد زیر یک مثال نسبتاً مفصل ارائه می‌دهد. وقتی کاربر دکمه را فشار می‌دهد، برنامه هم نشانگر پیشرفت را نمایش می‌دهد و هم یک کوروتین را اجرا می‌کند که به تدریج مقدار progress را افزایش می‌دهد. این باعث می‌شود که نشانگر پیشرفت به نوبت تکرار شود.

@Composable
fun LinearDeterminateIndicator() {
    var currentProgress by remember { mutableFloatStateOf(0f) }
    var loading by remember { mutableStateOf(false) }
    val scope = rememberCoroutineScope() // Create a coroutine scope

    Column(
        verticalArrangement = Arrangement.spacedBy(12.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.fillMaxWidth()
    ) {
        Button(onClick = {
            loading = true
            scope.launch {
                loadProgress { progress ->
                    currentProgress = progress
                }
                loading = false // Reset loading when the coroutine finishes
            }
        }, enabled = !loading) {
            Text("Start loading")
        }

        if (loading) {
            LinearProgressIndicator(
                progress = { currentProgress },
                modifier = Modifier.fillMaxWidth(),
            )
        }
    }
}

/** Iterate the progress value */
suspend fun loadProgress(updateProgress: (Float) -> Unit) {
    for (i in 1..100) {
        updateProgress(i.toFloat() / 100)
        delay(100)
    }
}

وقتی بارگذاری تا حدی تکمیل شود، نشانگر خطی در مثال قبلی به شکل زیر ظاهر می‌شود:

به همین ترتیب، نشانگر دایره‌ای به شکل زیر ظاهر می‌شود:

شاخص‌های نامشخص

یک نشانگر نامشخص نشان نمی‌دهد که یک عملیات چقدر به اتمام نزدیک است. در عوض، از حرکت برای نشان دادن به کاربر استفاده می‌کند که پردازش در حال انجام است، البته بدون مشخص کردن هیچ درجه‌ای از اتمام.

برای ایجاد یک نشانگر پیشرفت نامشخص، از LinearProgressIndicator یا CircularProgressIndicator قابل ترکیب استفاده کنید، اما مقداری برای progress ارسال نکنید. مثال زیر نشان می‌دهد که چگونه می‌توانید یک نشانگر پیشرفت نامشخص را با فشار دادن یک دکمه تغییر وضعیت دهید.

@Composable
fun IndeterminateCircularIndicator() {
    var loading by remember { mutableStateOf(false) }

    Button(onClick = { loading = true }, enabled = !loading) {
        Text("Start loading")
    }

    if (!loading) return

    CircularProgressIndicator(
        modifier = Modifier.width(64.dp),
        color = MaterialTheme.colorScheme.secondary,
        trackColor = MaterialTheme.colorScheme.surfaceVariant,
    )
}

در زیر مثالی از این پیاده‌سازی در حالتی که اندیکاتور فعال است، آمده است:

در ادامه مثالی از همین پیاده‌سازی آمده است، اما به جای CircularProgressIndicator از LinearProgressIndicator استفاده شده است.

منابع اضافی