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

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

فكِّر في حالات الاستخدام الثلاث التالية التي قد تستخدم فيها مؤشر التقدّم:

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

في التصميم المتعدّد الأبعاد، هناك نوعان من مؤشرات التقدم:

  • تحديد: تعرِض هذه الحالة مقدار التقدّم الذي تمّ تحقيقه بدقة.
  • غير محدّد: يتم عرض الصور المتحركة باستمرار بغض النظر عن مستوى التقدّم.

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

  • خطي: شريط أفقي يملأ من اليسار إلى اليمين
  • دائري: دائرة يزداد طولها حتى تشمل محيط الدائرة بالكامل.
مؤشر تقدم خطي بجانب مؤشر تقدم دائري
الشكل 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.

مصادر إضافية