成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

在 SwiftUI 中創建一個環形 Slider

開發 前端
本文展示了如何定義響應拖動手勢的圓環滑塊控件。可以設置滑塊視圖的大小,并且滑塊按預期工作。可以向控件添加更多參數以設置顏色或圓環內顯示的值的格式。 GitHub 上提供了 Circular Slider 的代碼。

前言

Slider 控件是一種允許用戶從一系列值中選擇一個值的 UI 控件。在 SwiftUI 中,它通常呈現為直線上的拇指選擇器。有時將這種類型的選擇器呈現為一個圓圈,拇指繞著圓周移動可能會更好。本文介紹如何在 SwiftUI 中定義一個環形的 Slider。

初始化環形輪廓

從ZStack中的三個圓環開始。一個灰色的圓環代表滑塊的路徑輪廓,一個淡紅色的圓弧代表沿著圓環的進度,一個圓圈代表當前光標或拇指的位置。將滑塊的范圍設置為0.0到1.0,并硬編碼一個直徑和一個的當前位置進度 - 0.33。

struct CircularSliderView1: View {
let progress = 0.33
let ringDiameter = 300.0

private var rotationAngle: Angle {
return Angle(degrees: (360.0 * progress))
}

var body: some View {
VStack {
ZStack {
Circle()
.stroke(Color(hue: 0.0, saturation: 0.0, brightness: 0.9), lineWidth: 20.0)
Circle()
.trim(from: 0, to: progress)
.stroke(Color(hue: 0.0, saturation: 0.5, brightness: 0.9),
style: StrokeStyle(lineWidth: 20.0, lineCap: .round)
)
.rotationEffect(Angle(degrees: -90))
Circle()
.fill(Color.white)
.frame(width: 21, height: 21)
.offset(y: -ringDiameter / 2.0)
.rotationEffect(rotationAngle)
}
.frame(width: ringDiameter, height: ringDiameter)

Spacer()
}
.padding(80)
}
}

圖片

將進度值和拇指位置綁定

將進度變量更改為狀態[1]變量并添加默認 Slider。這個 Slider 用于修改進度值,并在圓形滑塊上實現足夠的代碼以使拇指和進度弧響應。當前值顯示在環形 Slider 的中心。

struct CircularSliderView2: View {
@State var progress = 0.33
let ringDiameter = 300.0

private var rotationAngle: Angle {
return Angle(degrees: (360.0 * progress))
}

var body: some View {
ZStack {
Color(hue: 0.58, saturation: 0.04, brightness: 1.0)
.edgesIgnoringSafeArea(.all)

VStack {
ZStack {
Circle()
.stroke(Color(hue: 0.0, saturation: 0.0, brightness: 0.9), lineWidth: 20.0)
.overlay() {
Text("\(progress, specifier: "%.1f")")
.font(.system(size: 78, weight: .bold, design:.rounded))
}
Circle()
.trim(from: 0, to: progress)
.stroke(Color(hue: 0.0, saturation: 0.5, brightness: 0.9),
style: StrokeStyle(lineWidth: 20.0, lineCap: .round)
)
.rotationEffect(Angle(degrees: -90))
Circle()
.fill(Color.white)
.shadow(radius: 3)
.frame(width: 21, height: 21)
.offset(y: -ringDiameter / 2.0)
.rotationEffect(rotationAngle)
}
.frame(width: ringDiameter, height: ringDiameter)


VStack {
Text("Progress: \(progress, specifier: "%.1f")")
Slider(value: $progress,
in: 0...1,
minimumValueLabel: Text("0.0"),
maximumValueLabel: Text("1.0")
) {}
}
.padding(.vertical, 40)

Spacer()
}
.padding(.vertical, 40)
.padding()
}
}
}

圖片

添加觸摸手勢

DragGesture[2] 被添加到滑塊圓圈,并且使用臨時文本視圖顯示拖動手勢的當前位置。可以看到 x 和 y 坐標圍繞包含環形  Slider 的位置中心的變化情況。

