我有一个滑块,我想停止旋转后360度。我的目标是,一旦用户360度点击,我将为他们显示一个自定义文本选项。
我现在遇到的问题是它停在我的指定值(在这种情况下,我只是设置滑块停止在200),但发生的事情是它过去的指定值。例如,它跳到203、259等。它没有精确地停在值上。
任何建议将是伟大的!
struct CaloriesCircularSelector: View {
@State var calorieValue: CGFloat = 0.0
@State var angleValue: CGFloat = 0.0
@State private var isDragging = false
@State private var stopGesture = false
@State var prevCalorieValue: CGFloat = 0.0
@State var movingForward = false
@State var movingBackwards = false
let config = ConfigCircular(
minimumValue: 0.0,
maximumValue: 999.0,
totalValue: 1000.0,
knobRadius: 15.0,
radius: 125.0)
var body: some View {
ZStack {
Circle()
.fill(.red)
.frame(width: config.radius * 2, height: config.radius * 2)
.scaleEffect(1.2)
Circle()
.trim(from: 0.0, to: calorieValue/config.totalValue)
.stroke(Color.blue, lineWidth: 15)
.frame(width: config.radius * 2, height: config.radius * 2)
.rotationEffect(.degrees(-90))
Circle()
.fill(isDragging ? Color.red : Color.blue)
.frame(width: config.knobRadius * 2, height: config.knobRadius * 2)
.padding(10)
.offset(y: -config.radius)
.rotationEffect(Angle.degrees(Double(angleValue)))
.gesture(
DragGesture(minimumDistance: 0.2)
.onChanged { value in
isDragging = true // Set isDragging to true when the user starts dragging
}
.onEnded { _ in
isDragging = false // Set isDragging to false when the user stops dragging
}
)
Text("\(String.init(format: "%.0f", calorieValue)) cals")
.font(.system(size: 50))
.foregroundColor(.white)
}
.onChange(of: self.calorieValue) { newValue in
// Check if the user is moving forward or backward, can't find a use for this right now
if newValue > prevCalorieValue {
movingForward = true
movingBackwards = false
print("Moving forward")
} else if newValue < prevCalorieValue {
movingForward = false
movingBackwards = true
print("Moving backward")
}
prevCalorieValue = newValue
}
}
private func change(location: CGPoint) {
// creating vector from location point
let vector = CGVector(dx: location.x, dy: location.y)
let angle = atan2(vector.dy - (config.knobRadius + 10), vector.dx - (config.knobRadius + 10)) + .pi/2.0
let fixedAngle = angle < 0.0 ? angle + 2.0 * .pi : angle
let value = fixedAngle / (2.0 * .pi) * config.totalValue
if value >= config.minimumValue && value <= config.maximumValue {
if angleValue >= 200 && value > calorieValue {
// stop increasing the calorie value if it is already 200 or greater
return
}
calorieValue = value
angleValue = fixedAngle * 180 / .pi
}
}
}
struct ConfigCircular {
let minimumValue: CGFloat
let maximumValue: CGFloat
let totalValue: CGFloat
let knobRadius: CGFloat
let radius: CGFloat
}
1条答案
按热度按时间t3psigkw1#
您必须使用
.onChange
观察calorieValue
中的更改。下面是如何做到这一点。请阅读代码中的注解,因为它们将帮助您并指导您完成它。还要注意的是,这段代码并不完美,因为当你在
textfield
中输入任何值时,如果值低于360,它就会显示滑块。因为我不确定最终的行为,所以这是留给你去弄清楚你希望它是什么样子的。还请注意,如果我是你,我会打破我的看法成subviews例如我会做
最后,您可能需要添加一些动画。您可以在
.onChange
内部使用withAnimation()
执行此操作,也可以直接在要设置动画的视图上调用.animation(.linear, value: self.showSlider)
。