如何在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
相关产品推荐
相关产品推荐

