Swift中TableView单元格选中后红色视图消失问题求助
解决UITableViewCell选中后红色视图消失的问题
这个问题我之前也碰到过,核心原因是UITableViewCell默认的选中/高亮机制会影响子视图的层级或外观,导致你的红色侧边视图被遮挡或颜色被修改。结合你的代码场景,给你几个针对性的解决方案:
方案1:将红色视图添加到contentView中(最简单)
默认情况下,contentView是cell中所有自定义内容的容器,它的层级高于selectedBackgroundView(选中时显示的背景视图),所以把红色视图加到contentView里,就不会被选中背景覆盖。修改你的cellForRowAt代码:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = "Row \(indexPath.row)" // 先移除已存在的红色视图(避免复用cell时重复添加) cell.contentView.subviews.first(where: { $0.tag == 1001 })?.removeFromSuperview() let redView = UIView() redView.backgroundColor = .red redView.tag = 1001 // 标记方便复用cell时查找 redView.translatesAutoresizingMaskIntoConstraints = false cell.contentView.addSubview(redView) // 添加AutoLayout约束,适配不同cell高度 NSLayoutConstraint.activate([ redView.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor), redView.topAnchor.constraint(equalTo: cell.contentView.topAnchor), redView.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor), redView.widthAnchor.constraint(equalToConstant: 5) ]) return cell }
方案2:自定义cell的选中背景视图,避免覆盖红色视图
如果不想修改红色视图的添加位置,可以自定义selectedBackgroundView,让它的左边留出红色视图的宽度,这样既保留选中状态的视觉反馈,又不会遮挡红色视图:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = "Row \(indexPath.row)" // 配置红色视图 let redView = UIView() redView.backgroundColor = .red redView.translatesAutoresizingMaskIntoConstraints = false cell.addSubview(redView) NSLayoutConstraint.activate([ redView.leadingAnchor.constraint(equalTo: cell.leadingAnchor), redView.topAnchor.constraint(equalTo: cell.topAnchor), redView.bottomAnchor.constraint(equalTo: cell.bottomAnchor), redView.widthAnchor.constraint(equalToConstant: 5) ]) // 自定义选中背景视图,左边留出红色视图的宽度 let selectedBgView = UIView() selectedBgView.backgroundColor = UIColor.systemGray5 // 自定义选中背景色 let maskView = UIView() maskView.translatesAutoresizingMaskIntoConstraints = false selectedBgView.addSubview(maskView) NSLayoutConstraint.activate([ maskView.leadingAnchor.constraint(equalTo: selectedBgView.leadingAnchor, constant: 5), maskView.topAnchor.constraint(equalTo: selectedBgView.topAnchor), maskView.bottomAnchor.constraint(equalTo: selectedBgView.bottomAnchor), maskView.trailingAnchor.constraint(equalTo: selectedBgView.trailingAnchor) ]) selectedBgView.mask = maskView cell.selectedBackgroundView = selectedBgView return cell }
方案3:自定义Cell,在选中回调中保持红色视图状态
如果你的红色视图是固定的UI元素,推荐创建自定义Cell,重写选中/高亮的回调方法,强制保持红色视图的外观:
首先创建自定义Cell类:
class CustomSideCell: UITableViewCell { private let redSideView = UIView() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupRedSideView() } required init?(coder: NSCoder) { super.init(coder: coder) setupRedSideView() } private func setupRedSideView() { redSideView.backgroundColor = .red redSideView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(redSideView) NSLayoutConstraint.activate([ redSideView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), redSideView.topAnchor.constraint(equalTo: contentView.topAnchor), redSideView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), redSideView.widthAnchor.constraint(equalToConstant: 5) ]) } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // 强制保持红色视图颜色,不受默认选中机制影响 redSideView.backgroundColor = .red } override func setHighlighted(_ highlighted: Bool, animated: Bool) { super.setHighlighted(highlighted, animated: animated) // 高亮状态下也保持红色 redSideView.backgroundColor = .red } }
然后在ViewController中使用这个自定义Cell:
// 先在viewDidLoad中注册自定义Cell tableView.register(CustomSideCell.self, forCellReuseIdentifier: "CustomSideCell") // cellForRowAt方法中使用 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CustomSideCell", for: indexPath) as! CustomSideCell cell.textLabel?.text = "Row \(indexPath.row)" return cell }
关键注意点
- 一定要处理cell复用问题:避免在
cellForRowAt中重复添加红色视图,通过tag或自定义Cell的方式管理子视图。 - 优先使用AutoLayout约束代替frame,适配不同的cell高度和设备尺寸。
内容的提问来源于stack exchange,提问作者Anup Gupta
相关产品推荐
相关产品推荐

