Dokunup basın

Çoğu composable, dokunma veya tıklama için yerleşik desteğe sahiptir ve onClick lambda içerir. Örneğin, yüzeylerle etkileşime uygun tüm Materyal Tasarım davranışlarını içeren tıklanabilir bir Surface oluşturabilirsiniz:

Surface(onClick = { /* handle click */ }) {
    Text("Click me!", Modifier.padding(24.dp))
}

Ancak kullanıcılar composable'larla etkileşim kurmanın tek yolu tıklamalar değildir. Bu sayfada, tek bir işaretçi içeren hareketlere odaklanılmaktadır. İşaretçinin konumu, söz konusu etkinliğin işlenmesi için önemli değildir. Aşağıdaki tabloda bu hareket türleri listelenmiştir:

Hareket

Description

Dokunun (veya tıklayın)

İşaretçi önce aşağı, sonra yukarı

İki kez dokunun

İşaretçi iner, yukarı, aşağı, yukarı

Uzun basma

İşaretçi iner ve daha uzun süre tutulur

Basın

İşaretçi iniyor

Dokunarak veya tıklayarak yanıt verin

clickable, dokunma veya tıklamalara composable tepki veren, yaygın olarak kullanılan bir değiştiricidir. Bu değiştirici ayrıca odaklama, fare ve ekran kalemini hareket ettirme desteği ve basıldığında özelleştirilebilir görsel gösterge gibi ek özellikler de ekler. Değiştirici, "tıklamalara" kelimenin en geniş anlamında yanıt verir. Yalnızca fare veya parmakla değil, aynı zamanda klavye girişiyle veya erişilebilirlik hizmetlerini kullanırken tıklama etkinliklerini de kullanır.

Bir resim ızgarasını düşünün. Kullanıcı bir resme tıkladığında tam ekran olarak görüntülenir:

Bu davranışı uygulamak için tablodaki her öğeye clickable değiştiricisini ekleyebilirsiniz:

@Composable
private fun ImageGrid(photos: List<Photo>) {
    var activePhotoId by rememberSaveable { mutableStateOf<Int?>(null) }
    LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 128.dp)) {
        items(photos, { it.id }) { photo ->
            ImageItem(
                photo,
                Modifier.clickable { activePhotoId = photo.id }
            )
        }
    }
    if (activePhotoId != null) {
        FullScreenImage(
            photo = photos.first { it.id == activePhotoId },
            onDismiss = { activePhotoId = null }
        )
    }
}

clickable değiştiricisi, ek davranışlar da ekler:

  • interactionSource ve indication: Kullanıcılar composable'a dokunduğunda varsayılan olarak dalga çizer. Kullanıcı etkileşimlerini yönetme sayfasından bunların nasıl özelleştirileceğini öğrenin.
  • Anlambilim bilgilerini ayarlayarak erişilebilirlik hizmetlerinin öğe ile etkileşim kurmasına olanak tanır.
  • Etkileşim için odaklamaya izin verip Enter veya d-pad'in ortasına basarak klavye veya kontrol çubuğu etkileşimini destekler.
  • Öğenin fareyle üzerine gelinebilir olmasını sağlayın, böylece üzerine fare veya ekran kalemine yanıt verilir.

Bağlamsal içerik menüsünü göstermek için uzun basın

combinedClickable, normal tıklama davranışına ek olarak iki kez dokunma veya uzun basma davranışı eklemenize olanak tanır. Kullanıcı bir ızgara resmine dokunup basılı tuttuğunda içerik menüsünün gösterilmesi için combinedClickable kullanabilirsiniz:

var contextMenuPhotoId by rememberSaveable { mutableStateOf<Int?>(null) }
val haptics = LocalHapticFeedback.current
LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 128.dp)) {
    items(photos, { it.id }) { photo ->
        ImageItem(
            photo,
            Modifier
                .combinedClickable(
                    onClick = { activePhotoId = photo.id },
                    onLongClick = {
                        haptics.performHapticFeedback(HapticFeedbackType.LongPress)
                        contextMenuPhotoId = photo.id
                    },
                    onLongClickLabel = stringResource(R.string.open_context_menu)
                )
        )
    }
}
if (contextMenuPhotoId != null) {
    PhotoActionsSheet(
        photo = photos.first { it.id == contextMenuPhotoId },
        onDismissSheet = { contextMenuPhotoId = null }
    )
}

