1

有没有办法在带有 SegementedPickerStyle 的 SwiftUI Picker 中创建多行标签。我基本上想创建以下内容:

目标视图

但是我还没有找到一种方法来创建带有多行标签的 Picker。有没有办法用标准的 SwiftUI 控件来做到这一点?根据我的研究,即使在 UIKit 中,这也是一个问题。

4

1 回答 1

1

系统控件只是默认控件 - 我们始终可以使用我们需要的任何参数来实现我们自己的控件。

这是如何使用所需的任何单元格内容实现自定义选择器的简化演示。

注意:所有常量和参数都可以分离成独立的配置结构体作为样式等使用。

使用 Xcode 13.2 / iOS 15.2

演示

struct TestMyPicker: View {

    @State private var selection: Int?
    let data = [1, 2, 3, 4]
    var body: some View {
        MyPicker(data: data, selection: $selection) { item in
            VStack {
                Text("H\(item)")
                Text("Sub \(item)")
            }.padding(.horizontal, 12)
        }
    }
}

extension Int: Identifiable {      // just for testing purpose
    public var id: Int { self }
}


struct MyPicker<Cell, Data>: View where Cell: View, Data: RandomAccessCollection, Data.Element: Identifiable {
    let data: Data
    @Binding var selection: Data.Element?
    @ViewBuilder let cell: (Data.Element) -> Cell
    @Namespace private var ns

    var body: some View {
        HStack(spacing: 0) {
            ForEach(data) { item in
                cell(item)
                    .foregroundColor(.white)
                    .padding(.horizontal, 8)
                    .overlay(
                        Group {
                            if selection?.id == item.id {
                                RoundedRectangle(cornerRadius: 8).fill(Color.white)
                                    .opacity(0.2)
                                    .matchedGeometryEffect(id: "Marker", in: ns)
                            }
                        }
                    )
                    .onTapGesture {
                        if selection?.id == item.id {
                            selection = nil
                        } else {
                            selection = item
                        }
                    }
            }
        }
        .animation(.linear(duration: 0.25), value: selection?.id)
        .fixedSize(horizontal: false, vertical: true)
        .padding(2)
        .background(RoundedRectangle(cornerRadius: 8).fill(Color.gray))
    }
}
于 2022-01-24T13:28:01.427 回答