iT邦幫忙

2024 iThome 鐵人賽

DAY 24
0

前言

昨天我們用了上下滑的事件來觸發頁面跳轉的功能,今天我們來拓展一下這方面的內容,我弄了一個教學用的程式來做一些簡單的示範

程式碼

程式碼如下

  • kotlin
package com.example.myapplication

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.BasicText
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
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.foundation.gestures.detectTapGestures
import androidx.compose.foundation.gestures.detectTransformGestures
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.graphics.graphicsLayer

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MultiGestureTutorial()
        }
    }
}

@Composable
fun MultiGestureTutorial() {
    var boxContent by remember { mutableStateOf("點擊、長按、雙擊、拖動、縮放或旋轉方塊") }
    var scale by remember { mutableStateOf(1f) }  // 用於縮放
    var rotation by remember { mutableStateOf(0f) }  // 用於旋轉
    var offsetX by remember { mutableStateOf(0f) }  // 用於拖動
    var offsetY by remember { mutableStateOf(0f) }  // 用於拖動

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White)
    ) {
        // 使用 pointerInput,整合各種手勢處理邏輯
        Box(
            modifier = Modifier
                .size(200.dp)
                .offset { IntOffset(offsetX.toInt(), offsetY.toInt()) }  // 拖動效果
                .background(Color.Gray)
                .pointerInput(Unit) {
                    // 偵測縮放與旋轉手勢
                    detectTransformGestures { _, pan, zoom, rotationChange ->
                        scale *= zoom  // 更新縮放比例
                        rotation += rotationChange  // 更新旋轉角度
                        boxContent = "縮放: ${String.format("%.2f", scale)}, 旋轉: ${String.format("%.2f", rotation)}°"
                    }
                }
                .pointerInput(Unit) {
                    // 偵測點擊、雙擊與長按手勢
                    detectTapGestures(
                        onTap = { offset ->
                            boxContent = "單擊觸發,位置: $offset"
                        },
                        onDoubleTap = { offset ->
                            boxContent = "雙擊觸發,位置: $offset"
                        },
                        onLongPress = { offset ->
                            boxContent = "長按觸發,位置: $offset"
                        }
                    )
                }
                .pointerInput(Unit) {
                    // 偵測拖動手勢
                    detectDragGestures { change, dragAmount ->
                        offsetX += dragAmount.x
                        offsetY += dragAmount.y
                        boxContent = "拖動中..."
                    }
                }
                .graphicsLayer(
                    scaleX = scale,
                    scaleY = scale,
                    rotationZ = rotation
                )
        )

        BasicText(
            text = boxContent,
            modifier = Modifier.background(Color.Transparent),
            style = MaterialTheme.typography.bodyLarge
        )
    }
}

@Preview(showBackground = true)
@Composable
fun MultiGestureTutorialPreview() {
    MultiGestureTutorial()
}

這個程式的目的是演示如何在Jetpack Compose中實現基本的觸控手勢,包括拖動、縮放、旋轉,以及單擊、雙擊和長按等功能。在這段程式中,我們使用了多種手勢偵測器來處理使用者的觸控行為,並即時更新畫面上的方塊,讓我們能夠直觀地看到每個手勢的效果。
首先,我們定義了一個Box,用來承載可以進行手勢互動的灰色方塊。這個方塊可以根據使用者的手勢進行移動、縮放和旋轉。方塊的外觀會即時根據手勢發生變化。手勢的核心處理是透過pointerInput函數來完成的。在這個函數中,我們可以定義不同的手勢邏輯,來捕捉使用者的觸控動作。
首先,我們使用detectTransformGestures來偵測縮放和旋轉的手勢。這個函數會捕捉到多點觸控時的縮放比例 (zoom) 和旋轉角度(rotationChange),並且將這些值應用到方塊的scalerotation屬性上。當使用者用雙指捏合時,方塊會根據縮放比例放大或縮小;當雙指旋轉時,方塊也會跟著旋轉。這些變化透過graphicsLayer來實現,讓方塊的外觀即時更新。
接下來,我們使用detectTapGestures來處理單擊、雙擊和長按的手勢,我們針對不同的點擊行為設定回調。例如,當使用者單擊方塊時,會觸發onTap回調,並顯示單擊的位置;雙擊會觸發onDoubleTap,而長按則觸發 onLongPress。這些手勢被偵測到後,我們會更新boxContent,即時將手勢結果顯示在介面上。
此外拖動的功能是透過 detectDragGestures 來實現的。當使用者按住並拖動方塊時,方塊的位置會根據拖動的距離進行更新,這是通過改變 offsetX 和 offsetY 來完成的。這樣,方塊就可以隨著使用者的手勢在螢幕上移動。
下面有示範的影片
Yes

後話

今天有事情出去了一趟文章的內容比較水一點,補充一下昨天沒講到的東西,今天的內容就到這邊,我們明天再見,


上一篇
Day23:在APP使用上下滑動的手勢觸發事件
下一篇
Day25:Jetpack Compose的退出視窗
系列文
github裡永遠有一個還沒做的SideProject :用Kotlin來開發點沒用的酷東西30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言