Toggle

Toggle 是一个可以打开或关闭的开关。像其他控件一样,你需要把它绑定到一个变量上,这个变量被传递到 Toggle 的初始化器中。然后需要做的是改变这个绑定变量的值来改变 Toggle 的状态,使其开启或关闭。或者读取绑定变量的值来查看 Toggle 当前处于什么状态。

Toggle 是一个水平方向扩张型的视图,垂直方向则不扩张。

// 简单文字开关
Toggle("Night Mode", isOn: $isToggleOn)

// SwiftUI 中同一段代码在不同设备上可以产生不同的 UI 。例如以上代码对于 iOS 和 iPadOS,Toggle 会渲染成开关;而在 macOS 会渲染成单选框。SwiftUI 的美妙之处是你可以针对所有 Apple 平台复用大部分的代码,无需修改。

参数:isOn 绑定布尔值

//宣告一個状态变量來储存目前开关的设定
@State private var showCheckInOnly = false

Toggle(isOn: $showCheckInOnly) { ... }

参数:视图闭包

Toggle(isOn: $showCheckInOnly) {
    Text("开关的Label")
}

// 图标文字混用
Toggle(isOn: $showCheckInOnly) {
		Text("开关的Label")
		Image(systemName: "moon")
}

修饰符:toggleStyle

使用 toggleStyle() 修饰符可以自定义开关的颜色。这很有用,因为 accentColor() 不适用于 Toggle 视图,因此只能用这个方法上色。SwiftUI 中内置的切换样式包括:

// 例如使用 SwitchToggleStyle 设置为红色开关
Toggle("Show welcome message", isOn: $showGreeting)
		.toggleStyle(SwitchToggleStyle(tint: .red))

// 如果您的目标平台是 iOS 15 或更高版本,则可以通过指定 .toggleStyle(.button) 将开关配置为显示为按钮
// 在此模式下,按钮在其状态打开时翻转其色调颜色:
Toggle("Filter", isOn: $isOn)
		.toggleStyle(.button)
		.tint(.mint)

修饰符:labelsHidden

// 该修饰符可以隐藏 Label
Toggle("Turn this alarm on", isOn: $isToggleOn)        
	.labelsHidden()

实现一对多绑定的高级效果

该功能在 Xcode 中无法预览。

从 iOS 16 开始,还可以将 Toggle 绑定到布尔数组,这在您想要同时启用或禁用多个值时很有帮助。例如,我们可以编写一些代码来让用户订阅单个新闻通讯,或者通过一个开关来切换所有新闻通讯:

struct EmailList: Identifiable {
    var id: String
    var isSubscribed = false
}

struct ContentView: View {

    @State var lists = [
        EmailList(id: "Monthly Updates", isSubscribed: true),
        EmailList(id: "News Flashes", isSubscribed: true),
        EmailList(id: "Special Offers", isSubscribed: true)
    ]

    var body: some View {
        Form {
            Section {
                ForEach($lists) { $list in
                    Toggle(list.id, isOn: $list.isSubscribed)
                }
            }

						// 源是输入数组,绑定该数组的某个键路径(也就是一组布尔值)
            Section {
                Toggle("Subscribe to all", sources: $lists, isOn: \\.isSubscribed)
            }
        }
    }
}

使用 ToggleStyle 自定义切换样式

SwiftUI 提供了 ToggleStyle 协议来自定义 Toggle 开关的外观和工作方式。任何符合此协议的结构都必须实现 makeBody() 方法,该方法可以按照您的需要呈现 Toggle ,并且您将同时提供用于切换的标签和 isOn 绑定,您可以翻转它来调整切换。

重要提示:当您自定义 Toggle 开关时,您需要自己以某种方式切换打开状态,SwiftUI 不会为您做这件事。

以下演示自定义 Toggle 样式,这里使用按钮来翻转打开状态,然后添加自定义标签来显示该状态。我没有使用像标准 iOS Toggle 这样的移动圆圈,而是将此显示为两个 SF 符号之一:

struct CheckToggleStyle: ToggleStyle {
		func makeBody(configuration: Configuration) ->some View {
        Button {
            configuration.isOn.toggle()
        } label: {
            Label {
                configuration.label
            } icon: {
                Image(systemName: configuration.isOn ? "checkmark.circle.fill" : "circle")
                    .foregroundStyle(configuration.isOn ? Color.accentColor : .secondary)
                    .accessibility(label: Text(configuration.isOn ? "Checked" : "Unchecked"))
                    .imageScale(.large)
            }
        }
        .buttonStyle(.plain)
    }
}

// An example view showing the style in action
struct ContentView: View {
    @State private var isOn = false
		var body:some View {
        Toggle("Switch Me", isOn: $isOn)
            .toggleStyle(CheckToggleStyle())
    }
}