לחצני סמלים

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

יש שני סוגים של כפתורי סמלים:

  • ברירת מחדל: הלחצנים האלה יכולים לפתוח רכיבים אחרים, כמו תפריט או חיפוש.
  • מתג: הלחצנים האלה יכולים לייצג פעולות בינאריות שאפשר להפעיל או להשבית, כמו "מועדף" או "סימנייה".
5 לחצני סמלים עם סמלים שונים (הגדרות, עוד וכו'). חלק מהם מלאים, מה שמציין שהם נבחרו, וחלק מהם מסומנים בקו מתאר.
תרשים 1. לחצני סמלים, שחלקם מלאים (מציינים בחירה) וחלקם עם קווי מתאר.

פלטפורמת ה-API

משתמשים בקוד IconButton קומפוזבילי כדי להטמיע כפתורי סמלים רגילים. כדי ליצור סגנונות חזותיים שונים כמו מלא, מלא בצבע אחד או עם קווי מתאר, משתמשים ב-FilledIconButton, ב-FilledTonalIconButton וב-OutlinedIconButton, בהתאמה.

הפרמטרים העיקריים של IconButton כוללים:

  • ‫onClick: פונקציית lambda שמופעלת כשהמשתמש לוחץ על כפתור הסמל.
  • ‫enabled: ערך בוליאני שקובע אם הכפתור מופעל או מושבת. כשהערך הוא false, הכפתור לא מגיב לקלט של המשתמש.
  • ‫content: התוכן הניתן לשילוב בתוך הכפתור, בדרך כלל Icon.

דוגמה בסיסית: כפתור סמל של מתג

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

@Preview
@Composable
fun ToggleIconButtonExample() {
    // isToggled initial value should be read from a view model or persistent storage.
    var isToggled by rememberSaveable { mutableStateOf(false) }

    IconButton(
        onClick = { isToggled = !isToggled }
    ) {
        Icon(
            painter = if (isToggled) painterResource(R.drawable.favorite_filled) else painterResource(R.drawable.favorite),
            contentDescription = if (isToggled) "Selected icon button" else "Unselected icon button."
        )
    }
}

מידע חשוב על הקוד

  • הפונקציה הקומפוזבילית ToggleIconButtonExample מגדירה IconButton שניתן להפעיל או להשבית.
    • ‫mutableStateOf(false) יוצרת אובייקט MutableState שמכיל ערך בוליאני, שהערך הראשוני שלו הוא false. כך isToggled הופך למאחסן מצב, כלומר מערכת פיתוח נייטיב יוצרת מחדש את ממשק המשתמש בכל פעם שהערך שלו משתנה.
    • הפונקציה rememberSaveable מבטיחה שהמצב של isToggled יישמר גם אם משנים את ההגדרות, למשל אם מסובבים את המסך.
  • הלמבדה onClick של IconButton מגדירה את התנהגות הכפתור כשלוחצים עליו, ומחליפה את המצב בין true ל-false.
  • הפרמטר painter של הרכיב הניתן לקישור Icon טוען באופן מותנה painterResource שונה על סמך המצב של isToggled. הפעולה הזו משנה את המראה החזותי של הסמל.
    • אם הערך של isToggled הוא true, נטען ה-drawable של הלב המלא.
    • אם הערך של isToggled הוא false, הוא טוען את ה-drawable של הלב עם קווי המתאר.
  • ה-contentDescription של ה-Icon מתעדכן גם על סמך המצב של isToggled כדי לספק מידע מתאים לגבי נגישות.

תוצאה

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

כפתור החלפה של מועדפים (לב) במצב לא מסומן (לא מלא).
איור 2. כפתור החלפה של סמל "מועדף" במצב לא מסומן.

דוגמה מתקדמת: פעולות חוזרות בלחיצה

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

@Composable
fun MomentaryIconButton(
    unselectedImage: Int,
    selectedImage: Int,
    contentDescription: String,
    modifier: Modifier = Modifier,
    stepDelay: Long = 100L, // Minimum value is 1L milliseconds.
    onClick: () -> Unit
) {
    val interactionSource = remember { MutableInteractionSource() }
    val isPressed by interactionSource.collectIsPressedAsState()
    val pressedListener by rememberUpdatedState(onClick)

    LaunchedEffect(isPressed) {
        while (isPressed) {
            delay(stepDelay.coerceIn(1L, Long.MAX_VALUE))
            pressedListener()
        }
    }

    IconButton(
        modifier = modifier,
        onClick = onClick,
        interactionSource = interactionSource
    ) {
        Icon(
            painter = if (isPressed) painterResource(id = selectedImage) else painterResource(id = unselectedImage),
            contentDescription = contentDescription,
        )
    }
}

מידע חשוב על הקוד

  • הפונקציה MomentaryIconButton מקבלת את unselectedImage: Int, מזהה הפריט הגרפי שניתן להזזה של הסמל כשהכפתור לא לחוץ, ואת selectedImage: Int, מזהה הפריט הגרפי שניתן להזזה של הסמל כשהכפתור לחוץ.
  • הוא משתמש ב-interactionSource כדי לעקוב באופן ספציפי אחרי אינטראקציות של "לחיצה" מצד המשתמש.
  • הערך של isPressed הוא True כשהכפתור נלחץ, ו-False בכל מצב אחר. כשהערך של isPressed הוא true, ה-LaunchedEffect נכנס ללולאה.
    • בתוך הלולאה הזו, הוא משתמש ב-delay (עם stepDelay) כדי ליצור השהיות בין הפעולות שמופעלות. ‫coerceIn מוודא שההשהיה היא לפחות אלפית השנייה כדי למנוע לולאות אינסופיות.
    • הפונקציה pressedListener מופעלת אחרי כל השהיה בתוך הלולאה. כך הפעולה תחזור על עצמה.
  • ה-pressedListener משתמש ב-rememberUpdatedState כדי לוודא ש-onClick lambda (הפעולה שצריך לבצע) תמיד מעודכנת מהקומפוזיציה האחרונה.
  • התמונה שמוצגת ב-Icon משתנה בהתאם למצב של הלחצן – אם הוא לחוץ או לא.
    • אם הערך של isPressed הוא True, מוצג selectedImage.
    • אחרת, מוצג unselectedImage.

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

@Preview()
@Composable
fun MomentaryIconButtonExample() {
    var pressedCount by remember { mutableIntStateOf(0) }

    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically
    ) {
        MomentaryIconButton(
            unselectedImage = R.drawable.fast_rewind,
            selectedImage = R.drawable.fast_rewind_filled,
            stepDelay = 100L,
            onClick = { pressedCount -= 1 },
            contentDescription = "Decrease count button"
        )
        Spacer(modifier = Modifier)
        Text("advanced by $pressedCount frames")
        Spacer(modifier = Modifier)
        MomentaryIconButton(
            unselectedImage = R.drawable.fast_forward,
            selectedImage = R.drawable.fast_forward_filled,
            contentDescription = "Increase count button",
            stepDelay = 100L,
            onClick = { pressedCount += 1 }
        )
    }
}

מידע חשוב על הקוד

  • הרכיב הניתן לקישור MomentaryIconButtonExample מציג Row שמכיל שני מופעים של MomentaryIconButton ורכיב ניתן לקישור Text כדי ליצור ממשק משתמש להגדלה ולהקטנה של מונה.
  • הוא שומר על משתנה מצב pressedCount שניתן לשינוי באמצעות remember ו-mutableIntStateOf, שמאותחל ל-0. כש-pressedCount משתנה, כל רכיב Composable שצופה בו (כמו הרכיב Text) עובר הרכבה מחדש כדי לשקף את הערך החדש.
  • הערך הראשון של MomentaryIconButton יורד ב-pressedCount כשלוחצים עליו או לוחצים לחיצה ארוכה.
  • השנייה MomentaryIconButton מגדילה את pressedCount בלחיצה או בלחיצה ארוכה.
  • בשני הכפתורים מוגדר stepDelay של 100 אלפיות השנייה, כלומר הפעולה onClick חוזרת על עצמה כל 100 אלפיות השנייה כל עוד הכפתור לחוץ.

תוצאה

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

איור 3. ממשק משתמש של מונה עם שני כפתורי סמלים (פלוס ומינוס) שמגדילים ומקטינים את המונה.

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