Picker
使用户能够在使用iOS应用程序时在多个选项之间进行选择。在本文中,我们将了解它们的各种类型,并探索它们是如何声明、配置和样式的。和Button
差不多,Picker
是iOS应用中最常用的UI元素之一。
创建一个基本的Picker
首先,让我们创建一个显示硬编码数据列表的Picker
。例如说你最想去旅游的国家:意大利、中国、印度和美国。我们将把Picke
绑定到一个状态变量,并显示选中的值。
上面代码中,我们创建了一个@State
修饰的变量country
,并将其绑定到Picker
组件上,用来记录用户的选择。
另外还需要注意的是,Picker
中的每个Text
都加了tag
修饰符,这个很有必要的,tag
是唯一的,country
变量也是记录这个tag
值,上面的效果图,当选择后,Picker
显示了Text
的内容,而country
变量却显示的是tag
值。如果不加tag
修饰符,Picker
选择后,UI上也没什么变化。
枚举类型配合Picker使用
如果Picker
显示的数据不多,我们可以把要显示的数据定义成枚举,这样代码上更加方便整洁,数据也便于管理。
struct PickerDemo: View {
@State private var country: TravelCountry = .italian
enum TravelCountry: String, CaseIterable, Identifiable {
case italian = "Italian"
case chinese = "Chinese"
case indian = "Indian"
case american = "American"
var id: TravelCountry {
self
}
}
var body: some View {
VStack(spacing: 300) {
Text("Selected country: \(country)")
Picker("Selected country", selection: $country) {
ForEach(TravelCountry.allCases) { country in
Text(country.rawValue)
.tag(country)
}
}
}
}
}
上面代码中定义了一个TravelCountry
枚举,该枚举继承了CaseIterable
和Identifiable
协议,这样就可遍历枚举,同时每个枚举值也都有唯一的id
。
在Picker
中采用ForEach
循环遍历TravelCountry
的所有枚举值,这样数据部分和UI部分就分开管理了。
Picker种类简介
SwiftUI
提供了一些内置的Picker
样式,这些样式决定了Picker
有不同的样子和操作行为,主要的种类有:
DefaultPickerStyle
: 默认样式的选择器,根据平台自动选择合适的样式。
WheelPickerStyle
: 带有滚轮样式的选择器,用户可以通过滚动选择选项。
SegmentedPickerStyle:
分段样式的选择器,以分段控件的形式显示选项。
InlinePickerStyle
: 内联样式的选择器,直接嵌入到视图中。
MenuPickerStyle
: 弹出菜单样式的选择器,以菜单形式显示选项。
设置Picker
样式的时候只需要在Picker
上添加.pickerStyle()
修饰符即可,括号内传入内置的样式。
WheelPickerStyle
WheelPickerStyle
是带有滚轮样式的选择器,用户可以通过滚动选择选项。
.pickerStyle(.wheel)
在上面的代码中特意多加了一些样式,比如foregroundColor
,background
和frame
等,这些都是起作用的。
在ForEach
循环中添加了文字和图片,并分别设置了颜色,如果将foregroundColor
直接设置在HStack上则不起作用。
WheelPickerStyle
类型的Picker
还是比较好设置外观的。
SegmentedPickerStyle
SegmentedPickerStyle
是分段样式的选择器,以分段控件的形式显示选项。
.pickerStyle(.segmented)
上面代码中实现了一个简单的分段选择器,注意看我们给ForEach
中的Text
添加了一些修饰符,但是事实证明,这些修饰符都不起作用,不像WheelPickerStyle
还能设置一些。通过SwiftUI
代码唯一能设置就是整体的背景色,比如上面给Picker
添加的background
颜色。
那么分段选择器就不能设置外观了吗,当然不是,我们可以通过UISegmentedControl.appearance()
设置外观,上面代码中就设置了选中时的背景色,以及文字颜色,通过setTitleTextAttributes
方法,能设置不同状态下的文字的不同样式,比如颜色,字体等等。
不过UISegmentedControl.appearance()
设置外观的一大弊端就是给整个App中用到的所有分段选择器都设置成了统一样式,这点尤其要注意,如果一个App中有不同样式的分段选择器,记得要随时更改UISegmentedControl.appearance()
。
MenuPickerStyle
MenuPickerStyle
是弹出菜单样式的选择器,以菜单形式显示选项。
.pickerStyle(.menu)
上面是一个简单的menu类型Picker
,这里没有设置pickerStyle
,但是它显示的确实menu类型的Picker
,也就是默认就是这个。
我们在ForEach
里面添加了Text
和Image
,也都能显示出来,不过再想给这两个组件添加其他的修饰符都不起作用,一直都是系统默认的黑色,比如上面的代码。
上面给Picker
设置了accentColor
,这个起作用了,Picker
的Label
显示成了红色,但是这个Label
是真难看啊,我给选项加的爱心竟然这也显示一个,改掉他:
这回换了一个带Label
的初始化方法,但是结果很打脸,没起作用。经过一番查阅,很多建议外面再包一层Menu
组件,如下:
这回达到了想要的效果。在Menu
的Label
闭包内设置想要的外观,而Picker
的Label
闭包则是用来显示弹出的menu框顶部的提示文字。看样Picker
组件配合Menu
组件才能显示出想要的menu类型的Picker
。
上面的代码中仍然有一些无效的代码,比如针对Picker
设置font
,foregroundColor
,background
, fontWeight
等等,看样menu类型的Picker
只能采用系统的外观样式。
InlinePickerStyle
InlinePickerStyle
是内联样式的选择器,直接嵌入到视图中。
.pickerStyle(.inline)
通过上面的代码乍一看,Picker
设置font
,foregroundColor
,background
,fontWeight
等等起作用了,不过这好像和WheelPickerStyle
很像啊,我仔细对比了,WheelPickerStyle
每个选项有间隔,而这个没有。
结合上面MenuPickerStyle
的用法,我们修改一下代码:
事实证明,inline
模式的Picker
也需要和Menu
组件一起用效果更好,不过Picker
设置的font
,foregroundColor
,background
, fontWeight
等等就不起作用了。
inline
模式和menu
模式主要区别在于:
1. inline
模式点击后直接弹出了列表项,而menu
模式需要再点击一下列表项的header才能显示列表项。
2. inline
模式下Picker
的Label
闭包失效了。
总结
总之,Picker
是一个强大的工具,可以在你的SwiftUI
应用中收集用户输入。通过为选择器提供选择绑定、标签和要显示的内容,您可以创建各种不同的选择器来满足需要。
不过强大的组件对使用者要求也很高,关于外观设置这块,不同的PickerStyle
还需要不同的设置方法,有些还直接是内定的,不能设置。
本篇文章里的代码有些外观设置修饰符是不起作用的,代码中保留了主要是告诉大家哪些,或者哪一类的设置是无效的。
最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。