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

如何复刻iOS 17按钮点击时的高亮与动画效果(自定义ButtonStyle)

解决自定义ButtonStyle高亮效果适配问题的方案

针对固定opacity/brightness无法适配多背景色的问题,这里提供几个贴近苹果原生逻辑的解决方案:

方案1:iOS17+ 直接使用系统原生高亮修饰符(最推荐)

苹果在iOS17中提供了highlightEffect()修饰符,它会自动根据按钮背景色、当前明暗模式生成适配的高亮效果,完全不需要手动调整颜色参数。直接替换原有代码即可:

struct CustomButtonStyle: ButtonStyle {
    let backgroundColor: Color = .mint
    
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .frame(minWidth: 240)
            .foregroundStyle(.white)
            .font(.system(size: 19, design: .rounded).weight(.semibold))
            .background(backgroundColor, in: RoundedRectangle(cornerRadius: 10, style: .continuous))
            .highlightEffect() // 原生高亮效果,自动适配所有颜色和模式
    }
}

方案2:基于背景色亮度动态生成遮罩

如果需要兼容iOS17以下版本,可以通过计算背景色的亮度,动态切换高亮遮罩颜色(亮背景用深色半透明遮罩,暗背景用浅色半透明遮罩),完全模拟苹果原生的高亮逻辑:

首先添加计算颜色亮度的扩展:

extension Color {
    // 基于WCAG标准计算颜色相对亮度
    var brightness: Double {
        let uiColor = UIColor(self)
        var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0
        uiColor.getRed(&red, green: &green, blue: &blue, alpha: nil)
        return Double(0.2126 * red + 0.7152 * green + 0.0722 * blue)
    }
}

然后修改ButtonStyle:

struct CustomButtonStyle: ButtonStyle {
    let backgroundColor: Color = .mint
    
    func makeBody(configuration: Configuration) -> some View {
        // 根据背景亮度选择高亮遮罩颜色
        let highlightMask = backgroundColor.brightness > 0.5 
            ? Color.black.opacity(0.2) 
            : Color.white.opacity(0.2)
        
        configuration.label
            .frame(minWidth: 240)
            .foregroundStyle(.white)
            .font(.system(size: 19, design: .rounded).weight(.semibold))
            .background(backgroundColor, in: RoundedRectangle(cornerRadius: 10, style: .continuous))
            .overlay(
                RoundedRectangle(cornerRadius: 10, style: .continuous)
                    .fill(highlightMask)
                    .opacity(configuration.isPressed ? 1 : 0)
            )
            .animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
    }
}

方案3:使用混合模式实现自适应高亮

利用SwiftUI的blendMode(.overlay),可以让高亮层自动根据底层背景色调整明暗——白色叠加在亮色上会变暗,叠加在暗色上会变亮,效果接近原生:

struct CustomButtonStyle: ButtonStyle {
    let backgroundColor: Color = .mint
    
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .frame(minWidth: 240)
            .foregroundStyle(.white)
            .font(.system(size: 19, design: .rounded).weight(.semibold))
            .background(backgroundColor, in: RoundedRectangle(cornerRadius: 10, style: .continuous))
            .overlay(
                RoundedRectangle(cornerRadius: 10, style: .continuous)
                    .fill(Color.white)
                    .blendMode(.overlay)
                    .opacity(configuration.isPressed ? 0.3 : 0)
            )
            .animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:07:06