SwiftUI中自定义ButtonStyle后.controlSize()失效问题求助
当你自定义ButtonStyle时,.controlSize()修饰器不会自动生效——因为系统内置的按钮样式(比如.borderedProminent)内部已经实现了对controlSize环境变量的响应逻辑,而自定义样式需要你手动处理这个变量。
实现方法:读取环境中的controlSize并适配样式
在自定义ButtonStyle中,通过@Environment(\.controlSize)获取当前的控制尺寸,然后根据不同的尺寸值调整按钮的内边距、字体大小等属性,以此匹配系统的控制尺寸效果。
修改后的代码示例:
struct ContentView: View { var body: some View { VStack(spacing: 16) { Button("Hello World") { } .buttonStyle(.borderedProminent) .controlSize(.mini) Button("Hello World") { } .buttonStyle(CustomButtonStyle()) .controlSize(.mini) Button("Hello World") { } .buttonStyle(.borderedProminent) .controlSize(.large) Button("Hello World") { } .buttonStyle(CustomButtonStyle()) .controlSize(.large) } .padding() } } struct CustomButtonStyle: ButtonStyle { // 读取当前环境的controlSize @Environment(\.controlSize) private var controlSize func makeBody(configuration: Configuration) -> some View { configuration.label .font(fontForSize) .padding(paddingForSize) .background(Color.cyan) .border(Color.brown) .opacity(configuration.isPressed ? 0.8 : 1.0) // 添加上按下效果更贴近系统样式 } // 根据controlSize设置对应字体 private var fontForSize: Font { switch controlSize { case .mini: return .caption case .small: return .subheadline case .regular: return .body case .large: return .title3 @unknown default: return .body } } // 根据controlSize设置对应内边距 private var paddingForSize: EdgeInsets { switch controlSize { case .mini: return EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8) case .small: return EdgeInsets(top: 6, leading: 12, bottom: 6, trailing: 12) case .regular: return EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16) case .large: return EdgeInsets(top: 12, leading: 20, bottom: 12, trailing: 20) @unknown default: return EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16) } } }
另一种思路:基于系统样式扩展
如果你只想在系统样式基础上修改部分属性,不想完全自定义,可以直接基于系统样式做扩展,这样自动继承controlSize的响应逻辑:
struct CustomBorderedStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { Button(configuration.label) {} .buttonStyle(.borderedProminent) .background(Color.cyan) .border(Color.brown) } }
这种方式会保留系统样式对controlSize的处理,同时叠加你的自定义样式。
内容的提问来源于stack exchange,提问作者Yiming Designer
相关产品推荐
相关产品推荐

