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

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

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

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

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

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

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

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

ממשק API

למרות שיש כמה תכנים קומפוזביליים שאפשר להשתמש בהם כדי ליצור מדדי התקדמות עקביים ב-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)
    }
}

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

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

אינדיקטורים בלתי תלויים

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

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

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