SwiftUI分段按钮:点击时修改内部@State并触发外部回调
解决分段按钮内部状态更新问题
我来帮你搞定这个问题!你当前的核心问题是按钮点击时只触发了外部回调,没有同步更新内部的@State变量type。只需要调整按钮的action逻辑,把状态更新和外部回调结合起来就行。
修改后的完整代码
struct SegmentedButtonView: View { @State var type: SelectionType = .none var accept: () -> () var decline: () -> () var body: some View { HStack(alignment: .center) { // 左侧"否"按钮:先更新type为.no,再执行accept回调 Button(action: { type = .no accept() }){ Spacer() Text(SelectionType.no.rawValue) .font(.Montserrat(weight: (type == .yes || type == .none) ? .SemiBold : .Bold, size: 16)) .foregroundColor((type == .none || type == .yes) ? Color.lightGray : Color.white) Spacer() } .frame(height: 40) .background(type == .no ? Color.brand_purple : Color.white) Rectangle().vertical_line().background(type == .none ? Color.lightGray : Color.brand_purple) // 右侧"是"按钮:先更新type为.yes,再执行decline回调 Button(action: { type = .yes decline() }){ Spacer() Text(SelectionType.yes.rawValue) .font(.Montserrat(weight: (type == .no || type == .none) ? .SemiBold : .Bold, size: 16)) .foregroundColor((type == .none || type == .no) ? Color.lightGray : Color.white) Spacer() } .frame(height: 40) .background(type == .yes ? Color.brand_purple : Color.white) } .frame(width: 138, height: 40) .font(.Montserrat(weight: .Bold, size: 16)) .background(Color.white) .cornerRadius(7) .overlay( RoundedRectangle(cornerRadius: 7) .stroke(type != .none ? Color.brand_purple : Color.lightGray, lineWidth: 1)) } }
关键改动说明
- 把原来直接传入
accept/decline的按钮动作,改成了闭包组合:先设置type为对应的.no或.yes,再调用外部传入的回调函数。 - 这样修改后,点击按钮会先触发内部状态更新,让UI(背景色、字体粗细、文字颜色)立刻响应变化,然后再执行你定义的外部业务逻辑,完美实现了状态更新和回调触发的同步。
额外建议
如果之后需要让父视图控制这个分段按钮的选中状态,可以把@State var type改成@Binding var type,这样父视图可以传递一个绑定值进来,实现父子组件的状态同步。不过就当前你的需求而言,使用@State维护内部状态是完全合适的。
内容的提问来源于stack exchange,提问作者George Heints
相关产品推荐
相关产品推荐

