Jetpack Compose предоставляет функционал для работы с распространенными жестами (касание, двойное касание, длительное нажатие и перетаскивание, масштабирование, вращение, смахивание и т.д.). Причем в некоторых случаях Compose предоставляет два способа обнаружения жестов. Один из подходов предполагает использование модификаторов обнаружения жестов. Другой подход - применение функций интерфейса PointerInputScope, которые требуют дополнительного написания кода, но предоставляют более продвинутые возможности работы с жестами.
Первый подход уже был ранее частично рассмотрен. В частности, с помощью модификатора clickable можно обнаружить касание на компоненте. Этот модификатор принимает функцию (лямбду), которая выполняется при касании/нажатии на компоненте, к которому применяется этот модификатор. Например:
Text( "Click", Modifier.clickable { // здесь обработка нажатия } )
Проблема данного модификатора состоит в том, что он не может различать различные типы жестов - касания, нажатия, длинные нажатия и двойные нажатия.
Для этого уровня точности нам нужно использовать функцию detectTapGestures() класса PointerInputScope
. Эта функция применяется к компоненту через
модификатор pointerInput(), который дает нам доступ к PointerInputScope следующим образом:
Text( "Click", Modifier .pointerInput(Unit) { detectTapGestures( onPress = { /* обработка нажатия */ }, onDoubleTap = { /* обработка двойного нажатия */ }, onLongPress = { /* обработка долгого нажатия */ }, onTap = { /* обработка простого касания */ } ) } )
Рассмотрим небольшой пример:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.background import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { var tapType by remember { mutableStateOf("Undefined") } Column(Modifier.fillMaxSize()) { Box( Modifier .padding(10.dp) .background(Color.DarkGray) .size(200.dp) .pointerInput(Unit) { detectTapGestures( onPress = { tapType = "onPress" }, onDoubleTap = { tapType = "onDoubleTap" }, onLongPress = { tapType = "onLongPress" }, onTap = { tapType = "onTap" } ) } ) Text(tapType, Modifier.padding(10.dp), fontSize = 25.sp) } } } }
В данном случае по нажатию на темно-сервый квадрат в модиифкаторе pointerInput
перехватываем тип нажатия и выводим его в текстовое поле.