在iOS 15 中,Apple 引入了一个新方法,来为SwiftUI 和UIKit 框架的iOS App 客制化按钮。这篇教学文章主要会介绍SwiftUI 的新功能,如果你有兴趣了解如何在iOS 15 中设置 UIButton
样式,可以参考Sarun 撰写的这篇文章。
在SwiftUI 设置按钮样式
在我们介绍iOS 15 的新修饰符(modifier) 之前,先重温一下现在我们设置按钮样式的方法。
比如说,我们想创建一个圆角按钮,就可以如此编写程式码:
Button(action: {}) {
Text("Buy me a coffee")
}
.padding()
.foregroundColor(.white)
.background(Color.purple)
.clipShape(RoundedRectangle(cornerRadius: 5))
我们利用 .clipShape
修饰符,来客制化按钮的前景和背景颜色、应用间距(padding) 和圆角。
在iOS 15 中,要创建一个类似的圆角按钮,我们可以使用新修饰符buttonBorderShape
,并应用 BorderedProminentButtonStyle
新样式:
Button(action: {}) {
Text("Buy me a coffee")
}
.tint(.purple)
.buttonStyle(.borderedProminent)
.buttonBorderShape(.roundedRectangle(radius: 5))
.controlSize(.large)
应用 .borderedProminent
样式后,iOS 就会将按钮呈现为紫色背景和白色文字。.buttonBorderShape
则是让我们设置按钮的边框形状(border shape),在这里,我们会设置为.roundedRectangle
,以创建圆角按钮。
控制按钮的大小
我们可以利用 .controlSize
来改变按钮的大小。按钮的预设大小是.regular
,其他可选的设定包括.large
、.small
、和.mini
。让我们看看不同大小的按钮:
按钮的边框形状
除了 .roundedRectangle
外,SwiftUI 还提供了另外一个边框形状.capsule
,让开发者可以创建胶囊形状的按钮。
我们也可以使用.automatic
,让系统自动调整按钮的形状。
改变按钮样式
之前我们一直在使用 .borderProminent
按钮样式。新版本的SwiftUI 提供了其他内置样式,包括.bordered
、.borderless
和.plain
。.bordered
样式是我们通常会使用的样式。以下是在浅色(light) 和深色模式(dark mode) 下,使用 .bordered
样式的按钮预览图片:
当然,我们还是可以自己编写程式码来创建同样的按钮,但这个iOS 15 的新样式就可以为我们节省不少编写程式码的时间。
把样式应用到多个按钮
设定好按钮样式之后,我们就可以简单地为一组按钮应用同一样式,看看以下例子:
VStack {
Button(action: {}) {
Text("Add to Cart")
.font(.headline)
}
Button(action: {}) {
Text("Discover")
.font(.headline)
.frame(maxWidth: 300)
}
Button(action: {}) {
Text("Check out")
.font(.headline)
}
}
.tint(.purple)
.buttonStyle(.bordered)
.controlSize(.large)
利用按钮Role
SwiftUI 框架的iOS 15 版本为 Button
引入了一个新的 role
选项。这个选项会描述按钮的Semantic Role。iOS 会根据指定的role,自动为按钮呈现适当的外观。
比如说,我们把role 定义为.destructive
:
Button("Delete", role: .destructive) {
print("Delete")
}
.buttonStyle(.borderedProminent)
.controlSize(.large)
iOS 就会自动以红色显示Delete按钮。让我们看看不同role 和样式的配搭,会创建出怎样的按钮外观:
确认对话框(Confirmation Dialog)
iOS 15 除了新的按钮样式之外,还有一个新修饰符.confirmationDialog
,我们可以将其附加到 Button
来显示一个确认对话框。
让我们看看显示确认对话框的范例程式码:
struct DemoView: View {
@State private var isShowingDialog = false
var body: some View {
Button("Delete", role: .destructive) {
isShowingDialog = true
}
.buttonStyle(.borderedProminent)
.controlSize(.large)
.confirmationDialog("Are you sure to delete the data?", isPresented: $isShowingDialog, titleVisibility: .visible) {
Button("Confirm", role: .destructive) {
// Handle the delete action.
}
Button("Cancel", role: .cancel) {
}
}
}
}
我们可以在 .confirmationDialog
修饰符设定标题和布林值,用来决定是否显示对话框。你也可以在 titleVisibility
选择是否显示标题。
编写好上述的程式码后,我们会得到以下的确认对话框:
利用Material 客制化按钮
在iOS 15 中,SwiftUI 引入了一个Material 型别,让开发者可以创建不同的模糊效果(blur effect)。我们可以在.background
修饰符添加以下的Material,在一个视图后面的视图上应用模糊效果。
- .ultraThickMaterial
- .thickMaterial
- .regularMaterial
- .thinMaterial
- .ultraThinMaterial
让我们看看应用了 .ultraThinMaterial
的范例程式码:
Button(action: {}) {
Text("Add to Cart")
.font(.headline)
}
.padding()
.background(.ultraThinMaterial, in: Capsule())
就如Apple 所说,添加Material 就像是在视图与其背景之间插入一个半透明层(translucent layer)。如果我们使用不同的Material,就会实作出不同的模糊效果。你可以参考下图,看看不同Material 实作出的模糊效果。
Toggle 按钮
在iOS 中,Toggle 就像是一个开关按钮。在iOS 15 中,我们可以使用 .toggleStyle
修饰符,将Toggle 设置显示为一个按钮:
struct DemoView: View {
@State private var isEnabled = false
var body: some View {
Toggle(isOn: $isEnabled) {
Label("Airplane mode", systemImage: "airplane.circle.fill")
}
.padding()
.tint(.purple)
.controlSize(.large)
.toggleStyle(.button)
}
}
把 .toggleStyle
设置为 .button
后,Toggle 就会变成按钮的模样。以下是Toggle 在ON/OFF 状态时的外观:
总结
iOS 15 为客制化SwiftUI 按钮带来了许多改进。虽然我们也可以创建自己的方法来设计按钮样式,但新版本的SwiftUI 有很多内置样式,减轻了开发者的工作。
这些新功能唯一的缺点,就是只支持iOS 15。如果你的App 需要兼容旧版本的iOS,就需要自己实作来设置按钮样式。