在 SwiftUI 中,当你有一批按钮(Button
)需要使用统一的样式,且不想每次都重复定义相同的修饰符代码时,可以通过以下几种方法来实现代码的复用和统一样式设置:
方法 1:创建自定义 View Modifier #
SwiftUI 提供了 ViewModifier
,它允许你创建一个自定义的修饰符,用于集中定义按钮样式。这是最灵活的解决方案。
示例代码 #
- 创建一个自定义 View Modifier:
import SwiftUI
struct CustomButtonModifier: ViewModifier {
func body(content: Content) -> some View {
content
.padding() // 设置内边距
.background(Color.blue) // 按钮背景颜色
.cornerRadius(10) // 圆角
.foregroundColor(.white) // 文字颜色
.shadow(radius: 5) // 设置阴影
.font(.headline) // 文字字体
}
}
- 简化调用:通过扩展
View
添加一个简便方法:
extension View {
func customButtonStyle() -> some View {
self.modifier(CustomButtonModifier())
}
}
- 在按钮中使用:
struct ContentView: View {
var body: some View {
VStack(spacing: 20) {
Button("Primary") {
print("Primary Button")
}
.customButtonStyle() // 使用自定义样式
Button("Secondary") {
print("Secondary Button")
}
.customButtonStyle() // 使用相同的样式
}
}
}
优点 #
- 所有按钮样式可以在
CustomButtonModifier
中集中维护。 - 如果需要更改样式,只需修改
CustomButtonModifier
。
方法 2:创建自定义的按钮 View #
如果样式非常固定,可以把按钮封装为一个自定义的组件,这样可以直接创建样式化的按钮。
示例代码 #
- 定义一个自定义按钮组件:
import SwiftUI
struct CustomButton: View {
var title: String
var action: () -> Void
var body: some View {
Button(action: action) {
Text(title)
.padding() // 设置内边距
.background(Color.blue) // 按钮背景
.foregroundColor(.white) // 文字颜色
.cornerRadius(10) // 圆角
.shadow(radius: 5) // 阴影
}
}
}
- 使用时直接调用组件:
struct ContentView: View {
var body: some View {
VStack(spacing: 20) {
CustomButton(title: "Primary Button") {
print("Primary Button clicked")
}
CustomButton(title: "Secondary Button") {
print("Secondary Button clicked")
}
}
.padding()
}
}
优点 #
- 不再需要每次调用样式修饰符,直接通过自定义组件即可复用。
- 每个按钮都具有固定的外观,简化了代码结构。
方法 3:使用 Environment Values 共享样式 #
SwiftUI 提供了 Environment
,可以用它来统一存储并共享样式。结合自定义样式和 Environment Key,就可以实现按钮样式的全局定义。
示例代码 #
- 定义一个 Environment Key:
import SwiftUI
struct ButtonStyleKey: EnvironmentKey {
static let defaultValue: AnyViewModifier = AnyViewModifier(
modifier: CustomButtonModifier()
)
}
extension EnvironmentValues {
var buttonStyle: AnyViewModifier {
get { self[ButtonStyleKey.self] }
set { self[ButtonStyleKey.self] = newValue }
}
}
- 使用 Environment Key 在指定范围提供样式:
struct ContentView: View {
@Environment(\.buttonStyle) var buttonStyle
var body: some View {
VStack(spacing: 20) {
Button("Primary Button", action: {})
.modifier(buttonStyle.modifier)
Button("Secondary Button", action: {})
.modifier(buttonStyle.modifier)
}
.environment(\.buttonStyle, AnyViewModifier(modifier: CustomButtonModifier()))
.padding()
}
}
- 自定义
AnyViewModifier
来封装所有样式:
struct AnyViewModifier: ViewModifier {
let modifier: (Content) -> AnyView
init<V: ViewModifier>(modifier: V) {
self.modifier = { AnyView($0.modifier(modifier)) }
}
func body(content: Content) -> some View {
modifier(content)
}
}
方法 4:使用 SwiftUI 的 ButtonStyle
协议
#
SwiftUI 提供了内置的 ButtonStyle
协议,你可以通过自定义按钮样式来集中管理所有按钮外观。
示例代码 #
- 创建一个自定义按钮样式:
struct CustomButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding()
.frame(maxWidth: .infinity) // 按钮宽度固定或适配父视图
.background(configuration.isPressed ? Color.blue.opacity(0.6) : Color.blue) // 按下时效果
.cornerRadius(10)
.foregroundColor(.white)
.shadow(radius: configuration.isPressed ? 0 : 5) // 按下时改变阴影
}
}
- 在按钮中使用该自定义样式:
struct ContentView: View {
var body: some View {
VStack(spacing: 20) {
Button("Primary Button") {
print("Button 1")
}
.buttonStyle(CustomButtonStyle()) // 使用自定义按钮样式
Button("Secondary Button") {
print("Button 2")
}
.buttonStyle(CustomButtonStyle())
}
.padding()
}
}
- 如果需要在全局范围内设置按钮样式,使用
.buttonStyle()
修饰父级容器:
struct ContentView: View {
var body: some View {
VStack(spacing: 20) {
Button("Primary Button") { print("Primary Button Pressed") }
Button("Secondary Button") { print("Secondary Button Pressed") }
}
.buttonStyle(CustomButtonStyle()) // 对所有子按钮生效
.padding()
}
}
推荐方案 #
- 需要简单复用样式: 使用 自定义 View Modifier(方法 1)。
- 需要封装自成组件: 使用 自定义按钮 View(方法 2)。
- 需要全局统一样式: 使用
ButtonStyle
协议(方法 4) 或 Environment(方法 3)。 - 组合样式和行为: 将按钮封装成自定义组件,便于样式和逻辑统一管理(方法 2 最推荐)。
这几种方法可以根据你的需求灵活选择!