Swift - UIButton in UICollectionViewCell not click

2019-08-04 10:18发布

问题:

I currently have a UICollectionViewController to display all my news articles. For my news items, I have created a custom UICollectionViewCell with a small button in the top right corner.

The problem is that it is only working when I set my feedCell to isUserInteractionEnabled = true. I only want the newsMenu button to be clickable, not have the whole cell to be selectable.

How do I achieve this?

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

    let feedCell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FeedCell

    feedCell.post = m_Collection?[(indexPath as NSIndexPath).item]

    feedCell.newsMenu.addTarget(self, action: #selector(imageTapped), for: .touchUpInside)

    return feedCell
}

func imageTapped(button: UIButton)
{
    let newsAction = UIAlertController(title: "Message", message: "Do you want to edit or delete this news message?", preferredStyle: .actionSheet)

    let editAction = UIAlertAction(title: "Edit news", style: .default, handler: menuEditNews)
    let deleteAction = UIAlertAction(title: "Delete news", style: .destructive, handler: menuDeleteNews)
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)

    newsAction.addAction(editAction)
    newsAction.addAction(deleteAction)
    newsAction.addAction(cancelAction)

    self.present(newsAction, animated: true, completion: nil)
}

My custom cell:

class FeedCell: UICollectionViewCell {

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

    setupViews()
}

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

let titleLabel: UILabel = {
    let label = UILabel()
    label.adjustsFontSizeToFitWidth = false
    label.lineBreakMode = .byTruncatingTail
    label.numberOfLines = 2
    return label
}()

let profileImageView: UIImageView = {
    let imageView = UIImageView()
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.image = UIImage(named: "")
    imageView.layer.cornerRadius = 22
    imageView.layer.masksToBounds = true
    return imageView
}()

let newsTextView: UITextView = {
    let textView = UITextView()
    textView.isScrollEnabled = false
    textView.font = UIFont (name: "Helvetica", size: 13)
    return textView
}()

let newsMenu: UIButton = {
    let newsMenu = UIButton()
    newsMenu.isUserInteractionEnabled = true
    newsMenu.setImage(UIImage(named: "news_menuitem"), for: UIControlState())
    return newsMenu
}()

func setupViews() {
    backgroundColor = UIColor.white

    addSubview(titleLabel)
    addSubview(profileImageView)
    addSubview(newsTextView)
    addSubview(newsMenu)

    addConstraintsWithFormat("H:|-8-[v0(44)]-8-[v1]-10-[v2(25)]-8-|", views: profileImageView, titleLabel, newsMenu)
    addConstraintsWithFormat("H:|-4-[v0]-4-|", views: newsTextView)
    addConstraintsWithFormat("V:|-6-[v0]", views: newsMenu)
    addConstraintsWithFormat("V:|-10-[v0]", views: titleLabel)
    addConstraintsWithFormat("V:|-8-[v0(44)]-4-[v1]", views: profileImageView, newsTextView)
}
}

回答1:

The reason why the keyboard appears when tapping the cell is most likely that you're in fact tapping on the UITextView, to prevent this behavior just set the isUserInteractionEnabled flag to false on the newsTextView object.



回答2:

Change your code to:

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

        let feedCell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FeedCell

        feedCell.post = m_Collection?[(indexPath as NSIndexPath).item]

        feedCell.sourceController = self // assign controller

        return feedCell
    }

    func imageTapped() // remove (button: UIButton)
    {
        let newsAction = UIAlertController(title: "Message", message: "Do you want to edit or delete this news message?", preferredStyle: .actionSheet)

        let editAction = UIAlertAction(title: "Edit news", style: .default, handler: menuEditNews)
        let deleteAction = UIAlertAction(title: "Delete news", style: .destructive, handler: menuDeleteNews)
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)

        newsAction.addAction(editAction)
        newsAction.addAction(deleteAction)
        newsAction.addAction(cancelAction)

        self.present(newsAction, animated: true, completion: nil)
    }

And your custom cell:

class FeedCell: UICollectionViewCell {

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

        setupViews()
    }

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

    weak var sourceController: YourController?  // declare new variable

    let titleLabel: UILabel = {
        let label = UILabel()
        label.adjustsFontSizeToFitWidth = false
        label.lineBreakMode = .byTruncatingTail
        label.numberOfLines = 2
        return label
    }()

    let profileImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.image = UIImage(named: "")
        imageView.layer.cornerRadius = 22
        imageView.layer.masksToBounds = true
        return imageView
    }()

    let newsTextView: UITextView = {
        let textView = UITextView()
        textView.isScrollEnabled = false
        textView.font = UIFont (name: "Helvetica", size: 13)
        return textView
    }()

    lazy var newsMenu: UIButton = {  // change `let` to `lazy var`
        let newsMenu = UIButton()
        newsMenu.isUserInteractionEnabled = true
        newsMenu.setImage(UIImage(named: "news_menuitem"), for: UIControlState())
        newsMenu.addTarget(self, action: #selector(actionTap), for: .touchUpInside) // add target to button
        return newsMenu
    }()

    func setupViews() {
        backgroundColor = UIColor.white

        addSubview(titleLabel)
        addSubview(profileImageView)
        addSubview(newsTextView)
        addSubview(newsMenu)

        addConstraintsWithFormat("H:|-8-[v0(44)]-8-[v1]-10-[v2(25)]-8-|", views: profileImageView, titleLabel, newsMenu)
        addConstraintsWithFormat("H:|-4-[v0]-4-|", views: newsTextView)
        addConstraintsWithFormat("V:|-6-[v0]", views: newsMenu)
        addConstraintsWithFormat("V:|-10-[v0]", views: titleLabel)
        addConstraintsWithFormat("V:|-8-[v0(44)]-4-[v1]", views: profileImageView, newsTextView)
    }

    func actionTap() {  // handle function
         sourceController?. imageTapped()
    }


}


回答3:

imageTapped have param, so you must addtarget:

feedCell.newsMenu.addTarget(self, action: #selector(imageTapped(_:)), for: .touchUpInside)