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

如何在UISwitch控件中添加对勾标记?

给UISwitch添加对勾标记的实现方案

原生UISwitch没有暴露修改选中状态标记的公开API,这里提供两种实现思路,可根据你的现有代码进度选择:

方案1:自定义Switch控件(兼容性最高,推荐)

直接替换现有原生UISwitch,完全自定义样式,适配所有iOS版本,不会出现系统升级后的适配问题:

  • 继承UIControl开发自定义Switch,保留和原生UISwitch一致的isOn属性、setOn(_:animated:)方法,无需修改原有业务逻辑
  • 内部实现三个核心模块:背景视图、滑动滑块、对勾图层
  • 开启状态下背景设为蓝色,显示白色对勾;关闭状态下背景设为灰色,隐藏对勾,同步添加滑块滑动动画匹配原生交互体验

核心实现代码参考:

class CheckmarkSwitch: UIControl {
    // 对外暴露的状态属性,和原生UISwitch对齐
    var isOn: Bool = false {
        didSet { updateUI(animated: true) }
    }
    
    private let backgroundView = UIView()
    private let thumbView = UIView()
    private let checkmarkLayer = CAShapeLayer()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupLayout()
        setupCheckmark()
        addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(toggle)))
    }
    
    private func setupLayout() {
        bounds = CGRect(x: 0, y: 0, width: 51, height: 31) // 和原生UISwitch尺寸一致
        backgroundView.frame = bounds
        backgroundView.layer.cornerRadius = bounds.height / 2
        backgroundView.backgroundColor = .systemGray4
        addSubview(backgroundView)
        
        thumbView.frame = CGRect(x: 2, y: 2, width: 27, height: 27)
        thumbView.layer.cornerRadius = thumbView.bounds.height / 2
        thumbView.backgroundColor = .white
        thumbView.layer.shadowOpacity = 0.2
        thumbView.layer.shadowRadius = 2
        thumbView.layer.shadowOffset = .init(width: 0, height: 1)
        addSubview(thumbView)
    }
    
    private func setupCheckmark() {
        // 绘制白色对勾路径
        let checkPath = UIBezierPath()
        checkPath.move(to: .init(x: 9, y: 16))
        checkPath.addLine(to: .init(x: 13, y: 20))
        checkPath.addLine(to: .init(x: 19, y: 12))
        checkmarkLayer.path = checkPath.cgPath
        checkmarkLayer.strokeColor = UIColor.white.cgColor
        checkmarkLayer.lineWidth = 2
        checkmarkLayer.fillColor = UIColor.clear.cgColor
        checkmarkLayer.lineCap = .round
        checkmarkLayer.lineJoin = .round
        checkmarkLayer.opacity = 0
        backgroundView.layer.addSublayer(checkmarkLayer)
    }
    
    private func updateUI(animated: Bool) {
        backgroundView.backgroundColor = isOn ? .systemBlue : .systemGray4
        checkmarkLayer.opacity = isOn ? 1 : 0
        let thumbX = isOn ? bounds.width - thumbView.bounds.width - 2 : 2
        UIView.animate(withDuration: animated ? 0.25 : 0, delay: 0, options: .curveEaseInOut) {
            self.thumbView.frame.origin.x = thumbX
        }
    }
    
    @objc private func toggle() {
        isOn.toggle()
        sendActions(for: .valueChanged)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

方案2:原生UISwitch扩展(改动最小)

如果不想重构现有UISwitch相关代码,可以直接给原生控件添加对勾子视图:

  • 在现有UISwitch实例上添加CAShapeLayer类型的对勾图层,调整位置到开关左侧背景区域
  • 监听UISwitch的valueChanged事件,切换对勾的显示/隐藏状态

注意:需要把对勾图层的zPosition设置为1,避免被背景或者滑块遮挡,同时要做好不同iOS版本的尺寸适配,避免对勾位置偏移

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 09:09:07