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

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

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

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

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

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

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

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

مصادر إضافية