我正在我的应用程序中开发一项新功能,我希望用户拥有一张图像,然后能够在该图像的顶部扫过collectionView,并添加“过滤器”。我遇到的问题是我希望用户仍然能够与图像进行交互,但是它位于collectionView的后面。如果将collectionViews inUsersInteractionEnabled设置为false,那么我当然就不能使用collectionView。我打算使用与Snapchat的“滚动筛选器”功能类似的功能。任何帮助将不胜感激。感谢大伙们。代码如下:

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
    }

}

最佳答案

在任何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中进行一些修复。

关于swift - Swift 3:是否可以在collectionViewCell后面点击 View ?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43117645/

10-11 14:56