Jetpack Oluşturmada Hareket İşleme Değiştiricileri | Sherry Yuan tarafından

Jetpack Oluşturmada Hareket İşleme Değiştiricileri |  Sherry Yuan tarafından
fotoğrafı çeken Ebuen Clemente Jr. üzerinde Sıçramayı kaldır

Jetpack Compose, UI öğelerinin bildirimsel Composable işlevleriyle oluşturulduğu, Android’in modern UI araç takımıdır. Kullanıcı hareketlerini algılamaya yardımcı olmak için yeni bir API seti sunar. Henüz Compose ile çalışmadıysanız, öneririm temellerini öğrenmek bu makaleyi okumadan önce.

Bu makale, Android Dokunmatik Sistem serimin bir parçasıdır ve okuyucuların aşağıdakileri biraz anladıklarını varsayar. MotionEvents. Bunlara aşina değilseniz, lütfen kontrol edin Bölüm 1: Dokunma İşlevleri ve Görünüm Hiyerarşisi.

Kullanımları oluştur ModifierDolgu ve erişilebilirlik etiketleri dahil olmak üzere Composables için çeşitli öznitelikleri yapılandırmak için s. Hareket algılama da şu şekilde eklenir: Modifiers.

Bunlardan bazıları Modifiers üst düzeydir ve yaygın olarak kullanılan hareketleri kapsar. Örneğin, Modifier.clickable() basit tıklama algılamasına izin verir ve ayrıca Composable tıklandığında dalgalanmalar gibi görsel göstergeler görüntüler. Başka Modifiers daha düşük bir düzeyde daha fazla esneklik sunar ve daha az yaygın hareketleri algılamak için kullanılabilir.

Hareketleri işlemek için lambda parametrelerini kullanan birkaç Composable da vardır. Modifiers, örneğinButton() onunla onClick: () -> Unit parametredir, ancak bunlar kuraldan ziyade istisnadır.

Bu makalenin geri kalanı jestle ilgili ModifierCompose API’deki s ve bunların nasıl kullanılacağı.

Modifier.pointerInput() esnek, düşük seviyeli Modifier benzer OnTouchListener. Lambda parametresi çalışır PointerInputScopebize işaretçi boyutuna, olaya ve işaretçi girdisini işlemek için yararlı olan diğer alanlara erişim sağlar.

PointerInputScope gibi işlevler de sağlar. detectTapGestures() ve detectDragGestures() çeşitli hareketleri algılamak için. detectTapGestures() için yararlı bir alternatiftir Modifier.clickable() Musluğun tam konumuna ihtiyacımız varsa veya özel görsel değişiklikler veya erişilebilirlik göstergeleri eklemek istiyorsak.

Örnek kullanım:

Box(modifier = Modifier.pointerInput(Unit) {
detectTapGestures(
onTap = { Log.d(TAG, “Box tapped at ${it.x}, ${it.y}”) },
onDoubleTap = {
Log.d(TAG, “Box double tapped at ${it.x}, ${it.y}”)
}
)
})

Modifier.clickable() tek tıklamaları dinler ve eşdeğerdir OnClickListener geleneksel görünümlerde. çağırıyor Modifier.pointerInput { detectTapAndPress() } kaputun altında, ancak tıklama geri aramasını başlatmaya ek olarak görsel ve erişilebilirlik göstergeleri içerir. olduğundan daha özlü ve kullanımı daha kolaydır. pointerInput()ve çoğu tıklama işleme için yeterlidir.

Örnek kullanım:

Box(modifier = Modifier.clickable {
Log.d(TAG, “Box clicked”)
})

Modifier.combinedClickable() tek, çift ve uzun tıklamaları dinler. Görünüm dünyasındaki en yakın eşdeğeri GestureDetector; tarafından desteklenen hareketlerin yalnızca bir alt kümesini işler. GestureDetector, ancak kullanımı çok daha basittir. Beğenmek Modifier.clickable()çağırıyor Modifier.pointerInput { detectTapGestures() } kaputun altında.

Örnek kullanım:

