Birçok composable, dokunma veya tıklama için yerleşik desteğe sahiptir ve bir onClick lambda içerir. Örneğin, yüzeylerle etkileşim için uygun olan 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 tıklamalar, kullanıcıların composable'larla etkileşim kurmasının tek yolu değildir. Bu sayfada, tek bir işaretçi içeren ve bu işaretçinin konumunun, ilgili etkinliğin işlenmesi açısından önemli olmadığı hareketler ele alınmaktadır. Aşağıdaki tabloda bu hareket türleri listelenmiştir:
Hareket |
Açıklama |
Dokunun (veya tıklayın) |
İşaretçi önce aşağı, sonra yukarı hareket eder. |
İki kez dokunma |
İşaretçi aşağı, yukarı, aşağı, yukarı hareket ediyor |
Uzun basma |
İşaretçi aşağı iner ve daha uzun süre basılı tutulur |
Basın |
İşaretçi aşağı gider |
Dokunma veya tıklama işlemine yanıt verme
clickable, composable'ın dokunma veya tıklamalara tepki vermesini sağlayan, en çok tercih edilen bir değiştiricidir. Bu değiştirici, odaklanma, fare ve ekran kalemiyle üzerine gelme desteği ve basıldığında özelleştirilebilir bir görsel gösterge gibi ek özellikler de ekler. Değiştirici, kelimenin en geniş anlamıyla "tıklamalara" yanıt verir. Bu tıklamalar yalnızca fare veya parmakla değil, klavye girişiyle ya da erişilebilirlik hizmetleri kullanılırken yapılan tıklama etkinliklerini de kapsar.
Kullanıcıların tıkladığında tam ekran olarak gösterilen bir resim ızgarası düşünün:
Bu davranışı uygulamak için ızgaradaki 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ış da ekler:
- Kullanıcı composable'a dokunduğunda varsayılan olarak dalga efekti çizen
interactionSourceveindication. Bunları nasıl özelleştireceğinizi Kullanıcı etkileşimlerini işleme sayfasından öğrenebilirsiniz. - Semantik bilgilerini ayarlayarak erişilebilirlik hizmetlerinin öğeyle etkileşim kurmasına olanak tanır.
- Odaklanmaya ve etkileşim için
Enterveya d-pad'in ortasına basmaya izin vererek klavye ya da kontrol çubuğu etkileşimini destekler. - Öğeyi fareyle üzerine gelinebilir hale getirin. Böylece fare veya ekran kalemiyle üzerine gelindiğinde yanıt verir.
Bağlam 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 bağlam menüsü göstermek 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 geribildirim eklemeniz gerekir. Bu nedenle snippet, performHapticFeedback çağrısını içerir.
Scrim'e dokunarak composable'ı kapatma
Yukarıdaki örneklerde clickable ve combinedClickable, composable'larınıza faydalı işlevler ekler. Etkileşimde görsel bir gösterge sunar, fareyle üzerine gelindiğinde yanıt verir ve odak, klavye ve erişilebilirlik desteği içerir. Ancak bu ek davranış her zaman istenmeyebilir.
Resim ayrıntıları ekranına bakalım. Arka plan yarı şeffaf olmalı ve kullanıcı, ayrıntı ekranını kapatmak için bu arka plana dokunabilmelidir:
Bu durumda, arka planın etkileşimle ilgili görsel bir göstergesi olmamalı, fareyle üzerine gelmeye yanıt vermemeli, odaklanılabilir olmamalı ve klavye ile erişilebilirlik etkinliklerine verdiği yanıt, tipik bir composable'ın yanıtından farklı olmalıdır. clickable davranışını uyarlamaya çalışmak yerine daha düşük bir soyutlama düzeyine inebilir ve pointerInput değiştiricisini doğrudan detectTapGestures yöntemiyle birlikte kullanabilirsiniz:
@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ı iletirsiniz. Bu, lambda'yı otomatik olarak yeniden yürütür ve kullanıcı scrim'e 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 sınırları içindeki konuma erişmesi gerekebilir.
Resim ayrıntıları ekranına tekrar bakalım. En iyi uygulamalardan biri, iki kez dokunarak resmin yakınlaştırılabilmesini sağlamaktır:
Videoda gördüğünüz gibi, dokunma etkinliğinin gerçekleştiği konumda yakınlaştırma yapılıyor. Resmin sol tarafını yakınlaştırdığımızda elde ettiğimiz sonuç, sağ tarafını yakınlaştırdığımızda elde ettiğimiz sonuçtan farklıdır. 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: JavaScript devre dışı bırakıldığında bağlantı metni gösterilir.
- Hareketleri anlama
- Compose'da Materyal Tasarım 2
- Jetpack Compose için Kotlin