让我们想象一下,这是一个带有一些元素的ScrollView,我想要在这些元素上长时间点击一些操作(例如,更改 colored颜色 ).但我也想让滚动这个视图成为可能.
下面是一个例子:
import SwiftUI
struct TextBox: View {
var text: String
var color: Color
@GestureState private var isLongPressure: Bool = false
var body: some View {
let longTap = LongPressGesture(minimumDuration: 0.3)
.updating($isLongPressure) { state, newState, transaction in
newState = state
transaction.animation = .easeOut(duration: 0.2)
}
Text(text)
.frame(width: 400, height: 200)
.background(isLongPressure ? .white : color)
.simultaneousGesture(longTap)
}
}
struct TestGestures: View {
var body: some View {
ScrollView {
TextBox(text: "Test 1", color: .red)
TextBox(text: "Test 2", color: .green)
TextBox(text: "Test 3", color: .blue)
TextBox(text: "Test 4", color: .red)
TextBox(text: "Test 5", color: .green)
TextBox(text: "Test 6", color: .blue)
}
}
}
struct TestGestures_Previews: PreviewProvider {
static var previews: some View {
TestGestures()
}
}
因此,如果我 comments .simultaneousGesture(longTap)
-滚动工作,但如果我取消 comments -滚动停止工作.
附言:我试着在添加LongTap之前添加onTapGesture
,但没有帮助.
提前谢谢!
Update:个
感谢您提供的解决方案@nickreps:
import SwiftUI
struct TextBox: View {
var text: String
var color: Color
@GestureState private var isLongPressure: Bool = false
var body: some View {
let longTap = LongPressGesture(minimumDuration: 0.3)
.updating($isLongPressure) { value, state, transaction in
state = value
transaction.animation = .easeOut(duration: 0.2)
}
Text(text)
.frame(width: 400, height: 200)
.background(isLongPressure ? .white : color)
.delaysTouches(for: 0.01) {
//some code here, if needed
}
.gesture(longTap)
}
}
struct TestGestures: View {
var body: some View {
ScrollView {
TextBox(text: "Test 1", color: .red)
TextBox(text: "Test 2", color: .green)
TextBox(text: "Test 3", color: .blue)
TextBox(text: "Test 4", color: .red)
TextBox(text: "Test 5", color: .green)
TextBox(text: "Test 6", color: .blue)
}
}
}
extension View {
func delaysTouches(for duration: TimeInterval = 0.25, onTap action: @escaping () -> Void = {}) -> some View {
modifier(DelaysTouches(duration: duration, action: action))
}
}
fileprivate struct DelaysTouches: ViewModifier {
@State private var disabled = false
@State private var touchDownDate: Date? = nil
var duration: TimeInterval
var action: () -> Void
func body(content: Content) -> some View {
Button(action: action) {
content
}
.buttonStyle(DelaysTouchesButtonStyle(disabled: $disabled, duration: duration, touchDownDate: $touchDownDate))
.disabled(disabled)
}
}
fileprivate struct DelaysTouchesButtonStyle: ButtonStyle {
@Binding var disabled: Bool
var duration: TimeInterval
@Binding var touchDownDate: Date?
func makeBody(configuration: Configuration) -> some View {
configuration.label
.onChange(of: configuration.isPressed, perform: handleIsPressed)
}
private func handleIsPressed(isPressed: Bool) {
if isPressed {
let date = Date()
touchDownDate = date
DispatchQueue.main.asyncAfter(deadline: .now() + max(duration, 0)) {
if date == touchDownDate {
disabled = true
DispatchQueue.main.async {
disabled = false
}
}
}
} else {
touchDownDate = nil
disabled = false
}
}
}
struct TestGestures_Previews: PreviewProvider {
static var previews: some View {
TestGestures()
}
}