You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 17:43:11