SwiftUI中的多组件选择器(UIPickerView)
我正在尝试向SwiftUI应用程序添加一个三组件选择器(UIPickerView)(在传统的UIKit应用程序中,数据源将从SwiftUI中的多组件选择器(UIPickerView),swift,uipickerview,picker,swiftui,Swift,Uipickerview,Picker,Swiftui,我正在尝试向SwiftUI应用程序添加一个三组件选择器(UIPickerView)(在传统的UIKit应用程序中,数据源将从numberOfComponents方法返回3),但我在任何地方都找不到这样的示例 我尝试添加一个由三个单组件选择器组成的HStack,但是如果它们都是一个选择器的一部分,那么前景就不一样了 在纯SwiftUI中更新答案-在本例中,数据类型为String 在Xcode 11.1上测试-在以前的版本上可能无法工作 struct MultiPicker:视图{ typealia
numberOfComponents
方法返回3
),但我在任何地方都找不到这样的示例
我尝试添加一个由三个单组件选择器组成的HStack,但是如果它们都是一个选择器的一部分,那么前景就不一样了 在纯
SwiftUI
中更新答案-在本例中,数据类型为String
在Xcode 11.1上测试-在以前的版本上可能无法工作
struct MultiPicker:视图{
typealias标签=字符串
typealias条目=字符串
let数据:[(标签,[条目]])]
@绑定变量选择:[条目]
var body:一些观点{
GeometryReader{中的几何体
HStack{
ForEach(0..这不是很优雅,但它不涉及移植任何UIKit东西。我知道你在回答中提到透视图是不正确的,但这里的几何图形可能修复了这一点
GeometryReader { geometry in
HStack
{
Picker(selection: self.$selection, label: Text(""))
{
ForEach(0 ..< self.data1.count)
{
Text(self.data1[$0])
.color(Color.white)
.tag($0)
}
}
.pickerStyle(.wheel)
.fixedSize(horizontal: true, vertical: true)
.frame(width: geometry.size.width / 2, height: geometry.size.height, alignment: .center)
Picker(selection: self.$selection2, label: Text(""))
{
ForEach(0 ..< self.data2.count)
{
Text(self.data2[$0])
.color(Color.white)
.tag($0)
}
}
.pickerStyle(.wheel)
.fixedSize(horizontal: true, vertical: true)
.frame(width: geometry.size.width / 2, height: geometry.size.height, alignment: .center)
}
}
GeometryReader{geometry中的几何体
HStack
{
选择器(选择:self.$selection,标签:Text(“”))
{
ForEach(0..
使用几何图形和固定大小,如图所示,两个选择器整齐地占据了屏幕的一半宽度。现在,您只需要处理来自两个不同状态变量的选择,而不是一个,但我更喜欢这种方式,因为它将所有内容都保存在swift UI中克尔:
import SwiftUI
struct PickerView: UIViewRepresentable {
var data: [[String]]
@Binding var selections: [Int]
//makeCoordinator()
func makeCoordinator() -> PickerView.Coordinator {
Coordinator(self)
}
//makeUIView(context:)
func makeUIView(context: UIViewRepresentableContext<PickerView>) -> UIPickerView {
let picker = UIPickerView(frame: .zero)
picker.dataSource = context.coordinator
picker.delegate = context.coordinator
return picker
}
//updateUIView(_:context:)
func updateUIView(_ view: UIPickerView, context: UIViewRepresentableContext<PickerView>) {
for i in 0...(self.selections.count - 1) {
view.selectRow(self.selections[i], inComponent: i, animated: false)
}
}
class Coordinator: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
var parent: PickerView
//init(_:)
init(_ pickerView: PickerView) {
self.parent = pickerView
}
//numberOfComponents(in:)
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return self.parent.data.count
}
//pickerView(_:numberOfRowsInComponent:)
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return self.parent.data[component].count
}
//pickerView(_:titleForRow:forComponent:)
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return self.parent.data[component][row]
}
//pickerView(_:didSelectRow:inComponent:)
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.parent.selections[component] = row
}
}
}
import SwiftUI
struct ContentView: View {
private let data: [[String]] = [
Array(0...10).map { "\($0)" },
Array(20...40).map { "\($0)" },
Array(100...200).map { "\($0)" }
]
@State private var selections: [Int] = [5, 10, 50]
var body: some View {
VStack {
PickerView(data: self.data, selections: self.$selections)
Text("\(self.data[0][self.selections[0]]) \(self.data[1][self.selections[1]]) \(self.data[2][self.selections[2]])")
} //VStack
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
导入快捷界面
结构PickerView:UIViewRepresentable{
变量数据:[[String]]
@绑定变量选择:[Int]
//makeCoordinator()
func makeCoordinator()->PickerView.Coordinator{
协调员(自我)
}
//makeUIView(上下文:)
func makeUIView(上下文:UIViewRepresentableContext)->UIPickerView{
让picker=UIPickerView(帧:.0)
picker.dataSource=context.coordinator
picker.delegate=context.coordinator
回程选择器
}
//updateUIView(uIf:上下文:)
func updateUI视图(view:UIPickerView,context:UIViewRepresentableContext){
对于0中的i…(self.selections.count-1){
view.selectRow(self.selections[i],不完整:i,动画:false)
}
}
类协调器:NSObject、UIPickerViewDataSource、UIPickerViewDelegate{
变量父项:PickerView
//init(389;:)
init(pickerView:pickerView){
self.parent=pickerView
}
//部件数量(单位:)
func numberOfComponents(在pickerView:UIPickerView中)->Int{
返回self.parent.data.count
}
//pickerView(uuOfRowsInComponent:)
func pickerView(pickerView:UIPickerView,numberOfRowsInComponent:Int)->Int{
返回self.parent.data[component].count
}
//pickerView(uu:titleForRow:forComponent:)
func pickerView(pickerView:UIPickerView,titleForRow行:Int,forComponent组件:Int)->String{
返回self.parent.data[组件][行]
}
//pickerView(u2;:didSelectRow:不完整:)
func pickerView(pickerView:UIPickerView,didSelectRow行:Int,不完整组件:Int){
self.parent.selections[组件]=行
}
}
}
导入快捷键
结构ContentView:View{
私有let数据:[[String]]=[
数组(0…10).map{“\($0)”},
数组(20…40).map{“\($0)”},
数组(100…200).map{“\($0)”}
]
@国家私有变量选择:[Int]=[5,10,50]
var body:一些观点{
VStack{
PickerView(数据:self.data,选择:self.$selections)
文本(\(self.data[0][self.selections[0]])\(self.data[1][self.selections[1]])\(self.data[2][self.selections[2]]))
}//VStack
}
}
结构内容视图\u预览:PreviewProvider{
静态var预览:一些视图{
ContentView()
}
}
即使使用.clipped()
,底层选取器也不会收缩,并且倾向于与其他选取器重叠。我成功剪裁底层选取器视图的唯一方法是将.mask(Rectangle())
添加到父容器中。不要问为什么,我不知道
带有2个选择器的工作示例(小时和分钟):
GeometryReader{geometry中的几何体
HStack(间距:0){
选择器(“,选择:self.$hoursIndex){
ForEach(0..我非常喜欢woko的答案,但最终结果在视觉上有点不理想。元素感觉有点间隔,所以我将geometry.size.width乘数从2更改为5,并在选择器的两侧添加了间隔符。(我还包括了woko答案中缺失的hoursIndex和mintuesIndex变量。)
以下是在iPhone 12 Pro Max模拟器上使用Xcode 12在iOS 14上进行的测试
struct TimerView: View {
@State private var hours = Calendar.current.component(.hour, from: Date())
@State private var minutes = Calendar.current.component(.minute, from: Date())
var body: some View {
TimeEditPicker(selectedHour: $hours, selectedMinute: $minutes)
}
}
struct TimeEditPicker: View {
@Binding var selectedHour: Int
@Binding var selectedMinute: Int
var body: some View {
GeometryReader { geometry in
HStack(spacing: 0) {
Spacer()
Picker("", selection: self.$selectedHour) {
ForEach(0..<24) {
Text(String($0)).tag($0)
}
}
.labelsHidden()
.fixedSize(horizontal: true, vertical: true)
.frame(width: geometry.size.width / 5, height: 160)
.clipped()
Picker("", selection: self.$selectedMinute) {
ForEach(0..<60) {
Text(String($0)).tag($0)
}
}
.labelsHidden()
.fixedSize(horizontal: true, vertical: true)
.frame(width: geometry.size.width / 5, height: 160)
.clipped()
Spacer()
}
}
.frame(height: 160)
.mask(Rectangle())
}
}
struct TimerView:视图{
@State private var hours=Calendar.current.component(.hour,from:Date())
@状态私有变量分钟数=Calendar.current.component(