struct CircularSliderView3: View {
@State var progress = 0.33
let ringDiameter = 300.0

@State var loc = CGPoint(x: 0, y: 0)

private var rotationAngle: Angle {
return Angle(degrees: (360.0 * progress))
}

private func changeAngle(location: CGPoint) {
loc = location
}

var body: some View {
ZStack {
Color(hue: 0.58, saturation: 0.04, brightness: 1.0)
.edgesIgnoringSafeArea(.all)

VStack {
ZStack {
Circle()
.stroke(Color(hue: 0.0, saturation: 0.0, brightness: 0.9), lineWidth: 20.0)
.overlay() {
Text("\(progress, specifier: "%.1f")")
.font(.system(size: 78, weight: .bold, design:.rounded))
}
Circle()
.trim(from: 0, to: progress)
.stroke(Color(hue: 0.0, saturation: 0.5, brightness: 0.9),
style: StrokeStyle(lineWidth: 20.0, lineCap: .round)
)
.rotationEffect(Angle(degrees: -90))
Circle()
.fill(Color.blue)
.shadow(radius: 3)
.frame(width: 21, height: 21)
.offset(y: -ringDiameter / 2.0)
.rotationEffect(rotationAngle)
.gesture(
DragGesture(minimumDistance: 0.0)
.onChanged() { value in
changeAngle(location: value.location)
}
)
}
.frame(width: ringDiameter, height: ringDiameter)

Spacer().frame(height:50)

Text("Location = (\(loc.x, specifier: "%.1f"), \(loc.y, specifier: "%.1f"))")

Spacer()
}
.padding(.vertical, 40)
.padding()
}
}
}

圖片

為不同的坐標值設置滑塊位置

圓形滑塊上有兩個表示進度的值,用于顯示進度弧度的progress值和用于顯示滑塊光標的rotationAngle。應該只有一個屬性來保存滑塊進度。視圖被提取到一個單獨的結構中,該結構具有圓形滑塊上進度的一個綁定值。

滑塊的range的可選參數也是可用的。這需要對進度進行一些調整,以計算已設置的角度以及拇指在圓形滑塊上位置的旋轉角度。另外調用onAppear根據View出現前的進度值計算旋轉角度。

struct CircularSliderView: View {
@Binding var progress: Double

@State private var rotationAngle = Angle(degrees: 0)
private var minValue = 0.0
private var maxValue = 1.0

init(value progress: Binding<Double>, in bounds: ClosedRange<Int> = 0...1) {
self._progress = progress

self.minValue = Double(bounds.first ?? 0)
self.maxValue = Double(bounds.last ?? 1)
self.rotationAngle = Angle(degrees: progressFraction * 360.0)
}

private var progressFraction: Double {
return ((progress - minValue) / (maxValue - minValue))
}

private func changeAngle(location: CGPoint) {
// 為位置創建一個向量(在 iOS 上反轉 y 坐標系統)
let vector = CGVector(dx: location.x, dy: -location.y)

// 計算向量的角度
let angleRadians = atan2(vector.dx, vector.dy)

// 將角度轉換為 0 到 360 的范圍(而不是負角度)
let positiveAngle = angleRadians < 0.0 ? angleRadians + (2.0 * .pi) : angleRadians

// 根據角度更新滑塊進度值
progress = ((positiveAngle / (2.0 * .pi)) * (maxValue - minValue)) + minValue
rotationAngle = Angle(radians: positiveAngle)
}

var body: some View {
GeometryReader { gr in
let radius = (min(gr.size.width, gr.size.height) / 2.0) * 0.9
let sliderWidth = radius * 0.1

VStack(spacing:0) {
ZStack {
Circle()
.stroke(Color(hue: 0.0, saturation: 0.0, brightness: 0.9),
style: StrokeStyle(lineWidth: sliderWidth))
.overlay() {
Text("\(progress, specifier: "%.1f")")
.font(.system(size: radius * 0.7, weight: .bold, design:.rounded))
}
// 取消注釋以顯示刻度線
//Circle()
// .stroke(Color(hue: 0.0, saturation: 0.0, brightness: 0.6),
// style: StrokeStyle(lineWidth: sliderWidth * 0.75,
// dash: [2, (2 * .pi * radius)/24 - 2]))
// .rotationEffect(Angle(degrees: -90))
Circle()
.trim(from: 0, to: progressFraction)
.stroke(Color(hue: 0.0, saturation: 0.5, brightness: 0.9),
style: StrokeStyle(lineWidth: sliderWidth, lineCap: .round)
)
.rotationEffect(Angle(degrees: -90))
Circle()
.fill(Color.white)
.shadow(radius: (sliderWidth * 0.3))
.frame(width: sliderWidth, height: sliderWidth)
.offset(y: -radius)
.rotationEffect(rotationAngle)
.gesture(
DragGesture(minimumDistance: 0.0)
.onChanged() { value in
changeAngle(location: value.location)
}
)
}
.frame(width: radius * 2.0, height: radius * 2.0, alignment: .center)
.padding(radius * 0.1)
}

.onAppear {
self.rotationAngle = Angle(degrees: progressFraction * 360.0)
}
}
}
}

