Picker

选择器与文本字段一样,需要与属性进行双向绑定,以便它们可以跟踪其值。

Picker(selection: $favoriteState, label: Text("Your name")) {                
	Text("Paul").tag("Paul")                
	Text("Chris").tag("Chris")                
	Text("Mark").tag("Mark")                

参数:label

Picker 必须加到 Form 视图里,label 标签才会显示。另外即使标签文本不可见,它仍然很有用,因为 VoiceOver 在阅读屏幕时会使用它。

// 首先,选择器可以设置 label 文字
Picker(label: Text("喜欢的课程")){ ... }

参数:selection

selection 参数是需要和【状态参数】双向绑定的,以此决定选择器的值是什么

//先要定义状态参数
@State private var favoriteState = 1

//将 selection 参数,双向绑定到状态参数
Picker(selection: $favoriteState){ ... }

参数:闭包

// 选择器后面大括号的闭包,主要是设置选择器的 UI ,视图是什么样的
Picker(selection: $favoriteState, label: Text("喜欢的课程")){
		Text("SwiftUI")
    Text("React")
    Text("SwiftUI")
}

// 选项一般用循环“数组”生成
Picker("How pay?", selection: $paymentType) {
		ForEach(paymentTypes, id: \\.self) {
				Text($0)
		}
}

// 然后需要给闭包的每一项,后面添加 tag 修饰符
Picker(selection: $favoriteState, label: Text("喜欢的课程")){
		Text("SwiftUI").tag(0)
    Text("React").tag(1)
    Text("SwiftUI").tag(2)
}

// tag的值可以是整数,也可以是字符串、布尔值等;它要和前面绑定的状态属性的类型一致,这样才能映射。

tag 选项值的设定

要获取或设置选择器的值,需要将其绑定到变量。 然后将此变量传递到选择器的初始化器中。 然后,您需要做的就是更改此绑定变量的值,以选择您想要在选择器中显示的行。 或者读取绑定变量的值,以查看当前选择的行。

tag 可以是字符串

// 示例:Picker 使用 tag(字符串) 来标识每一项
@State private var selectedName = "Paul"
var body: some View {
        VStack {
            Picker("Your name", selection: $selectedName) {
                Text("Paul").tag("Paul")
                Text("John").tag("John")
                Text("Sarah").tag("Sarah")
            }
            Text("Selected name: \\(selectedName)")
        }
}

tag 可以是数组

例如用于切换排序规则上,选了哪个选项,就更新一个数组类型的状态属性。

@State private var sortOrder = [
        SortDescriptor(\\User.name),
        SortDescriptor(\\User.joinDate),
]

// 用 tag 修饰符,包裹具体选项的值(可以是任何值)。该值与状态属性绑定
Picker("Sort", selection: $sortOrder) {
		Text("Sort by Name")
				.tag([
								SortDescriptor(\\User.name),
                SortDescriptor(\\User.joinDate),
        ])
		Text("Sort by Join Date")
				.tag([
                SortDescriptor(\\User.joinDate),
                SortDescriptor(\\User.name)
        ])
}

在子视图里设置 tag

在子视图代码里设置 tag 值,在父视图中实例化,实例化时再给他赋值。

// 父视图:实例化子视图时传入 name 参数,作为 tag 的值
Picker(selection: $youTuberName, label: Text("")) {
		// 这里不要打tag,因为在子视图里打了
		Row(name: "Sean")
    Row(name: "Chris")
    Row(name: "Mark")
}

// 子视图:加了tag,但是tag的值是未明确的,等待实例化时才能获取填入
struct Row : View {
		// 接受一个参数
    var name: String
    var body: some View {
        return HStack {
            Image(systemName: "person.fill")
                .padding(.trailing)
                .foregroundColor(Color.red)
            Text(name)
        }
				// 在return后打tag
        .tag(name)
    }
}
// 以上例子也可以通过 ForEach 循环创建

// 例如,将选项存储到数组中
var youTubers = ["Sean", "Chris", "Mark", "Scott", "Paul"]

// 第1个参数双向绑定状态参数
Picker(selection: $youTuberName, label: Text("")) {
	// 从数组里进行循环
	ForEach(youTubers, id: \\.self) {
		// 设了个参数是name
		name in            
		Row(name: name)        
}

// 还是在抽出的子视图里加
struct Row : View {
	var name: String    
	var body: some View {        
		HStack {            
			Image(systemName: "person.fill")            
			Text(name)        
		}
		.tag(name)    
	}
}

不设置默认选中项

如果希望不设置默认选中项,可以让状态属性的初始值不等于任何一个tag:

// 例如:让初始值等于 0
@State private var selection = 0

Picker("", selection: $selection) {        
	Text("One").tag(1)
	Text("Two").tag(2)
	Text("Three").tag(3)
}

自定义 Picker 样式

Picker 带有许多替代样式,具体取决于您希望事物的行为方式。

1. 菜单样式

菜单样式,是选择器的默认样式。其表现是直接在当前页面展开一个小浮层,显示所有选项。

2. 导航链接样式

// 将 .pickerStyle(.navigationLink) 修饰符添加到选择器
Picker(selection: $favoriteState, label: Text("")) { ... }
	.pickerStyle(.navigationLink)

// 这时会在右边看到一个灰色箭头。但整行将显示为灰色,且点击时不会显示任何内容
// 需要做的是提供一个包裹选择器的 NavigationStack,它会做两件事:在顶部提供一些空间来放置标题,并且点击后还会导航到新视图中
NavigationStack {
    Form {
        Picker(selection: $favoriteState, label: Text("")) { ... }
			    .pickerStyle(.navigationLink)
    }
}

3. 分段选择器样式

分段式样式适用于有限选项。 为了获取或设置所选段,您需要将其绑定到变量。 此变量被传递到分段控件(Picker)的初始化器中。 Segmented 是收缩型视图。

//例如:

//1. 定义一个数组储存选项
let tipPercentages = [10, 15, 20, 25, 0]
@State private var tipPercentage = 10

//2. 双向绑定之前定义的选择的值,并通过循环读取选项构建UI
Picker("Tip percentage", selection: $tipPercentage) {
	ForEach(tipPercentages, id: \\.self) {
	  Text($0, format: .percent)
  }
}
//3. 将 .pickerStyle()修饰符添加到Picker,目前有两种写法
.pickerStyle(.segmented)
.pickerStyle(SegmentedPickerStyle())  

Screenshot - 2023-09-21 15.33.13.png

4. 轮子样式

轮子样式会在当前页面展开一个滑轮进行选择。

.pickerStyle(.wheel)