אינדיקטורים של התקדמות

אינדיקטורים של התקדמות מציגים באופן חזותי את הסטטוס של פעולה. הם משתמשים בתנועה כדי להעביר למשתמש מידע על מידת ההתקדמות של התהליך, למשל טעינת נתונים או עיבוד נתונים. הן יכולות גם לסמן שהעיבוד מתבצע, בלי לציין עד כמה הוא קרוב לסיום.

ריכזנו כאן שלושה תרחישים לדוגמה שבהם אפשר להשתמש באינדיקטור של התקדמות:

  • טעינת תוכן: בזמן אחזור תוכן מרשת, למשל טעינת תמונה או נתונים של פרופיל משתמש.
  • העלאת קובץ: נותנים למשתמש משוב על משך ההעלאה המשוער.
  • עיבוד ארוך: כשאפליקציה מעבדת כמות גדולה של נתונים, חשוב להציג למשתמש את ההתקדמות ביחס לזמן הנדרש.

בעיצוב חדשני תלת-ממדי יש שני סוגים של אינדיקטורים של התקדמות:

  • קביעה: מדד ההתקדמות המדויק של ההתקדמות.
  • לא ידועה: האנימציה פועלת באופן קבוע ללא קשר להתקדמות.

באופן דומה, אינדיקטור ההתקדמות יכול להופיע באחת משתי הצורות הבאות:

  • לינארי: עמודה אופקית שמתמלאת משמאל לימין.
  • מעגלית: מעגל שהקו שלו מתארך עד שהוא מקיף את ההיקף המלא של המעגל.
אינדיקטור התקדמות ליניארי לצד מחוון התקדמות מעגלי.
איור 1. שני הסוגים של מדדי התקדמות.

ממשק API

יש כמה רכיבים שאפשר להשתמש בהם כדי ליצור אינדיקטורים של התקדמות בהתאם ל-Material Design, אבל הפרמטרים שלהם לא שונים בהרבה. בין הפרמטרים העיקריים שכדאי לזכור:

  • progress: ההתקדמות הנוכחית שמוצגת במדד. מעבירים Float בין 0.0 ל-1.0.
  • color: הצבע של האינדיקטור בפועל. כלומר, החלק ברכיב שמשקף את ההתקדמות ומקיף אותו במלואו כשההתקדמות הושלמה.
  • trackColor: הצבע של המסלול שבו מצויר האינדיקטור.

אינדיקטורים מוגדרים

אינדיקטור מדויק משקף בדיוק את מידת השלמות של פעולה. משתמשים ברכיבי ה-Composable‏ 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)
    }
}

כשהטעינה הושלמה חלקית, האינדיקטור הליניארי בדוגמה הקודמת מופיע כך:

כמו כן, האינדיקטור העגול מופיע כך:

אינדיקטורים לא ידועים

אינדיקטור לא ידוע לא משקף את מידת ההתקדמות של פעולה כלשהי. במקום זאת, הוא משתמש בתנועה כדי להצביע למשתמש שהעיבוד נמשך, בלי לציין את מידת ההתקדמות.

כדי ליצור אינדיקטור של התקדמות לא ידועה, משתמשים ב-composable‏ 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.

מקורות מידע נוספים