Box(modifier = Modifier.combinedClickable(
onClick = { Log.d(TAG, “Box clicked”) },
onDoubleClick = { Log.d(TAG, “Box double clicked”)},
onLongClick = { Log.d(TAG, “Box long clicked”)}
)

Clickable() ve CombineClickable()’ı birlikte kullanırsak ne olur?

İkisi de olursa Modifiers aynı Composable’da ayarlanır, daha sonra Modifier zincir kullanılacaktır. Eğer clickable() sonra gelir combinedClickable()hepsi combinedClickable()‘s onClick, onLongClickve onDoubleClick göz ardı edilecek ve clickable() yerine çağrılacak.

Örneğin, aşağıdaki kod verildi:

Box(modifier = Modifier
.combinedClickable(
onClick = { Log.d(TAG, “Click in combinedClickable”) },
onDoubleClick = {
Log.d(TAG, “Double click in combinedClickable”)
},
onLongClick = {
Log.d(TAG, “Long click in combinedClickable”)
}
)
.clickable { Log.d(TAG, “Click in clickable”) }
)

Normal, çift veya uzun tıklama olsun, kutu tıklandığında yalnızca “Tıklanabilir durumda tıklayın” günlüğe kaydedilir.

Açık olan herhangi bir Composable için onClick parametre, onClick lambda, değiştirici zincirdeki tüm tıklama geri aramalarını geçersiz kılar.

Bunun nedeni, sonunda, onClick parametre değiştirici zincirin sonuna eklenir. Bunu Düğme uygulamasında görebiliriz:

Button(
onClick: () -> Unit,
modifier: Modifier = Modifier,

) {

}

İşlev çağrılarının ardından, bir çağrı görüyoruz. Surface:

Surface(
modifier = modifier.minimumTouchTargetSize(),

clickAndSemanticsModifier = Modifier
.clickable(onClick = onClick)
)

Hangi sırayla çağırır Box ve ekler clickAndSemanticsModifier sonuna kadar Modifier Zincir:

Box(
modifier
.…
.then(clickAndSemanticsModifier)
) {

}

Sonuç olarak, bu verildiğinde:

Button(
onClick = { Log.d(TAG, “Click in onClick”) },
modifier = Modifier.clickable {
Log.d(TAG, “Click in clickable”)
}
)

Düğme tıklandığında yalnızca “Click in Click” günlüğe kaydedilir.

Modifier.draggable() kullanıcının parmağını yere koyduğu hareketi algılar, ekranda sürükler ve sonra kaldırır. bu yardımcı Modifier View dünyasında bir karşılığı olmayan; sürükleme hareketleri geleneksel olarak karmaşık durum yönetimi ve içeride hesaplamalar yapmayı gerektirir onTouchListener.

Örnek kullanım:

val state = rememberDraggableState(
onDelta = { delta -> Log.d(TAG, “Dragged $delta”) }
)
Box(modifier = Modifier.draggable(
state = state,
orientation = Orientation.Vertical,
onDragStarted = { Log.d(TAG, “Drag started”) },
onDragStopped = { Log.d(TAG, “Drag ended”) }
))

Her ikisinde de hareketi içeren daha nüanslı sürükle algılamayı algılamak için x ve y Yol tarifleri, Oluştur ayrıca sağlar detectDragGestures içinde pointerInput:

Modifier.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
Log.d(TAG, “dragged x: ${dragAmount.x}”)
Log.d(TAG, “dragged y: ${dragAmount.y}”)
}
}

Modifier.scrollable() benzer GestureDetector.SimpleOnGestureListener‘s onScroll(). Uygulaması aslında çağırıyor draggable(). İkisi arasındaki temel fark, draggable() yalnızca hareketi algılar, oysa scrollable() sonucuna göre ekranda Composable’ı hem algılar hem de hareket ettirir. consumeScrollDelta.

Örnek kullanım:

val scrollableState = rememberScrollableState(
consumeScrollDelta = {
delta -> Log.d(TAG, “scrolled $delta”)
0f
}
)
Box(modifier = Modifier.scrollable(
state = scrollableState,
orientation = Orientation.Vertical
))

Birleştirilebilir, arasındaki farka göre hareket eder delta ve dönüş değeri consumeScrollDelta. dönüş 0f lambda’dan, kaydırmanın hiçbirinin tüketilmediği ve birleştirilebilir hareket edeceği anlamına gelir delta piksel.

ikisi de çağırıyor scrollable() kaputun altında ve erişmemiz gerekmediği sürece kullanımı daha kolay delta. Ayrıca her iki yöndeki kaydırmaları algılamak için birlikte kullanılabilirler ve birbirlerini geçersiz kılmazlar.

Örnek kullanım:

Box(modifier = Modifier
.verticalScroll(rememberScrollState())
.horizontalScroll(rememberScrollState())
)

Modifier.nestedScroll() ayrıca var, ama biraz daha karmaşık ve bu makalede onu incelemeyeceğim.

