Przyciski ikon

Przyciski ikon wyświetlają działania, które użytkownicy mogą wykonać. Przyciski ikon muszą używać ikony o jasnym znaczeniu i zwykle reprezentują typowe lub często używane działania.

Istnieją 2 rodzaje przycisków ikon:

  • Domyślne: te przyciski mogą otwierać inne elementy, takie jak menu lub wyszukiwanie.
  • Przełącznik: te przyciski mogą reprezentować działania binarne, które można włączać lub wyłączać, takie jak „ulubione” lub „zakładka”.
5 przycisków z różnymi ikonami (ustawienia, więcej itp.). Niektóre są wypełnione, co oznacza, że są wybrane, a niektóre są tylko obrysowane.
Rysunek 1. Przyciski ikon, z których niektóre są wypełnione (co oznacza wybór) i obramowane.

Interfejs API

Aby zaimplementować standardowe przyciski ikon, użyj funkcji kompozycyjnej IconButton. Aby utworzyć różne style wizualne, takie jak wypełniony, wypełniony tonalny lub konturowy, użyj odpowiednio FilledIconButton, FilledTonalIconButton i OutlinedIconButton.

Najważniejsze parametry IconButton to:

  • onClick: funkcja lambda, która jest wykonywana, gdy użytkownik kliknie przycisk ikony.
  • enabled: wartość logiczna, która określa stan włączenia przycisku. Gdy false, przycisk nie reaguje na dane wejściowe użytkownika.
  • content: funkcja kompozycyjna wewnątrz przycisku, zwykle Icon.

Podstawowy przykład: przycisk ikony przełącznika

Ten przykład pokazuje, jak zaimplementować przycisk przełącznika z ikoną. Przycisk ikony przełącznika zmienia wygląd w zależności od tego, czy jest zaznaczony, czy nie.

@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."
        )
    }
}

Najważniejsze informacje o kodzie

  • Element kompozycyjny ToggleIconButtonExample definiuje przełączany element IconButton.
    • mutableStateOf(false) tworzy obiekt MutableState, który zawiera wartość logiczną, początkowo false. Dzięki temu isToggled jest zmienną stanu, co oznacza, że Compose ponownie komponuje interfejs, gdy zmienia się jej wartość.
    • rememberSaveable zapewnia, że stan isToggled jest zachowywany podczas zmian konfiguracji, takich jak obrót ekranu.
  • Funkcja lambda onClick elementu IconButton określa zachowanie przycisku po kliknięciu, przełączając stan między true a false.
  • Parametr painter funkcji kompozycyjnej Icon warunkowo wczytuje inny element painterResource na podstawie stanu isToggled. Zmienia to wygląd ikony.
    • Jeśli isToggled to true, wczytuje wypełniony element graficzny serca.
    • Jeśli isToggled to false, wczytuje element rysowalny z konturem serca.
  • contentDescription elementu Icon również aktualizuje się na podstawie stanu isToggled, aby dostarczać odpowiednie informacje o ułatwieniach dostępu.

Wynik

Obraz poniżej przedstawia przycisk przełączania z poprzedniego fragmentu kodu w stanie niewybranym:

Przycisk przełączania ulubionych (serce) w stanie niewybranym (niewypełniony).
Rysunek 2. Przycisk przełączania „Ulubione” w stanie niewybranym.

Przykład zaawansowany: powtarzane działania po naciśnięciu

W tej sekcji pokazujemy, jak tworzyć przyciski ikon, które stale wywołują działanie, gdy użytkownik je naciśnie i przytrzyma, zamiast wywoływać je tylko raz po kliknięciu.

@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,
        )
    }
}

Najważniejsze informacje o kodzie

  • MomentaryIconButton przyjmuje unselectedImage: Int, czyli identyfikator obiektu rysowalnego ikony, gdy przycisk nie jest naciśnięty, oraz selectedImage: Int, czyli identyfikator obiektu rysowalnego ikony, gdy przycisk jest naciśnięty.
  • Używa interactionSource do śledzenia interakcji „naciśnięcia” przez użytkownika.
  • isPressed ma wartość true, gdy przycisk jest aktywnie naciskany, a w przeciwnym razie ma wartość false. Gdy isPressed ma wartość true, LaunchedEffect wchodzi w pętlę.
    • W tej pętli używa delay (z stepDelay), aby tworzyć przerwy między działaniami wyzwalającymi. coerceIn zapewnia, że opóźnienie wynosi co najmniej 1 ms, aby zapobiec nieskończonym pętlom.
    • Funkcja pressedListener jest wywoływana po każdym opóźnieniu w pętli. Spowoduje to powtórzenie działania.
  • pressedListener używa rememberUpdatedState, aby mieć pewność, że lambda onClick (działanie do wykonania) jest zawsze aktualna i pochodzi z najnowszej kompozycji.
  • Icon zmienia wyświetlany obraz w zależności od tego, czy przycisk jest aktualnie naciśnięty.
    • Jeśli isPressed ma wartość Prawda, wyświetla się selectedImage.
    • W przeciwnym razie wyświetli się unselectedImage.

Następnie użyj tego słowa MomentaryIconButton w przykładzie. Ten fragment kodu pokazuje 2 przyciski ikon sterujące licznikiem:

@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 }
        )
    }
}

Najważniejsze informacje o kodzie

  • Funkcja kompozycyjna MomentaryIconButtonExample wyświetla element Row zawierający 2 instancje MomentaryIconButton i funkcję kompozycyjną Text, aby utworzyć interfejs do zwiększania i zmniejszania licznika.
  • Utrzymuje zmienną stanu zmiennego pressedCount za pomocą remember i mutableIntStateOf, zainicjowaną na 0. Gdy wartość pressedCount się zmienia, wszystkie elementy kompozycyjne, które ją obserwują (np. element kompozycyjny Text), są ponownie komponowane, aby odzwierciedlić nową wartość.
  • Pierwszy element MomentaryIconButton zmniejsza wartość pressedCount po kliknięciu lub przytrzymaniu.
  • Kliknięcie lub przytrzymanie drugiej wartości MomentaryIconButton zwiększa wartość pressedCount.
  • Oba przyciski mają stepDelay o wartości 100 milisekund, co oznacza, że działanie onClick powtarza się co 100 ms, gdy przycisk jest przytrzymywany.

Wynik

Poniższy film przedstawia interfejs z przyciskami ikon i licznikiem:

Rysunek 3. Interfejs licznika z 2 przyciskami ikon (plus i minus), które zwiększają i zmniejszają wartość licznika.

Dodatkowe materiały