CircularSliderView 的三種不同視圖被添加到View中以測試和演示 Circular Slider 視圖的不同功能。

struct CircularSliderView5: View {
@State var progress1 = 0.75
@State var progress2 = 37.5
@State var progress3 = 7.5

var body: some View {
ZStack {
Color(hue: 0.58, saturation: 0.06, brightness: 1.0)
.edgesIgnoringSafeArea(.all)

VStack {
CircularSliderView(value: $progress1)
.frame(width:250, height: 250)

HStack {
CircularSliderView(value: $progress2, in: 1...10)

CircularSliderView(value: $progress3, in: 0...100)
}

Spacer()
}
.padding()
}
}
}

圖片

總結

本文展示了如何定義響應拖動手勢的圓環滑塊控件。可以設置滑塊視圖的大小,并且滑塊按預期工作。可以向控件添加更多參數以設置顏色或圓環內顯示的值的格式。 GitHub 上提供了 Circular Slider[3] 的代碼。

參考資料

[1]state: https://developer.apple.com/documentation/swiftui/state?。

[2]DragGesture: https://developer.apple.com/documentation/swiftui/draggesture/?。

[3]Circular Slider: https://github.com/SwiftCommunityRes/swift?。

責任編輯:姜華 來源: Swift社區
相關推薦

2022-11-07 08:42:50

iOS 16SwiftUI

2015-08-06 13:44:21

swiftcocoapods

2023-11-03 11:57:04

2024-04-01 08:18:52

CSSHTMLWeb

2022-11-18 09:03:09

SwiftUIiOS16

2020-09-29 07:24:14

Python字典數據

2011-03-10 10:45:47

Azure“Hello Worl

2009-09-22 11:54:42

ibmdwPHP

2022-01-17 09:22:42

SwiftUI App Store開源

2023-12-29 09:01:10

SwiftUI空狀態Product?

2023-11-20 09:55:34

音頻圖表SwiftUI

2011-09-08 10:46:12

Widget

2024-05-06 00:00:00

Android系統通信

2017-02-10 20:00:17

Linux共享目錄命令

2021-01-04 09:12:31

集合變量

2022-11-11 09:01:08

SwiftUI條形圖子視圖

2021-04-14 15:25:39

Linux加密文件保險庫

2017-08-17 14:38:39

JavaAbstract抽象

2022-02-10 22:34:51

對象JVM收集器

2016-03-08 09:52:22

xcode插件開發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一级在线 | 欧美男人亚洲天堂 | 国产一区二区三区在线看 | 久久爱综合| 日本不卡免费新一二三区 | av片免费观看 | www.五月天婷婷.com | 国产精品大片 | 久久一区二区三区电影 | 春色av| 欧美日韩中文字幕在线 | 亚洲精品一 | 一级在线观看 | 午夜合集| 欧美一区二区三区四区视频 | 天堂成人国产精品一区 | www.亚洲一区二区 | 视频一区二区在线观看 | 免费在线播放黄色 | 亚洲午夜视频 | 一区二区免费视频 | 亚洲精品电影网在线观看 | 极品国产视频 | 久久久久久91 | 鲁视频 | 国产精品久久久久久久久久久久 | 国产精品中文在线 | 日本一区二区三区精品视频 | 国产精品久久久久久久久久久久久久 | 九九久久精品 | 国产 欧美 日韩 一区 | 日韩av黄色| 欧美日韩综合一区 | 日韩欧美在线播放 | 国产精品久久久久一区二区 | 羞羞视频在线免费 | 91精品久久久久久久久 | 日本一道本视频 | 中文字幕福利视频 | 国产成人精品999在线观看 | 亚洲一区二区视频在线观看 |