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

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

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

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

في 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

مصادر إضافية