Ç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
veindication
: 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 } )
Sizin için önerilenler
- Not: Bağlantı metni JavaScript kapalıyken görüntülenir
- Hareketleri anlama
- Oluşturma işleminde Materyal Tasarım 2
- Jetpack Compose için Kotlin