如何解决SwiftUI:在最小值和最大值之间更改值的放大手势
我想做与滑块相同的事情:
@State itemSize: CGFloat = 55.60
....
Text("ItemSize: \(itemSize)")
Slider(value: $itemSize,in: 45...120)
但有放大手势。
我为此创建了修饰符:
import SwiftUI
@available(OSX 11.0,*)
public extension View {
func magnificationZoomer(value: Binding<CGFloat>,min: CGFloat,max: CGFloat) -> some View
{
self.modifier( MagnificationZoomerMod(minZoom: min,maxZoom: max,zoom: value) )
}
}
@available(OSX 11.0,*)
public struct MagnificationZoomerMod: ViewModifier {
let minZoom: CGFloat
let maxZoom: CGFloat
@Binding var zoom: CGFloat
public func body (content: Content) -> some View
{
content
.gesture(
MagnificationGesture()
.onChanged() { val in
let magnification = (val - 1) * 2.2
print("magnification = \(magnification)")
zoom = max(min(zoom + magnification,maxZoom),minZoom)
}
)
}
}
使用示例:
@State itemSize: CGFloat = 55.60
var body: some View {
HStack {
vstack {
Text("ItemSize: \(itemSize)")
Slider(value: $itemSize,in: 45...120)
}
}
.frame(width: 500,height: 500)
.magnificationZoomer(value: $itemSize,min: 45,max: 120)
}
但是我对这段代码有一些问题:
- 它以一种奇怪的方式滑动值——有时以正确的速度,它不会改变它
- 使用一段时间后,它完全停止工作
我做错了什么?
解决方法
它几乎就像魔术一样,您可以通过 滑块 或您的手指在 MagnificationGesture 上更改圆形的大小/比例,两者一起工作并一起下沉。 >
import SwiftUI
struct ContentView: View {
let minZoom: CGFloat = 0.5
let maxZoom: CGFloat = 1.5
@State private var scale: CGFloat = 1.0
@State private var lastScale: CGFloat = 1.0
@State private var magnitudeIsActive: Bool = Bool()
var body: some View {
ZStack {
Circle()
.fill(Color.red)
.scaleEffect(scale)
.gesture(magnificationGesture.simultaneously(with: dragGesture)) // <<: Here: adding unneeded dragGesture! on macOS! no need on iOS!
VStack {
Spacer()
Text("scale: " + scale.rounded)
HStack {
Button("min") { scale = minZoom; lastScale = scale }
Slider(value: Binding.init(get: { () -> CGFloat in return scale },set: { (newValue) in if !magnitudeIsActive { scale = newValue; lastScale = newValue } }),in: minZoom...maxZoom)
Button("max") { scale = maxZoom; lastScale = scale }
}
}
}
.padding()
.compositingGroup()
.shadow(radius: 10.0)
.animation(Animation.easeInOut(duration: 0.2),value: scale)
}
var magnificationGesture: some Gesture {
MagnificationGesture(minimumScaleDelta: 0.0)
.onChanged { value in
if !magnitudeIsActive { magnitudeIsActive = true }
let magnification = (lastScale + value.magnitude - 1.0)
if (magnification >= minZoom && magnification <= maxZoom) {
scale = magnification
}
else if (magnification < minZoom) {
scale = minZoom
}
else if (magnification > maxZoom) {
scale = maxZoom
}
}
.onEnded { value in
let magnification = (lastScale + value.magnitude - 1.0)
if (magnification >= minZoom && magnification <= maxZoom) {
lastScale = magnification
}
else if (magnification < minZoom) {
lastScale = minZoom
}
else if (magnification > maxZoom) {
lastScale = maxZoom
}
scale = lastScale
magnitudeIsActive = false
}
}
var dragGesture: some Gesture { DragGesture(minimumDistance: 0.0) } // <<: Here: this Extra un-needed gesture would keep magnificationGesture alive! And Stop it to get killed in macOS! We do not need this line of code in iOS!
}
extension CGFloat { var rounded: String { get { return String(Double(self*100.0).rounded()/100.0) } } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。