Simge düğmeleri

Simge düğmeleri, kullanıcıların yapabileceği işlemleri gösterir. Simge düğmelerinde açıkça anlaşılır bir simge kullanılmalıdır ve genellikle yaygın veya sık kullanılan işlemleri temsil etmelidir.

İki tür simge düğmesi vardır:

  • Varsayılan: Bu düğmeler menü veya arama gibi diğer öğeleri açabilir.
  • Açma/kapatma: Bu düğmeler, "favori" veya "yer işareti" gibi etkinleştirilip devre dışı bırakılabilen ikili işlemleri temsil edebilir.
Farklı simgelerin (ayarlar, daha fazla vb.) yer aldığı 5 simge düğmesi. Bazıları, seçim olduğunu belirtmek için doldurulur, bazıları ise kenarlıklandırılır.
Şekil 1. Bazıları içi boyalı (seçimi belirtir) ve dış çizgili simge düğmeleri.

API yüzeyi

Standart simge düğmelerini uygulamak için IconButton bileşenini kullanın. Doldurulmuş, tonlu veya kenarlıklandırılmış gibi farklı görsel stiller oluşturmak için sırasıyla FilledIconButton, FilledTonalIconButton ve OutlinedIconButton simgesini kullanın.

IconButton için temel parametreler şunlardır:

  • onClick: Kullanıcı simge düğmesine dokunduğunda yürütülen bir lambda işlevi.
  • enabled: Düğmenin etkin durumunu kontrol eden bir boole değeridir. false olduğunda düğme kullanıcı girişine yanıt vermez.
  • content: Düğmenin içindeki, genellikle Icon olan derlenebilir içerik.

Temel örnek: Açma/kapatma simgesi düğmesi

Bu örnekte, açma/kapatma düğmesi simgesinin nasıl uygulanacağı gösterilmektedir. Açma/kapatma düğmesi simgesinin görünümü, düğmenin seçili olup olmadığına göre değişir.

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

Kodla ilgili önemli noktalar

  • ToggleIconButtonExample composable, açma/kapatma düğmeli bir IconButton tanımlar.
    • mutableStateOf(false), başlangıçta false olan bir boole değeri içeren bir MutableState nesnesi oluşturur. Bu, isToggled değerini bir durum tutucusu yapar. Diğer bir deyişle, Compose, değeri değiştiğinde kullanıcı arayüzünü yeniden oluşturur.
    • rememberSaveable, isToggled durumunun ekran döndürme gibi yapılandırma değişikliklerinde korunmasını sağlar.
  • IconButton öğesinin onClick lambdası, düğmenin tıklandığında davranışını tanımlar ve durumu true ile false arasında değiştirir.
  • Icon bileşeninin painter parametresi, isToggled durumuna göre koşullu olarak farklı bir painterResource yükler. Bu işlem, simgesinin görsel görünümünü değiştirir.
    • isToggled true ise dolu kalp çizilebilir öğesi yüklenir.
    • isToggled false ise kenarları çizili kalp çizilebilir öğesi yüklenir.
  • Icon'un contentDescription özelliği de uygun erişilebilirlik bilgilerini sağlamak için isToggled durumuna göre güncellenir.

Sonuç

Aşağıdaki resimde, önceki snippet'teki açma/kapatma simgesi düğmesi seçili olmayan durumunda gösterilmektedir:

Seçilmemiş durumdaki (içi boyanmamış) favori açma/kapatma simgesi düğmesi (kalp).
Şekil 2. "Favori" açma/kapatma düğmesi, seçili değil.

Gelişmiş örnek: Basın sırasında tekrarlanan işlemler

Bu bölümde, kullanıcı düğmeye basıp basılı tutarken bir işlemi yalnızca tıklama başına bir kez değil, sürekli olarak tetikleyen simge düğmelerinin nasıl oluşturulacağı gösterilmektedir.

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

Kodla ilgili önemli noktalar

  • MomentaryIconButton, düğmeye basılmadığında simgenin çizilebilir kaynak kimliği olan unselectedImage: Int ve düğmeye basıldığında simgenin çizilebilir kaynak kimliği olan selectedImage: Int parametrelerini alır.
  • Özellikle kullanıcıdan gelen "basma" etkileşimlerini izlemek için bir interactionSource kullanır.
  • isPressed, düğmeye etkin bir şekilde basıldığında doğru, aksi takdirde yanlış değerini alır. isPressed, true olduğunda LaunchedEffect bir döngüye girer.
    • Bu döngü içinde, tetikleyici işlemler arasında duraklamalar oluşturmak için delay (stepDelay ile) kullanılır. coerceIn, sonsuz döngüleri önlemek için gecikmenin en az 1 ms olmasını sağlar.
    • pressedListener, döngüdeki her gecikmeden sonra çağrılır. Bu işlem, işlemin tekrar etmesini sağlar.
  • pressedListener, onClick lambda'sının (uygulanacak işlem) her zaman en son derlemedeki en güncel sürüm olduğundan emin olmak için rememberUpdatedState'ı kullanır.
  • Icon, düğmeye basılı olup olmadığına bağlı olarak görüntülenen resmini değiştirir.
    • isPressed doğruysa selectedImage gösterilir.
    • Aksi takdirde unselectedImage gösterilir.

Ardından, bu MomentaryIconButton değerini bir örnekte kullanın. Aşağıdaki snippet'te, bir sayıcıyı kontrol eden iki simge düğmesi gösterilmektedir:

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

Kodla ilgili önemli noktalar

  • MomentaryIconButtonExample bileşeni, iki MomentaryIconButton örneği içeren bir Row ve bir sayıcıyı artırıp azaltmak için kullanıcı arayüzü oluşturmak üzere bir Text bileşeni gösterir.
  • remember ve mutableIntStateOf kullanarak 0 olarak başlatılmış bir pressedCount değişken durum değişkeni tutar. pressedCount değiştiğinde, bunu gözlemleyen tüm bileşenler (Text bileşeni gibi) yeni değeri yansıtacak şekilde yeniden oluşturulur.
  • İlk MomentaryIconButton tıklandığında veya basılı tutulduğunda pressedCount azalır.
  • İkinci MomentaryIconButton, tıklandığında veya basılı tutulduğunda pressedCount değerini artırır.
  • Her iki düğmede de 100 milisaniyelik bir stepDelay kullanılır. Yani düğme basılı tutulurken onClick işlemi 100 milisaniyede bir tekrarlanır.

Sonuç

Aşağıdaki videoda, simge düğmelerini ve sayacı içeren kullanıcı arayüzü gösterilmektedir:

Şekil 3. Sayacı artıran ve azaltan iki simge düğmesi (artı ve eksi) içeren bir sayaç kullanıcı arayüzü.

Ek kaynaklar