【发布时间】:2020-11-02 07:59:22
【问题描述】:
我们来看看这段代码:
@State private var progress: TimeInterval = 0
@State private var sliderMoving: Bool = false
Slider(value: $progress, in: 0 ... Double(100), onEditingChanged: { didChange in
seekToProgress(p: progress)
}).simultaneousGesture(
DragGesture(minimumDistance: 0)
.onChanged { gesture in
print("gesture onChanged")
sliderMoving = true
}
.onEnded { gesture in
print("gesture onEnded")
sliderMoving = false
}
)
我想跟踪滑块上的触地和结束事件,但这会阻止实际的滑块被触摸。换句话说,尽管使用了同步手势,但 DragGesture 似乎消耗了触摸。我也尝试过添加 GestureMask.all,但也没有用。我怎样才能解决这个问题?我需要跟踪触摸向下/向上,因为此滑块用于查找音轨,而且音轨也会更新滑块。然而它不应该这样做,当用户触摸滑块时(滑块移动标志应该处理这个)。
类似的方法适用于按钮点击,但不适用于滑块移动。
编辑:
我正在发布最终答案,感谢@Marco Boerner 的大力帮助:
GeometryReader { geometry in
Slider(value: $progress, in: 0 ... Double(100), onEditingChanged: { didChange in
print("onEditingChanged") //not used
})
.simultaneousGesture(
DragGesture(minimumDistance: 0)
.onChanged { gesture in
sliderMoving = true
updateProgress(x: gesture.location.x, width: geometry.size.width)
}
.onEnded { gesture in
sliderMoving = false
updateProgress(x: gesture.location.x, width: geometry.size.width)
seekToProgress(p: progress)
}
)
}
private func updateProgress(x: CGFloat, width: CGFloat) {
let knobWidth: CGFloat = 30
if x < knobWidth / 2 {
progress = TimeInterval(0)
} else if x >= width - knobWidth / 2 {
progress = TimeInterval(100)
} else {
let x2 = x - knobWidth / 2
let width2 = width - knobWidth
progress = TimeInterval(x2 / (width2 / 100))
}
}
唯一的缺点是我们假设旋钮有一个固定值,但因为我将滑块高度设置为 30,所以在我的情况下它完美无缺。
【问题讨论】:
-
我们遇到了类似的问题并尝试了各种方法。我认为你不能同时运行两个相同的手势。假设 Slider 有自己的 DragGesture 他们似乎在干扰。使用 TapGesture 而不是 DragGesture 可用于上触,但不会记录触地。您是否尝试过将
sliderMoving = true移动到滑块本身的didChange内,并将sliderMoving = false与TapGesture 的.onEnded 一起使用? -
这种方法不起作用 - onTapGesture 仅在点击到位时才被调用,更糟糕的是 didChange 总是在它之后调用。所以它只是在播放曲目时阻止滑块更新。
-
好的,我想我想错了。播放音轨时如何以编程方式更新 Slider?我的想法是设置您的 DragGesture 以编程方式更新滑块。基本上完全绕过了滑块手势识别器。
-
好的,我试过了,它似乎对我的情况和理解有效。如果这是您正在寻找的解决方案,请尝试一下。 :)
标签: ios swift xcode swiftui ios14