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

如何让UICollectionView Cell中的指定View支持点击交互?

解决UICollectionView Cell内指定View的点击交互问题

你当前代码无法触发点击事件的核心原因是:在cellForItemAt方法中,你直接替换了cell.customView.view的实例,导致之前在CollectionViewCell初始化时添加的手势识别器被覆盖掉了。下面是具体的修复方案:

步骤1:修改ScreenView的view属性逻辑

不要直接替换view实例,而是通过修改现有实例的属性来更新样式,避免丢失手势:

import UIKit

class ScreenView: UIView {
    
    let rectangleView = ImageView(image: "")
    let maskImage = ImageView(image: "")
    let vectorImage = ImageView(image: "")
    let heading = Label(text: "Some Text", font: UIFont.systemFont(ofSize: 30, weight: .black), textColor: .black)
    
    let detailText:UILabel = {
        let lbl = UILabel()
        lbl.translatesAutoresizingMaskIntoConstraints = false
        lbl.font = .systemFont(ofSize: 14, weight: .light)
        lbl.numberOfLines = 0
        return lbl
    }()
    
    // 将view改为不可变实例,后续只修改属性
    let view = View(background: .systemPurple, cornerRadius: 12)
    let labelInView = Label(text: "Get Started", font: UIFont.systemFont(ofSize: 14, weight: .black), textColor: .white)
    
    init() {
        super.init(frame: .zero)
        self.translatesAutoresizingMaskIntoConstraints = false
        setupViews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupViews() {
        addSubview(rectangleView)
        rectangleView.addSubview(maskImage)
        rectangleView.addSubview(vectorImage)
        addSubview(heading)
        addSubview(detailText)
        addSubview(view)
        view.addSubview(labelInView)
        
        NSLayoutConstraint.activate([
            rectangleView.centerYAnchor.constraint(equalTo: centerYAnchor),
            rectangleView.centerXAnchor.constraint(equalTo: centerXAnchor),
            rectangleView.widthAnchor.constraint(equalToConstant: 345),
            rectangleView.heightAnchor.constraint(equalToConstant: 441),
            
            maskImage.topAnchor.constraint(equalTo: rectangleView.topAnchor),
            maskImage.widthAnchor.constraint(equalToConstant: 345),
            
            vectorImage.bottomAnchor.constraint(equalTo: rectangleView.bottomAnchor, constant: -10),
            vectorImage.centerXAnchor.constraint(equalTo: rectangleView.centerXAnchor),
            vectorImage.widthAnchor.constraint(equalToConstant: 313),
            vectorImage.heightAnchor.constraint(equalToConstant: 251),
            
            heading.topAnchor.constraint(equalTo: rectangleView.bottomAnchor, constant: 20),
            heading.centerXAnchor.constraint(equalTo: centerXAnchor),
            
            detailText.topAnchor.constraint(equalTo: heading.bottomAnchor, constant: 20),
            detailText.centerXAnchor.constraint(equalTo: centerXAnchor),
            detailText.widthAnchor.constraint(equalToConstant: 313),
            
            view.topAnchor.constraint(equalTo: detailText.bottomAnchor, constant: 74),
            view.leadingAnchor.constraint(equalTo: rectangleView.leadingAnchor ),
            view.widthAnchor.constraint(equalToConstant: 345),
            view.heightAnchor.constraint(equalToConstant: 52),
            
            labelInView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            labelInView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        ])
    }
}

同时给View类添加属性更新方法:

class View: UIView {
    init(background: UIColor, cornerRadius: CGFloat) {
        super.init(frame: .zero)
        backgroundColor = background
        layer.cornerRadius = cornerRadius
        // 显式开启用户交互(默认值为true,显式声明更稳妥)
        isUserInteractionEnabled = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // 添加属性更新方法
    func update(background: UIColor, cornerRadius: CGFloat) {
        backgroundColor = background
        layer.cornerRadius = cornerRadius
    }
}

步骤2:调整cellForItemAt中的赋值逻辑

不再替换view实例,而是调用更新方法修改其属性:

extension ViewController: UICollectionViewDelegateFlowLayout,UICollectionViewDataSource {
 
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return arrayData.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)as! CollectionViewCell
        let data = arrayData[indexPath.row]
        
        cell.customView.vectorImage.image = UIImage(named: data.vectorImages)
        cell.customView.maskImage.image = UIImage(named: data.maskImages)
        cell.customView.rectangleView.image = UIImage(named: data.rectangleImage)
        cell.customView.heading.text = data.headingLabel
        cell.customView.detailText.text = data.detailText
        cell.customView.labelInView.text = data.labelInView
        
        // 替换原赋值逻辑,改为更新现有view的属性
        cell.customView.view.update(background: data.view.backgroundColor ?? .systemPurple, cornerRadius: data.view.layer.cornerRadius)
        
        cell.viewTapped = { [weak self] aCell in
            let idx = self?.collectionView.indexPath(for: aCell)
            print("bottomView in cell at indexPath: \(idx ?? nil) was tapped")
        }
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 393 , height: 852)
    }
}

步骤3:确保手势添加逻辑正确

保留CollectionViewCell的手势逻辑,同时显式开启view的用户交互:

class CollectionViewCell: UICollectionViewCell {
    
    let customView = ScreenView()
    
    var viewTapped: ((UICollectionViewCell) -> ())?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
        tapOnView()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func tapOnView() {
        let tapView = UITapGestureRecognizer(target: self, action: #selector(handleTap))
        customView.view.isUserInteractionEnabled = true
        customView.view.addGestureRecognizer(tapView)
    }
    
    func setupView() {
        addSubview(customView)
        NSLayoutConstraint.activate([
            customView.centerYAnchor.constraint(equalTo: centerYAnchor, constant: -140),
            customView.centerXAnchor.constraint(equalTo: centerXAnchor)
        ])
    }
    
    @objc func handleTap() {
        viewTapped?(self)
    }
}

修改完成后,cell内的customView.view就能正常响应点击事件,同时样式也能正确更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 16:37:01