如何为UISegmentedControl选中项添加自定义子视图及底部边框
嘿,我来帮你搞定这两个需求!看你已经完成了隐藏边框和自定义选中背景的工作,接下来咱们一步步实现剩下的功能:
一、为选中的Segment添加底部边框
我们可以在你的UISegmentedControl扩展里新增一个方法,用来给选中项添加底部边框,并且监听选中状态变化自动更新边框位置:
import UIKit import Foundation extension UISegmentedControl { // 你已有的removeBorders方法和imageWithColor方法保持不变 func removeBorders() { setBackgroundImage(imageWithColor(color: backgroundColor ?? Constants.Color.mainNavBarBGColor), for: .normal, barMetrics: .default) setBackgroundImage(imageWithColor(color: Constants.Color.mainNavBarBGColor), for: .selected, barMetrics: .default) // 补充移除分割线的代码(如果需要) setDividerImage(imageWithColor(color: .clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default) } private func imageWithColor(color: UIColor) -> UIImage { let rect = CGRect(x: 0, y: 0, width: 1, height: 1) UIGraphicsBeginImageContext(rect.size) let context = UIGraphicsGetCurrentContext() context?.setFillColor(color.cgColor) context?.fill(rect) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image ?? UIImage() } // 新增:添加选中项底部边框 func addSelectedBottomBorder(color: UIColor, height: CGFloat = 2.0) { // 先移除旧的边框,避免重复叠加 subviews.forEach { segment in segment.layer.sublayers?.filter { $0.name == "selectedBottomBorder" }.forEach { $0.removeFromSuperlayer() } } // 给当前选中的segment添加边框 guard let selectedSegment = subviews.first(where: { $0.isSelected }) else { return } let borderLayer = CALayer() borderLayer.name = "selectedBottomBorder" borderLayer.frame = CGRect( x: 0, y: selectedSegment.frame.height - height, width: selectedSegment.frame.width, height: height ) borderLayer.backgroundColor = color.cgColor selectedSegment.layer.addSublayer(borderLayer) // 监听选中变化,自动更新边框位置 addTarget(self, action: #selector(updateSelectedBottomBorder(color:height:)), for: .valueChanged) } @objc private func updateSelectedBottomBorder(color: UIColor, height: CGFloat) { // 移除所有旧边框 subviews.forEach { segment in segment.layer.sublayers?.filter { $0.name == "selectedBottomBorder" }.forEach { $0.removeFromSuperlayer() } } // 给新选中的segment添加边框 guard let selectedSegment = subviews.first(where: { $0.isSelected }) else { return } let borderLayer = CALayer() borderLayer.name = "selectedBottomBorder" borderLayer.frame = CGRect( x: 0, y: selectedSegment.frame.height - height, width: selectedSegment.frame.width, height: height ) borderLayer.backgroundColor = color.cgColor selectedSegment.layer.addSublayer(borderLayer) } }
使用的时候,只需要在调用removeBorders()之后,再调用这个方法:
yourSegmentedControl.removeBorders() yourSegmentedControl.addSelectedBottomBorder(color: .systemBlue, height: 2.5)
二、为选中的Segment添加自定义子视图
同样在扩展里新增方法,支持给选中项添加自定义视图,并且在选中切换时自动转移视图:
// 在UISegmentedControl扩展里继续添加: func addCustomSubviewToSelectedSegment(_ subview: UIView) { // 先移除之前添加的自定义视图(用tag标记方便查找) subviews.forEach { segment in segment.subviews.filter { $0.tag == 999 }.forEach { $0.removeFromSuperview() } } // 添加到当前选中的segment guard let selectedSegment = subviews.first(where: { $0.isSelected }) else { return } subview.tag = 999 subview.translatesAutoresizingMaskIntoConstraints = false selectedSegment.addSubview(subview) // 这里可以根据你的需求设置约束,示例是让视图居中 NSLayoutConstraint.activate([ subview.centerXAnchor.constraint(equalTo: selectedSegment.centerXAnchor), subview.centerYAnchor.constraint(equalTo: selectedSegment.centerYAnchor), subview.widthAnchor.constraint(equalToConstant: 24), subview.heightAnchor.constraint(equalToConstant: 24) ]) // 监听选中变化,更新视图位置 addTarget(self, action: #selector(updateCustomSubview(_:)), for: .valueChanged) } @objc private func updateCustomSubview(_ sender: UISegmentedControl) { // 找到之前的自定义视图并移除 let existingSubview = sender.subviews.flatMap { $0.subviews }.first(where: { $0.tag == 999 }) existingSubview?.removeFromSuperview() // 这里可以根据需求重新创建视图,或者保留原有视图的引用 // 示例中我们重新创建一个简单的红色圆形视图 let customView = UIView() customView.backgroundColor = .systemRed customView.layer.cornerRadius = 12 sender.addCustomSubviewToSelectedSegment(customView) }
使用示例:
// 创建一个自定义视图,比如UIImageView let customIcon = UIImageView(image: UIImage(systemName: "checkmark")) customIcon.tintColor = .white yourSegmentedControl.addCustomSubviewToSelectedSegment(customIcon)
这样就能实现你要的两个效果啦!
内容的提问来源于stack exchange,提问作者SlavisaPetkovic
相关产品推荐
相关产品推荐

