UI をドラッグ操作で動かしたい。今回は要素の並び方を元にしてUIを構築する Jetpack Compose でどのように実現できるのか調べました。
最初に Composable の modifier でドラッグ移動を実現する方法について見てみます。
@Composable
fun DragMe() {
var offserX by remember { mutableStateOf(0) }
var offserY by remember { mutableStateOf(0) }
Text(
text = "Drag Me",
modifier = Modifier
.offset{ IntOffset(offserX, offserY) }
.pointerInput(Unit) {
detectTransformGestures { change, dragAmount, _ , _ ->
offserX += dragAmount.x.toInt()
offserY += dragAmount.y.toInt()
}
}
.background(Color.LightGray)
)
}
最初に、xとyの offset を保持、監視するために、remember mutableStateOf を使用して宣言しておきます。
次に、Text の modifier で offset に それらを渡します。
あとは offset の値をドラッグ操作で更新するだけです。
modifier の pointerInput は key と suspend fun の block を受け取ります。
key はポインター入力の種類を識別するための引数です(タッチ、マウス、ペン など…)。基本的には Unit が渡されます。
ドラッグ操作を行っている間だけ関数を動作させるため、引数に渡すのは suspend fun になります。suspend fun は中断可能な関数です。
detectTransformGestures はポインターの変換ジェスチャ(ドラッグやスケーリングなど…)を検出するメソッドで、これを用いてoffserを更新します。
4つのラムダ式が含まれますが、今回はドラッグの量を示す Offset のオブジェクトである dragAmount を使います。x,y の offset の値を dragAmount でそれぞれ更新します。
先ほどの方法では、Composable 毎に modifier を書くことになるのでコードの再利用がしにくいです。
そこで、動かしたい Composable 関数をラップする Composable を用意してみます。
@Composable
fun DragMe2(content: @Composable (Modifier) -> Unit) {
var offserX by remember { mutableStateOf(0) }
var offserY by remember { mutableStateOf(0) }
Column(
modifier = Modifier
.offset { IntOffset(offserX, offserY) }
.pointerInput(Unit) {
detectTransformGestures { _, dragAmount, _, _ ->
offserX += dragAmount.x.toInt()
offserY += dragAmount.y.toInt()
}
}
) {
content(Modifier)
}
}