ios - 带有 SwiftUI 的旋钮
问题描述
所以我试图用旋钮复制普通的 SwiftUI 滑块功能。我已将 UI 编码并运行,当前连接到标准 SwiftUI 滑块以旋转它。
现在我需要添加其余的滑块功能(即$value、range、stride)和触摸功能(即上下左右拖动时旋钮旋转)。老实说,我迷失了做到这一点的最佳方式。任何帮助是极大的赞赏。
以下是主文件,该项目可以在Github Slider Project上找到
//
// FKKnob.swift
//
// Created by Brent Brinkley on 3/7/21.
//
import SwiftUI
struct FKKnob: View {
// Set the color for outer ring and inner dash
let color: Color
// Minimum appearance value:
let circleMin: CGFloat = 0.0
// Maximum appearance value
let circleMax: CGFloat = 0.9
// Because our circle is missing a chunk of degrees we have to account
// for this adjustment
let circOffsetAmnt: CGFloat = 1 / 0.09
// Offset needed to align knob properly
let knobOffset: Angle = .degrees(110)
// calculate the our circle's mid point
var cirMidPoint: CGFloat {
0.4 * circOffsetAmnt
}
// User modfiable control value
@State var value: CGFloat = 0.0
var body: some View {
VStack {
ZStack {
// MARK: - Knob with dashline
Knob(color: color)
.rotationEffect(
// Currently controlled by slider
.degrees(max(0, Double(360 * value )))
)
.gesture(DragGesture(minimumDistance: 0)
.onChanged({ value in
// Need help here setting amount based on x and y touch drag
}))
// MARK: - Greyed Out Ring
Circle()
.trim(from: circleMin, to: circleMax)
.stroke(Color.gray ,style: StrokeStyle(lineWidth: 6, lineCap: .round, dash: [0.5,8], dashPhase: 20))
.frame(width: 100, height: 100)
// MARK: - Colored ring inidicating change
Circle()
.trim(from: circleMin, to: value)
.stroke(color ,style: StrokeStyle(lineWidth: 6, lineCap: .round, dash: [0.5,8], dashPhase: 20))
.frame(width: 100, height: 100)
}
.rotationEffect(knobOffset)
Text("\(value * circOffsetAmnt, specifier: "%.0f")")
Slider(value: $value, in: circleMin...circleMax)
.frame(width: 300)
.accentColor(.orange)
}
}
}
struct DashedCircle_Previews: PreviewProvider {
static var previews: some View {
FKKnob(color: Color.orange)
}
}
解决方案
这是我在我的一个项目中使用的版本。
当拖动开始时,它会设置一个初始值(存储在 中startDragValue
)。这是因为您总是希望值的修改基于您开始时的旋钮值。
然后,我决定只更改基于 y 轴的值。理由是这样的:可以根据从 x1, y1 到 x2, y2 的绝对距离进行更改,但是在尝试获取负值时会遇到问题。例如,右上象限将是一个整体增加可能是有道理的——但是左上象限呢——它会导致积极的变化(因为 y 轴的变化)还是消极的(因为 x轴)?
如果您决定走 x,y 更改的路线,此方法仍然可以帮助您进行设置。
struct ContentView: View {
@State var value : Double = 0.0
@State private var startDragValue : Double = -1.0
var body: some View {
Text("Knob \(value)")
.gesture(DragGesture(minimumDistance: 0)
.onEnded({ _ in
startDragValue = -1.0
})
.onChanged { dragValue in
let diff = dragValue.startLocation.y - dragValue.location.y
if startDragValue == -1 {
startDragValue = value
}
let newValue = startDragValue + Double(diff)
value = newValue < 0 ? 0 : newValue > 100 ? 100 : newValue
})
}
}
我的滑块基于控件向上或向下 100pt 的值,但您显然也可以根据自己的喜好更改这些值。
就范围而言,我建议始终让旋钮从 0.0 变为 1.0,然后再对值进行插值。
推荐阅读
- python - 在 AWS 上运行 Celery
- python - Django Migrate 命令抛出 ORA-00955 错误
- python - 如何在不使用排序功能的情况下对python中的1000万个数字进行排序?
- java - 如何访问在 Java 中用作对象属性的数组?
- ios - 无法以编程方式设置 UILabel/UITextView 的高度
- .net - System.DirectoryServices.AccountManagement 正在查询不再生产的 DC
- javascript - 承诺抛出错误,因为它无法访问它
- firebase - firebase 没有给我我需要的权限
- jquery - 如何在引导程序 4 的一行中循环 4 列?
- python - 电子商务网站如何与ERP系统集成?