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

macOS SwiftUI:解决Toggle窗口失活变色,替代tintAdjustmentMode功能

解决方案

方案1:强制Toggle保持原有tint颜色不变

系统默认的switch样式会在窗口失活时自动降低tint饱和度,要规避这个行为,需自定义ToggleStyle,完全接管开关绘制逻辑,不受系统自动调整影响:

struct FixedTintSwitchStyle: ToggleStyle {
    let tintColor: Color
    let canActivate: Bool
    
    func makeBody(configuration: Configuration) -> some View {
        HStack {
            Spacer()
            ZStack(alignment: configuration.isOn ? .trailing : .leading) {
                // 开关背景
                Capsule(style: .continuous)
                    .fill(configuration.isOn ? tintColor.opacity(0.3) : Color(.systemGray5))
                    .frame(width: 51, height: 31)
                // 开关滑块
                Circle()
                    .fill(Color.white)
                    .shadow(radius: 1)
                    .padding(3)
                    .frame(width: 25, height: 25)
                    .offset(x: configuration.isOn ? 10 : -10)
                    .animation(.easeInOut(duration: 0.2), value: configuration.isOn)
            }
            .onTapGesture {
                guard canActivate else { return }
                configuration.isOn.toggle()
            }
            .opacity(canActivate ? 1 : 0.5)
            Spacer()
        }
        .overlay(
            canActivate ? Capsule(style: .continuous).stroke(tintColor) : nil
        )
    }
}

// 使用方式
Toggle(isOn: $userManagedIsActive) {
    EmptyView()
}
.disabled(!canActivate)
.toggleStyle(FixedTintSwitchStyle(tintColor: toggleColor(), canActivate: canActivate))

该自定义样式完全脱离系统默认tint调整逻辑,无论窗口是否激活,都会使用你指定的tintColor,尺寸和交互逻辑与系统原生开关对齐。


方案2:让Overlay和Toggle同步变暗匹配系统风格

要让自定义overlay与系统Toggle的变暗效果同步,需监听窗口激活状态,动态调整颜色的饱和度/透明度,对齐系统行为:

struct SyncDimSwitchStyle: ToggleStyle {
    @State private var isWindowActive = true
    
    let tintColor: Color
    let canActivate: Bool
    
    func makeBody(configuration: Configuration) -> some View {
        Toggle(isOn: configuration.$isOn) {
            EmptyView()
        }
        .disabled(!canActivate)
        .toggleStyle(.switch)
        .tint(adjustedTintColor())
        .overlay(
            canActivate ? Capsule(style: .continuous).stroke(adjustedTintColor()) : nil
        )
        .onReceive(NotificationCenter.default.publisher(for: NSWindow.didBecomeMainNotification)) { _ in
            isWindowActive = true
        }
        .onReceive(NotificationCenter.default.publisher(for: NSWindow.didResignMainNotification)) { _ in
            isWindowActive = false
        }
    }
    
    private func adjustedTintColor() -> Color {
        guard canActivate else { return tintColor.opacity(0.5) }
        // 窗口失活时降低颜色饱和度和透明度,匹配系统默认效果
        return isWindowActive ? tintColor : tintColor
            .saturation(0.3)
            .opacity(0.7)
    }
}

// 使用方式
Toggle(isOn: $userManagedIsActive) {
    EmptyView()
}
.toggleStyle(SyncDimSwitchStyle(tintColor: toggleColor(), canActivate: canActivate))

通过监听NSWindow的激活通知,动态调整颜色参数,让overlay的描边颜色与系统Toggle的变暗效果完全同步。可根据视觉需求微调saturation和opacity数值,匹配系统风格。


内容的提问来源于stack exchange,提问作者Peter Lapisu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 04:30:23