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

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

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

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

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

مراجع إضافية