我把我的头发拔了出来,我没有找到一个似乎合适的答案。
我有一个视图(见下文)-我需要支持两个手势(拖动和放大),以某种方式在这个控制。视图是一个knob和拖动修改的值,放大被认为是修改旋钮的精度。
我尝试了以下几点:
drag.simultanously(with:magnification)做了一个手势,这有点管用,但问题似乎是,当一根手指被提起时,MagnificationGesture还没有结束,因此拖放不会继续--它也永远不会得到.onEnded调用。(我不知道为什么-我会认为这是个窃听器?)其效果是一种相当奇怪的体验,当用户期望改变值时,旋钮仍在放大。drag.onChange的.gesture(drag).gesture(magnification),它从不调用drag.onChange块,但出于某种原因只调用了.onEnded。实际上,拖动并不是work...drag.exclusively(before:magnification)与放大、永不结束和传回拖动两者的结合。magnification手势放置在周围的VStack上,并将拖动手势保留在内部Path视图中,但不知怎么的,这似乎也会导致与drag.simultanously(with:magnification)在内部区域的结果相同。我还没有弄清楚如何防止拖动手势在内部视图上传播并与magnification结合。我将非常感谢反馈,因为我的想法,至少在目前.
struct VirtualKnobView<Content:View>: View {
init(model:VirtualKnobModel, contentSize:CGSize, @ViewBuilder _ contentView:()-> Content ){
self.model = model
self.contentSize = contentSize
self.contentView = contentView()
}
init(contentSize:CGSize, @ViewBuilder _ contentView:()-> Content){
self.model = VirtualKnobModel(inner: 0.7, outer: 0.8, ext: 0.05, angle: 30.0)
self.contentSize = contentSize
self.contentView = contentView()
}
@ObservedObject var model:VirtualKnobModel
@State var lastMagnitude:CGFloat = 1.0
@State var isDragging:Bool = false
var contentSize:CGSize
var contentView:Content
var body: some View {
let size = model.calclulateSize(for: contentSize)
let drag = DragGesture(minimumDistance: 0)
.onChanged({ state in
print ("Drag Changed")
let point = state.location
let refPoint = CGPoint(x: (point.x - size/2)/size,
y: (point.y - size/2)/size)
model.setTouchPoint(point: refPoint)
})
.onEnded({ _ in
print ("Drag ended")
model.reset()
})
let magnification = MagnificationGesture()
.onChanged({ (magnitude:CGFloat) in
print ("Magnification changed")
let delta = magnitude / lastMagnitude
lastMagnitude = magnitude
let angle = model.clickAngle
print ("Magnitude: \(magnitude)")
let magnified = angle * delta
if magnified >= model.minClick && magnified <= model.maxClick {
model.clickAngle = magnified
}
})
.onEnded({ _ in
print("Magnification ended")
lastMagnitude = 1.0
model.reset()
})
let scaler = CGAffineTransform(scaleX: size, y: size)
let gesture = magnification.simultaneously(with: drag)
ZStack {
HStack {
Spacer()
VStack{
Spacer()
Path { path in
model.segmentList.forEach { segment in
let inner = segment.inner
let outer = segment.outer
let innerScaled = inner.applying(scaler)
let outerScaled = outer.applying(scaler)
path.move(to: innerScaled)
path.addLine(to: outerScaled)
}
}
.stroke(model.strokeColor, lineWidth: model.lineWidth)
.background(Color.black)
.frame(width: size, height: size)
Spacer()
}
Spacer()
}
.background(Color.black)
.gesture(gesture)
HStack {
Spacer()
VStack{
Spacer()
contentView
.frame(width: contentSize.width,
height: contentSize.height,
alignment: .center)
Spacer()
}
Spacer()
}
}
}
}发布于 2020-12-01 18:55:32
以下是我今天得到的解决方案:
,
,
我没有办法实现我在UiKit上的行为,在这种情况下,夹点和拖动是同时工作的。
如果你碰到路-请告诉我。
有趣的细节:我认为手势只适用于不透明的像素。所以每件事都需要有背景。无法将手势附加到颜色(.clear)或任何不显示的东西上。这让我对路径视图感到有些头疼,因为它只会触发路径实际上画了什么东西的手势。
struct VirtualKnobView<Content:View>: View {
init(model:VirtualKnobModel, contentSize:CGSize, @ViewBuilder _ contentView:()-> Content ){
self.model = model
self.contentSize = contentSize
self.contentView = contentView()
}
init(contentSize:CGSize, @ViewBuilder _ contentView:()-> Content){
self.model = VirtualKnobModel(inner: 0.7, outer: 0.8, ext: 0.05, angle: 30.0)
self.contentSize = contentSize
self.contentView = contentView()
}
@ObservedObject var model:VirtualKnobModel
@State var lastMagnitude:CGFloat = 1.0
@State var isDragging:Bool = false
var contentSize:CGSize
var contentView:Content
// The bgcolor is needed for the views to receive gestures.
let bgColor = Color(UIColor.black.withAlphaComponent(0.001))
var body: some View {
let size = model.calclulateSize(for: contentSize)
let drag = DragGesture(minimumDistance: 0)
.onChanged({ state in
let point = state.location
let refPoint = CGPoint(x: (point.x - size/2)/size,
y: (point.y - size/2)/size)
model.setTouchPoint(point: refPoint)
})
.onEnded({ _ in
model.reset()
})
let magnification = MagnificationGesture()
.onChanged({ (magnitude:CGFloat) in
let delta = magnitude / lastMagnitude
lastMagnitude = magnitude
let angle = model.clickAngle
let magnified = angle * delta
if magnified >= model.minClick && magnified <= model.maxClick {
model.clickAngle = magnified
}
})
.onEnded({ _ in
lastMagnitude = 1.0
model.reset()
})
let scaler = CGAffineTransform(scaleX: size, y: size)
ZStack {
HStack(spacing:0) {
Rectangle()
.foregroundColor(bgColor)
.gesture(magnification)
VStack(spacing:0){
Rectangle()
.foregroundColor(bgColor)
Path { path in
model.segmentList.forEach { segment in
let inner = segment.inner
let outer = segment.outer
let innerScaled = inner.applying(scaler)
let outerScaled = outer.applying(scaler)
path.move(to: innerScaled)
path.addLine(to: outerScaled)
}
}
.stroke(model.strokeColor, lineWidth: model.lineWidth)
.foregroundColor(bgColor)
.gesture(drag)
.frame(width: size, height: size)
Rectangle()
.foregroundColor(bgColor)
}
Rectangle()
.foregroundColor(bgColor)
.gesture(magnification)
}
HStack {
Spacer()
VStack{
Spacer()
contentView
.frame(width: contentSize.width,
height: contentSize.height,
alignment: .center)
Spacer()
}
Spacer()
}
}
}
}https://stackoverflow.com/questions/65093068
复制相似问题