除扩展Button外,是否有其他实现ButtonStyle条件切换的方案?
你提到无法直接使用.buttonStyle(selected : .bordered : .borderedProminent)的写法(推测是语法书写错误,正确的三元表达式应为selected ? .bordered : .borderedProminent),除了扩展Button类之外,还有以下几种实用的替代方案:
方案一:直接使用三元运算符(修正语法后)
.bordered和.borderedProminent同属PrimitiveButtonStyle类型,完全可以通过三元表达式直接传入buttonStyle修饰符,这是最简洁的写法:
struct DepartureArrivalView: View { @Binding var value: String @Binding var selected: Bool var body: some View { VStack(spacing: 0) { Button { } label: { Text(value) .frame(maxWidth: .infinity, alignment: .leading) .font(.title) } .buttonStyle(selected ? .bordered : .borderedProminent) .padding(16) } } }
方案二:自定义条件ButtonStyle结构体
通过实现PrimitiveButtonStyle协议封装条件逻辑,适合需要在多个视图中复用该样式规则的场景:
// 封装条件样式的结构体 struct ConditionalButtonStyle: PrimitiveButtonStyle { let isSelected: Bool func makeBody(configuration: Configuration) -> some View { if isSelected { configuration.label.buttonStyle(.bordered) } else { configuration.label.buttonStyle(.borderedProminent) } } } // 视图中使用自定义样式 struct DepartureArrivalView: View { @Binding var value: String @Binding var selected: Bool var body: some View { VStack(spacing: 0) { Button { } label: { Text(value) .frame(maxWidth: .infinity, alignment: .leading) .font(.title) } .buttonStyle(ConditionalButtonStyle(isSelected: selected)) .padding(16) } } }
方案三:内联@ViewBuilder条件判断
无需扩展或自定义结构体,直接在修饰链中通过@ViewBuilder实现分支逻辑,适合临时场景:
struct DepartureArrivalView: View { @Binding var value: String @Binding var selected: Bool var body: some View { VStack(spacing: 0) { // 内联判断样式 @ViewBuilder let styledButton = Button { } label: { Text(value) .frame(maxWidth: .infinity, alignment: .leading) .font(.title) } .applyStyle(selected) styledButton.padding(16) } } } // 辅助扩展让内联逻辑更清晰 extension View { @ViewBuilder func applyStyle(_ isSelected: Bool) -> some View { if isSelected { self.buttonStyle(.bordered) } else { self.buttonStyle(.borderedProminent) } } }
内容的提问来源于stack exchange,提问作者Jason Rich Darmawan
相关产品推荐
相关产品推荐

