Swift中如何高亮UITableViewCell部分区域及分离不同点击的高亮效果
Hey there! Let's break down your two UITableViewCell highlighting questions with practical, Swift-based solutions:
The default UITableViewCell highlights the entire cell, but we can customize this to target specific subviews. Here are two common scenarios:
场景1:点击整个cell时,仅高亮指定子视图
Override the cell's setHighlighted or setSelected methods to modify the target subview's style (like background color or text color) with smooth animations:
class PartialHighlightCell: UITableViewCell { // The subview we want to highlight let highlightableLabel = UILabel() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupLabel() } required init?(coder: NSCoder) { super.init(coder: coder) setupLabel() } private func setupLabel() { highlightableLabel.text = "Highlight Me!" highlightableLabel.frame = CGRect(x: 20, y: 12, width: 160, height: 28) contentView.addSubview(highlightableLabel) } // Control highlight state for the target subview override func setHighlighted(_ highlighted: Bool, animated: Bool) { super.setHighlighted(highlighted, animated: animated) UIView.animate(withDuration: animated ? 0.2 : 0) { self.highlightableLabel.backgroundColor = highlighted ? .systemGray4 : .clear self.highlightableLabel.textColor = highlighted ? .systemBlue : .label } } // Keep the highlight if the cell is selected override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) UIView.animate(withDuration: animated ? 0.2 : 0) { self.highlightableLabel.backgroundColor = selected ? .systemGray4 : .clear self.highlightableLabel.textColor = selected ? .systemBlue : .label } } }
场景2:仅点击指定部分时才高亮它
Add a tap gesture recognizer to the target subview, then toggle its highlight style manually when tapped:
class TapTriggeredHighlightCell: UITableViewCell { let highlightableButton = UIButton(type: .system) override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupButton() } required init?(coder: NSCoder) { super.init(coder: coder) setupButton() } private func setupButton() { highlightableButton.setTitle("Tap to Highlight", for: .normal) highlightableButton.frame = CGRect(x: bounds.width - 110, y: 12, width: 90, height: 28) highlightableButton.isUserInteractionEnabled = true let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap)) highlightableButton.addGestureRecognizer(tapGesture) contentView.addSubview(highlightableButton) } @objc private func handleTap() { let isHighlighted = highlightableButton.backgroundColor == .systemGray4 UIView.animate(withDuration: 0.2) { self.highlightableButton.backgroundColor = isHighlighted ? .clear : .systemGray4 self.highlightableButton.setTitleColor(isHighlighted ? .label : .systemBlue, for: .normal) } // Add your tap action logic here (e.g., navigation) print("Highlighted area tapped!") } }
The key here is to isolate the two click areas so they control their own highlight states independently. Here's how to do it:
Step 1: Disable default cell highlight
First, turn off the cell's default selection style so clicking doesn't highlight the entire cell:
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) selectionStyle = .none // Disable default cell highlight setupViews() }
Step 2: Add independent interaction for each area
Assume you have two click zones: a left area (navigates to Storyboard 1, highlights the whole cell) and a right button (navigates to Storyboard 2, only highlights itself).
Handle right button highlight
Use UIButton's built-in highlighted state to customize its style without extra gestures:
let rightButton = UIButton(type: .system) private func setupRightButton() { rightButton.setTitle("Go to SB 2", for: .normal) rightButton.frame = CGRect(x: bounds.width - 100, y: 0, width: 90, height: bounds.height) // Custom highlight style rightButton.setBackgroundImage(UIColor.systemGray4.image, for: .highlighted) rightButton.setTitleColor(.systemBlue, for: .highlighted) rightButton.addTarget(self, action: #selector(rightButtonTapped), for: .touchUpInside) addSubview(rightButton) } @objc private func rightButtonTapped() { // Add your Storyboard navigation logic here print("Navigating to second Storyboard!") }
Handle left area highlight
Add a tap gesture to the cell's content view, and only trigger the full-cell highlight if the tap is outside the right button:
private func setupLeftAreaGesture() { let leftTapGesture = UITapGestureRecognizer(target: self, action: #selector(leftAreaTapped)) contentView.addGestureRecognizer(leftTapGesture) } @objc private func leftAreaTapped(_ gesture: UITapGestureRecognizer) { let tapPoint = gesture.location(in: self) // Ignore taps on the right button guard !rightButton.frame.contains(tapPoint) else { return } // Animate full-cell highlight UIView.animate(withDuration: 0.2) { self.contentView.backgroundColor = .systemGray4 } // Reset background color after animation DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { UIView.animate(withDuration: 0.2) { self.contentView.backgroundColor = .clear } } // Add your first Storyboard navigation logic here print("Navigating to first Storyboard!") }
Step 3: Ensure button gets priority for taps
Override hitTest to make sure the right button receives taps first, so the cell's gesture doesn't interfere:
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { if rightButton.frame.contains(point) { return rightButton } return super.hitTest(point, with: event) }
Helper extension for solid color images
To create the button's highlight background, add this extension to UIColor:
extension UIColor { var image: UIImage { let rect = CGRect(x: 0, y: 0, width: 1, height: 1) UIGraphicsBeginImageContext(rect.size) let context = UIGraphicsGetCurrentContext() context?.setFillColor(self.cgColor) context?.fill(rect) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image! } }
内容的提问来源于stack exchange,提问作者geniusme

