【问题标题】:Swift 3: Be able to tap view behind a collectionViewCell?Swift 3:能够点击 collectionViewCell 后面的视图?
【发布时间】:2017-03-30 12:17:10
【问题描述】:

我正在我的应用程序中开发一项新功能,我希望用户拥有一张图片,然后能够在该图片顶部滑动一个 collectionView,添加“过滤器”。我遇到的问题是我希望用户仍然能够与图像交互,但它在 collectionView 后面。如果我将usersInteractionEnabled 中的collectionViews 设置为false,那么我当然根本无法使用collectionView。我正在寻求与 Snapchats“滚动过滤器”功能类似的功能。任何帮助将不胜感激。谢谢你们。代码如下:

import UIKit

class FirstCell: UICollectionViewCell {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    func setupViews() {
        backgroundColor = .clear
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class SecondCell: UICollectionViewCell {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    let cellView: UIView = {
        let view = UIView()
        view.backgroundColor = .red
        view.alpha = 0.25
        return view
    }()

    func setupViews() {
        backgroundColor = .clear
        addSubview(cellView)

        cellView.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class SecondController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.minimumLineSpacing = 0
        layout.minimumInteritemSpacing = 0
        layout.scrollDirection = .horizontal
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = .clear
        cv.dataSource = self
        cv.delegate = self
        cv.translatesAutoresizingMaskIntoConstraints = false
        cv.isPagingEnabled = true
        return cv
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView.register(FirstCell.self, forCellWithReuseIdentifier: "firstCell")
        collectionView.register(SecondCell.self, forCellWithReuseIdentifier: "secondCell")

        view.backgroundColor = .white

        setupViews()
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: view.frame.width, height: view.frame.height)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 2
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        if indexPath.item == 0 {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "firstCell", for: indexPath) as! FirstCell
            return cell
        } else {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "secondCell", for: indexPath) as! SecondCell
            return cell
        }
    }

    lazy var imageView: UIImageView = {
        let iv = UIImageView()
        let image = UIImage(named: "img")
        iv.image = image
        iv.contentMode = .scaleAspectFill
        iv.translatesAutoresizingMaskIntoConstraints = false
        iv.isUserInteractionEnabled = true
        iv.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))
        return iv
    }()

    func handleTap() {
        print(123)
    }

    func setupViews() {
        view.addSubview(imageView)
        view.addSubview(collectionView)

        imageView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        imageView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        imageView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true

        collectionView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        collectionView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        collectionView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    }

}

【问题讨论】:

    标签: swift swift3 uicollectionview uicollectionviewcell


    【解决方案1】:

    有一个hitTest(_::) 方法可用于覆盖任何UIView 子类,您可以在您的自定义UICollectionView 子类中实现该方法,然后从它转发到任何其他视图(集合视图后面的图像在您的案例)。

    override func hitTest(_ point: CGPoint,
                                   with event: UIEvent?) -> UIView? {
    
        let hitView = super.hitTest(point, with: event)
    
        if self.parentViewController.forwardTapToImageIfNeeded(point) {
            return nil
        }
    
        return hitView
    }
    

    其中parentViewController 是对您的SecondController 实例的引用,它应该具有forwardTapToImageIfNeeded(_) 函数来检查用户的点击是否在图像帧的顶部,如果是,则自动将点击事件传递给它。

    func forwardTapToImageIfNeeded(_ p: CGPoint) -> Bool {
        /* Convert point to local coordinates */
        let pointInSuperView = self.convert(p, from: collectionView)
        /* Check if tap is on top of the image frame */
        if imageBehindCollection.frame.contains(pointInSuperView) { 
            // Forward tap to the image `imageBehindCollection`
            return true 
        }
    
        return false
    }
    

    注意:我没有自己测试这个特定的代码,所以它可能需要在 Xcode 中进行一些修复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-06
      相关资源
      最近更新 更多