En iyi uygulama olarak, kullanıcı öğelere uzun bastığında dokunsal geri bildirim eklemeniz gerekir. Snippet, bu nedenle performHapticFeedback çağrısını içerir.

Bir öğeye dokunarak composable'ı kapatın

Yukarıdaki örneklerde clickable ve combinedClickable, composable'larınıza yararlı işlevler katar. Etkileşim hakkında görsel bir işaret gösterir, fareyle üzerine gelmeye yanıt verir ve odak, klavye ve erişilebilirlik desteği içerir. Ancak bu ekstra davranış her zaman arzu edilen bir davranış değildir.

Şimdi, resim ayrıntıları ekranına bakalım. Arka plan yarı şeffaf olmalıdır ve kullanıcı bu arka plana dokunarak ayrıntı ekranını kapatabilir:

Bu durumda, arka planın etkileşimle ilgili herhangi bir görsel göstergesi bulunmamalı, üzerine gelmeye yanıt vermemeli, odaklanılamayacak bir öğe ve klavye ile erişilebilirlik etkinliklerine verdiği yanıt tipik bircomposable'dan farklı olmalıdır. clickable davranışını uyarlamaya çalışmak yerine, daha düşük bir soyutlama seviyesine geçebilir ve pointerInput değiştiricisini doğrudan detectTapGestures yöntemiyle birlikte kullanabilirsiniz:

@OptIn(ExperimentalComposeUiApi::class)
@Composable
private fun Scrim(onClose: () -> Unit, modifier: Modifier = Modifier) {
    val strClose = stringResource(R.string.close)
    Box(
        modifier
            // handle pointer input
            .pointerInput(onClose) { detectTapGestures { onClose() } }
            // handle accessibility services
            .semantics(mergeDescendants = true) {
                contentDescription = strClose
                onClick {
                    onClose()
                    true
                }
            }
            // handle physical keyboard input
            .onKeyEvent {
                if (it.key == Key.Escape) {
                    onClose()
                    true
                } else {
                    false
                }
            }
            // draw scrim
            .background(Color.DarkGray.copy(alpha = 0.75f))
    )
}

pointerInput değiştiricisinin anahtarı olarak onClose lambda'yı geçersiniz. Bu işlem lambda'yı otomatik olarak yeniden yürütür ve kullanıcı kumaşa dokunduğunda doğru geri çağırmanın çağrılmasını sağlar.

Yakınlaştırmak için iki kez dokunun

Bazen clickable ve combinedClickable, etkileşime doğru şekilde yanıt vermek için yeterli bilgi içermez. Örneğin, composable'ların etkileşimin gerçekleştiği composable'ın sınırları içinde kalan konuma erişmesi gerekebilir.

Şimdi, resim ayrıntıları ekranına tekrar bakalım. En iyi uygulamalardan biri, iki kez dokunarak resmi yakınlaştırmaktır:

Videoda görebileceğiniz gibi yakınlaştırma, dokunma etkinliğinin konumunun çevresinde gerçekleşiyor. Sonuç, resmin sol kısmını yakınlaştırmak yerine sağ kısmını yakınlaştırdığımızda farklı olur. Dokunma konumunu hesaplamamıza dahil etmek için pointerInput değiştiricisini detectTapGestures ile birlikte kullanabiliriz:

var zoomed by remember { mutableStateOf(false) }
var zoomOffset by remember { mutableStateOf(Offset.Zero) }
Image(
    painter = rememberAsyncImagePainter(model = photo.highResUrl),
    contentDescription = null,
    modifier = modifier
        .pointerInput(Unit) {
            detectTapGestures(
                onDoubleTap = { tapOffset ->
                    zoomOffset = if (zoomed) Offset.Zero else
                        calculateOffset(tapOffset, size)
                    zoomed = !zoomed
                }
            )
        }
        .graphicsLayer {
            scaleX = if (zoomed) 2f else 1f
            scaleY = if (zoomed) 2f else 1f
            translationX = zoomOffset.x
            translationY = zoomOffset.y
        }
)