SwiftUIでカラーピッカーを作るという連載です。今回はノブをドラッグ(パン)ジェスチャーで移動できるようにする処理を実装します。
SwiftUIではDragGestureを使う
UIKitではiOSやiPadOSで、スクリーンを指でなぞるジェスチャーのことを「パン」と呼びます。macOSではマウスやトラックパッドを使って行う同様の操作は「ドラッグ」と呼んでいます。
SwiftUIはiOS, iPadOS, macOSのいずれにも対応しているので「ドラッグジェスチャー」と呼んでいます。
DragGestureの使い方
SwiftUIでドラッグジェスチャーを使うには、ジェスチャーを使いたいビューのgesture()
モディファイアにDragGesture
を渡します。
var drag: some Gesture {
DragGesture()
.onChanged { dragValue in
// ドラッグ中の処理
}
.onEnded { dragValue in
// ドラッグ完了時の処理
}
}
var body: some View {
SomeView() // ジェスチャーを使うビュー
.gesture(drag)
}
ノブの移動処理の実装
ドラッグジェスチャーでノブを移動する処理を実装します。まずは、ドラッグジェスチャーの処理の実装です。
dragプロパティの実装
実装する処理はタップと同様に、ジェスチャーの発生している座標のX座標の値から現在値を計算して、ColorPickerChannelModel.currentValue
プロパティの値を更新します。
PickerGradationView
に次のようなコードを追加します。
struct PickerGradationView: View {
var drag: some Gesture {
DragGesture()
.onChanged { dragValue in
channel.changeCurrentValue(dragValue.location.x / gradation.viewSize.width)
channel.clearFieldText()
}
}
ビューへのジェスチャーの設定
drag
プロパティで取得したジェスチャーをビューに設定します。ビューへの設定はgesture()
モディファイアを使用します。次のようなコードになります。
struct PickerGradationView: View {
var body: some View {
ZStack(alignment: .leading) {
GeometryReader() { geometry in
LinearGradient(gradient: Gradient(colors: [gradation.startColor, gradation.endColor]), startPoint: UnitPoint(x: 0, y: 0), endPoint: UnitPoint(x: 1, y: 0))
}
.frame(height: gradationHeigh)
.background {
GeometryReader { geometry in
Path { path in
Task.detached {
await updateViewSize(geometry.size)
}
}
}
}
.onTapGesture { point in
channel.currentValue = point.x / gradation.viewSize.width
channel.clearFieldText()
}
.gesture(drag)
動作確認
動作確認します。ColorPicker.swift
を開いてライブプレビューでグラデーションビュー上をドラッグします。ドラッグしたカーソルの位置にノブが移動して、テキストフィールドにも新しい現在値が表示されます。
コードのダウンロード
今回の記事で作成したコードのダウンロードはこちらです。