目次
概要
タップした時、長押しした時に処理を行いたいことはあるが、
例えば、グリッド上に表示されているビューをタップした時、タップではなく長押しした時に処理を行う時など。
今回はそのボタン以外でタップ、長押しをする時の実装方法を記載する。
ソースコード
アプリの最初の実行部分
import SwiftUI
@main
struct TestApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
TapGestureView()
}
}
}
View表示部分
import SwiftUI
struct TapGestureView: View {
@ObservedObject private var viewModel = TapGestureViewModel()
@State var textColor: Color = .black
@State var iconTapCount: Int = 0
let cellImage = Image(systemName: "bell.square")
var gradientLayer = CAGradientLayer()
var body: some View {
VStack {
Spacer()
Text("セルを表示しているよ")
.frame(width: 240, height: 100)
.border(textColor)
.foregroundColor(textColor)
.onTapGesture {
iconTapCount += 1
switch iconTapCount % 5 {
case 0:
textColor = .red
case 1:
textColor = .blue
case 2:
textColor = .green
case 3:
textColor = .yellow
case 4:
textColor = .black
default:
textColor = .black
}
}
Spacer()
cellImage
.resizable(resizingMode: .stretch)
.frame(width: 100, height: 100)
.foregroundColor(viewModel.imageColor)
.onLongPressGesture(minimumDuration: 1.0, maximumDistance: 20) {
print("長押し処理")
viewModel.timerFiring()
} onPressingChanged: { isPress in
if isPress {
print("押されてからminimumDurationの時間が経つまで")
viewModel.stopTimer()
} else {
print("minimumDurationだけ時間が経った")
}
}
Spacer()
}
}
}
処理部分
import Foundation
import SwiftUI
class TapGestureViewModel: ObservableObject {
var red: Double = 1.0
var green: Double = 0.0
var blue: Double = 0.0
var count: Int = 0
var timer: Timer?
@Published private(set) var imageColor: Color = Color.init(red: 1.0, green: 0.0, blue: 0.0)
func timerFiring() {
timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(updateColor), userInfo: nil, repeats: true)
}
@objc private func updateColor() {
count = (count + 1) % 300
switch count {
case 0 ..< 50:
red = 1.0
green = 0.0
blue = 0.0 + Double(count)/50.0
case 50 ..< 100:
red = 1.0 - Double(count-50)/50.0
green = 0.0
blue = 1.0
case 100 ..< 150:
red = 0.0
green = 0.0 + Double(count-100)/50.0
blue = 1.0
case 150 ..< 200:
red = 0.0
green = 1.0
blue = 1.0 - Double(count-150)/50.0
case 200 ..< 250:
red = 0.0 + Double(count-200)/50.0
green = 1.0
blue = 0.0
case 250 ..< 300:
red = 1.0
green = 1.0 - Double(count-250)/50.0
blue = 0.0
default:
red = 0.0
green = 0.0
blue = 0.0
}
imageColor = Color(red: red, green: green, blue: blue)
}
func stopTimer() {
timer?.invalidate()
}
}
デモ動画
以下の動画は、「セルを表示しているよ」の部分をタップすると色が変わり、
下の「ベルマーク」を長押しすると色が変わるというもの
詳細
タップした時の処理を実装
Viewなど、ボタン以外のタップをした時の処理の実装方法
.onTapGesture {
// UIをタップされた時に行われる処理
}
長押しした時に表示されるメニュー
長押しした時に行う処理の実装方法
.onLongPressGesture {
// 長押しをした時に行われる処理
}
また、ソースコードに書かれたもののように、onLongPressGestureには以下の設定値も設定することができる。最低限設定する必要があるのがperform actionのみ。
引数名 | 内容 |
minimumDuration | UIをタップしてから長押しの処理を行うまでの時間 Double型でデフォルトは0.5 |
maximumDistance | UIをタップしたところを中心に動かしてもいい範囲 CGFloat型でデフォルトは10 |
perform action(必須) | (() -> Void)型で長押ししている時の処理内容 |
onPressingChanged | ((Bool) -> Void)?型でデフォルトはnil isPressがtrue →UIが押されてからminimumDurationの時間が経つまで isPressがfalse →UIが押されてからminimumDurationの時間が経った時 |
参考ページ:
iOS アプリ開発「[SwiftUI] タップや長押しの認識、onTapGestureとonLongPressGesture」
Qiita「Swift4環境でTimerの使い方と挙動を確認してみた」