Modifier.swipeable() değiştirici ayrıca sürükleme hareketlerini de dinler. Sürükleme serbest bırakıldığında, Composable, kullanarak ayarlayabileceğimiz bir bağlantı durumuna animasyon uygulayacaktır. anchors parametre. Yaygın olarak kullanılan iki kullanım örneği, genişletilmiş ve daraltılmış bağlantı durumlarına sahip bir Composable oluşturmak veya “kaydırmak için kaydır”ı uygulamaktır. Bu, “kaydırma”nın genellikle “kaçma” ile birbirinin yerine kullanıldığı geleneksel Android görünümlerindeki kaydırma hareketleri kavramından biraz farklıdır.

İşte buna benzer bir örnek Android belgeleridaha belirgin durumlarla:

@Composable
fun SwipeableDemo() {
val width = 300.dp
val squareSize = 100.dp
val swipeableState = rememberSwipeableState(States.LEFT)
val squareSizePx = with(LocalDensity.current) {
(width — squareSize).toPx()
}
Box(
modifier = Modifier
.width(width)
.swipeable(
state = swipeableState,
anchors = mapOf(
0f to States.LEFT,
squareSizePx to States.RIGHT
),
thresholds = { _, _ -> FractionalThreshold(0.5f) },
orientation = Orientation.Horizontal
)
.background(Color.LightGray)
) {
Box(
modifier = Modifier
.offset {
IntOffset(swipeableState.offset.value.toInt(), 0)
}
.size(squareSize)
.background(Color.DarkGray)
)
}
}
enum class States { LEFT, RIGHT }

İki tıklanabilir gibi Modifiersdan beri draggable(), scrollable()ve swipeable() hangisi daha sonra gelirse, kaputun altında aynı sürükleme hareketi algılamasını kullanın. Modifier zincir tetiklenecektir.

Modifier.transformable() kaydırma, yakınlaştırma ve döndürme için kullanılan çoklu dokunma hareketlerini algılar. Şuna benzer ScaleGestureDetector geleneksel Görünüm dünyasında. Dönüşümün ölçeğini, dönüşünü ve ofsetini sağlar, ancak grafik dönüşümlerini doğrudan işlemez. Geliştiriciler, dönüşümleri uygulamalıdır. rememberTransformableState {}.

@Composable
fun TransformableDemo() {
var scale by remember { mutableStateOf(1f) }
var rotation by remember { mutableStateOf(0f) }
var offset by remember { mutableStateOf(Offset.Zero) }
val state = rememberTransformableState {
zoomChange, offsetChange, rotationChange ->
scale *= zoomChange
rotation += rotationChange
offset += offsetChange
}

Box(
modifier = Modifier
.graphicsLayer(
scaleX = scale,
scaleY = scale,
rotationZ = rotation,
translationX = offset.x,
translationY = offset.y
)
.transformable(state = state)
.background(Color.Blue)
.fillMaxSize()
)
}

Modifier.pointerInteropFilter() alır onTouchEvent lambda parametresi ve altta yatan erişim sağlar MotionEvents. Birlikte çalışma desteği için Compose API’sine dahil edilmiştir, böylece geliştiriciler daha önce uyguladıkları özel dokunma işlemlerini kullanmaya devam edebilirler.

Örnek kullanım:

class DemoOnTouchListener : View.OnTouchListener {
override fun onTouch(v: View, event: MotionEvent): Boolean {
Log.d(“TAG, “Detecting motion event ${event.action}”)
return false
}
}
// In a Composable
val listener = DemoOnTouchListener()
val view = LocalView.current
Box(
modifier = Modifier
.pointerInteropFilter { motionEvent ->
listener.onTouch(view, motionEvent)
}
)

bu onTouchEvent lambda var Boolean ile aynı dönüş türü olan dönüş türü View.onTouchEvent. Sağlanırsa, Görünüm dünyası gibi onTouchEvent true dönerse, lambda ele geçirilmedikleri sürece gelecekteki olayları almaya devam eder.

İşte linkler Bölüm 1: Dokunma İşlevleri ve Görünüm Hiyerarşisi, 2. Bölüm: Ortak Dokunma Olayı Senaryolarıve Bölüm 3: MotionEvent Dinleyicileri Android Dokunmatik Sistem serimden.

Bölüm 5: Jetpack Compose’da Hareketler Nasıl Çalışır? İşaretçi olaylarının Oluştur hiyerarşisinde nasıl çalıştığını, Oluştur’daki bazı hareket algılama sınırlamalarını ve özel Modifiers sınırlamaları aşmak için.

Başlangıçta, Oluştur’da hareketler için tek bir makale yapmayı planlamıştım ama çok uzun sürüyordu ¯_(ツ)_/¯

Sayesinde Russel ve Kelvin değerli düzenlemeleri ve geri bildirimleri için ❤️

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.