مؤشرات التقدم

تُظهر مؤشرات التقدم حالة العملية بشكل مرئي. وهو يستخدم الحركة للفت انتباه المستخدم إلى مدى قرب اكتمال العملية، مثل تحميل البيانات أو معالجتها. كما يمكنهم أن يشيروا أيضًا إلى أن المعالجة قيد التنفيذ، دون الإشارة إلى مدى قُرب اكتمالها.

ضع في اعتبارك حالات الاستخدام الثلاث هذه التي يمكنك فيها استخدام مؤشر التقدم:

  • تحميل المحتوى: أثناء جلب المحتوى من الشبكة، مثل تحميل صورة أو بيانات ملف شخصي للمستخدم
  • تحميل الملف: قدِّم للمستخدم ملاحظات عن المدة التي قد يستغرقها التحميل.
  • المعالجة الطويلة: أثناء معالجة تطبيق بكمية كبيرة من البيانات، اعرض للمستخدم مقدار البيانات الإجمالي.

في Material Design، هناك نوعان من مؤشرات التقدم:

  • التحديد: لعرض مدى التقدم الذي تم إحرازه بالضبط.
  • غير محدد: يتحرك باستمرار بغض النظر عن مستوى التقدم.

وبالمثل، يمكن أن يتخذ مؤشر التقدم أحد الشكلين التاليين:

  • خطي: شريط أفقي يملأ من اليسار إلى اليمين.
  • دائرية: دائرة ينمو طول خطها حتى تشمل المحيط الكامل للدائرة.
مؤشر تقدّم خطي إلى جانب مؤشر تقدّم دائري.
الشكل 1. نوعان من مؤشرات التقدّم.

سطح واجهة برمجة التطبيقات

على الرغم من وجود العديد من العناصر القابلة للإنشاء التي يمكنك استخدامها لإنشاء أزرار إجراءات عائمة متوافقة مع Material Design، فإن معلماتها لا تختلف اختلافًا كبيرًا. في ما يلي بعض المعلمات التي يجب وضعها في الاعتبار:

  • progress: مستوى التقدّم الحالي الذي يعرضه المؤشر. المرور Float بين 0.0 و1.0
  • color: لون المؤشر الفعلي أي جزء المكون الذي يعكس التقدم والذي يشمل بالكامل المكون عند اكتمال التقدم.
  • trackColor: لون المسار الذي تم رسم المؤشر عليه

تحديد المؤشرات

يعكس مؤشر التحديد مدى اكتمال الإجراء بالضبط. استخدِم العنصر LinearProgressIndicator أو CircularProgressIndicator القابل للإنشاء وأدخِل قيمة للمَعلمة progress.

يقدم المقتطف التالي مثالاً مفصلاً نسبيًا. عندما يضغط المستخدم على الزر، يعرض التطبيق مؤشر التقدم ويطلق الكوروتين الذي يزيد تدريجيًا من قيمة progress. يؤدي هذا إلى تكرار مؤشر التقدم بالترتيب.

@Composable
fun LinearDeterminateIndicator() {
    var currentProgress by remember { mutableStateOf(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,
    )
}

وفي ما يلي مثال على هذا التنفيذ عندما يكون المؤشر نشطًا:

فيما يلي مثال على عملية التنفيذ نفسها ولكن مع LinearProgressIndicator بدلاً من CircularProgressIndicator.

مصادر إضافية