MyProgressBar2 📦
我自己設計的進度條 (不包含標題的部分),可設定內距 (padding)、外距 (margin) 與進度條高度。
Last updated
我自己設計的進度條 (不包含標題的部分),可設定內距 (padding)、外距 (margin) 與進度條高度。
Last updated
import SwiftUI
/// ⭐️ `NeuProgressBar2` 的「進度條」部分
public struct MyProgressBar2<Bar: View>: View {
let height : CGFloat // 進度條高度
let padding: CGFloat // 進度條與凹槽邊緣的間距
let margin : CGFloat // 凹槽上下邊緣與外界的間距
let bar : Bar // 進度條的樣式
@Binding var percent: CGFloat // 0.0 ~ 1.0
public init(
_ percent: Binding<CGFloat>,
height : CGFloat = 10,
padding : CGFloat = 2,
margin : CGFloat = 0,
@ViewBuilder bar: () -> Bar // ⭐️ @ViewBuilder closure
) {
self._percent = percent // ⭐️ 傳進 @Binding 變數
self.height = height
self.padding = padding
self.margin = margin
self.bar = bar()
}
public var body: some View {
let h = height
let p = padding
let m = margin
// ⭐️ 為了計算進度條「著色部分」的寬度,使用 `GeometryReader`
return GeometryReader { geometry in
ZStack(alignment: .leading) {
// 凹槽
Capsule()
.frame(height: h + 2 * p) // ⭐️ 定義凹槽的「高度」
.foregroundColor(Neu.color.cardBackground)
// 凹槽漸層效果 (groove gradient)
.overlay(Neu.progressBarGroove.opacity(0.7)) // ⭐️ 讓背景再透過來一些
.clipShape(Capsule())
// 進度條
self.bar // ⭐️ 進度條「樣式」
.frame(height: h) // ⭐️ 進度條「高度」
.mask( // ⭐️ 將進度條依「下面的形狀」剪下來
Capsule() // ⭐️ 進度條「形狀」
// ⭐️ 計算進度條「後面空白部分的寬度」
.padding(.trailing, (geometry.size.width - 2 * p) * (1 - self.percent))
// ⭐️ 進度條前後各再扣掉一個 padding
.padding(.horizontal, p)
) // mask
.shadow(color: Neu.color.text.opacity(0.7), radius: 2, x: 0, y: 1)
} // ZStack
}// container (GeometryReader)
.frame(height: h + 2 * p + 2 * m) // ⭐️ 計算「總高度」
}
}
// ⭐️ 給進度條「預設樣式」
extension MyProgressBar2 where Bar == LinearGradient {
public init(
_ percent: Binding<CGFloat>,
height : CGFloat = 10,
padding : CGFloat = 2,
margin : CGFloat = 0
) {
self._percent = percent // ⭐️ 傳進 @Binding 變數的方式
self.height = height
self.padding = padding
self.margin = margin
// ⭐️ 給進度條「預設樣式」
self.bar = Gradient.right(Color.yellow.opacity(0.8), .red) as! Bar
}
}