SwiftUIでViewの表示領域を限定する際に、.clipped()モディファイアはとても便利である.
しかし....clipped()を使って画像のドラッグ移動などを実装する時、例えば.offset()などで画像表示位置を変更した場合、下記の図の様にclippedで非表示領域もタップが有効なままなので、下層のView(ボタンとか)がタップできなくなくなってしまう.
別に気にならないケースもあるでしょうけど、この例みたいに別のタップしたいアクションがあるとちょっと困るのだ.
そこで、シンプルな解決法がこれ.
.contentShape(Rectangle())
このモディファイアを1行追加するだけで問題は解消するのである.
例)画像をドラッグ移動するサンプル↓
Sample_for_contentShape
import SwiftUI
struct ContentView: View {
@State var offset:CGSize = .zero // drag value
@State var lastOffset: CGSize = .zero // hold last drag value
var dragGesture: some Gesture { // Gesture for Drag to move
DragGesture()
.onChanged {
offset = CGSize(width: lastOffset.width + $0.translation.width, height: lastOffset.height + $0.translation.height) }
.onEnded{ _ in
lastOffset = offset }
}
var body: some View {
VStack {
Button(action: { // Reset drag
offset = .zero
lastOffset = .zero
}){ Text("Reset") }
Image("bluesky") // 背景の青空画像
.resizable()
.scaledToFit()
.overlay(
Image("strawberry") // 苺の画像:切り抜きで背景透過
.resizable()
.scaledToFit()
.offset(offset)
.gesture(dragGesture)
)
.frame(width: 300)
.clipped()
.contentShape(Rectangle()) // *** これを追加すれば解決! ***
}
}
}
この解法はネット検索しても意外に僅かしか出てこなかったので、ここに掲載.
環境情報:
Xcode 14.3, Swift 5.8