我还没有完成它,因为出现了其他东西,但这是我的(未完成的实现 SegmentedPicker 的尝试):
struct SegmentedPickerElementView<Content>: View where Content : View {
@Binding var selectedElement: Int
let content: () -> Content
@inlinable init(_ selectedElement: Binding<Int>, @ViewBuilder content: @escaping () -> Content) {
self._selectedElement = selectedElement
self.content = content
}
var body: some View {
GeometryReader { proxy in
self.content()
.fixedSize(horizontal: true, vertical: true)
.frame(minWidth: proxy.size.width, minHeight: proxy.size.height)
.contentShape(Rectangle())
}
}
}
struct SegmentedPickerView: View {
@Environment (\.colorScheme) var colorScheme: ColorScheme
var elements: [(id: Int, view: AnyView)]
@Binding var selectedElement: Int
@State var internalSelectedElement: Int = 0
private var width: CGFloat = 620
private var height: CGFloat = 200
private var cornerRadius: CGFloat = 20
private var factor: CGFloat = 0.95
private var color = Color(UIColor.systemGray)
private var selectedColor = Color(UIColor.systemGray2)
init(_ selectedElement: Binding<Int>) {
self._selectedElement = selectedElement
self.elements = [
(id: 0, view: AnyView(SegmentedPickerElementView(selectedElement) {
Text("4").font(.system(.title))
})),
(id: 1, view: AnyView(SegmentedPickerElementView(selectedElement) {
Text("5").font(.system(.title))
})),
(id: 2, view: AnyView(SegmentedPickerElementView(selectedElement) {
Text("9").font(.system(.title))
})),
(id: 3, view: AnyView(SegmentedPickerElementView(selectedElement) {
Text("13").font(.system(.title))
})),
(id: 4, view: AnyView(SegmentedPickerElementView(selectedElement) {
Text("13").font(.system(.title))
})),
(id: 5, view: AnyView(SegmentedPickerElementView(selectedElement) {
Text("13").font(.system(.title))
})),
]
self.internalSelectedElement = selectedElement.wrappedValue
}
func calcXPosition() -> CGFloat {
var pos = CGFloat(-self.width * self.factor / 2.4)
pos += CGFloat(self.internalSelectedElement) * self.width * self.factor / CGFloat(self.elements.count)
return pos
}
var body: some View {
ZStack {
Rectangle()
.foregroundColor(self.selectedColor)
.cornerRadius(self.cornerRadius * self.factor)
.frame(width: self.width * self.factor / CGFloat(self.elements.count), height: self.height - self.width * (1 - self.factor))
.offset(x: calcXPosition())
.animation(.easeInOut(duration: 0.2))
HStack(alignment: .center, spacing: 0) {
ForEach(self.elements, id: \.id) { item in
item.view
.gesture(TapGesture().onEnded { _ in
print(item.id)
self.selectedElement = item.id
withAnimation {
self.internalSelectedElement = item.id
}
})
}
}
}
.frame(width: self.width, height: self.height)
.background(self.color)
.cornerRadius(self.cornerRadius)
.padding()
}
}
struct SegmentedPickerView_Previews: PreviewProvider {
static var previews: some View {
SegmentedPickerView(.constant(1))
}
}
我还没有弄清楚2.4的值所在的公式......这取决于元素的数量......她是我学到的:
2 个元素 = 4
3 个元素 = 3
4 个元素 = 2.6666
5 个元素 = 大约2.4
如果你弄清楚了这一点并修复了选择器中内容的对齐方式,它基本上是完全可调节的......你也可以通过 width 和 height 使用 GeometryReader 的洞东西
祝你好运!
P.S.:我会在它完成后更新它,但目前它不是我的第一要务,所以不要指望我这样做。