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

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

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

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

ב-Material Design יש שני סוגים של מדדי התקדמות:

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

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

  • לינארי: עמודה אופקית שמתמלאת משמאל לימין.
  • מעגלי: מעגל שהקו של הקו גדל עד שהוא כולל את את ההיקף המלא של המעגל.
אינדיקטור התקדמות ליניארי לצד מחוון התקדמות מעגלי.
איור 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)
    }
}

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

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

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

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

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

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