Swift 3-如何在UICollectionViewCell中获取按钮

时间:2017-06-05 12:02:07

标签: ios swift material-design

我正在尝试在单元格中实现“编辑”按钮。

请参考图片:
enter image description here

到目前为止我做了什么:

MainController:

this

ImgItemCell:

class MainController: UICollectionViewController, UICollectionViewDelegateFlowLayout  {
  let imgCellId = "imgCellId"

  override func viewDidLoad() {
    collectionView?.backgroundColor = .white
    collectionView?.register(ImgItemCell.self, forCellWithReuseIdentifier: imgCellId)
  }

  override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {   
      let cell = collectionView.dequeueReusableCell(withReuseIdentifier: imgCellId, for: indexPath) as! ImgItemCell
      cell.editButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)

      return cell
  }

  func buttonPressed(){
    print("buttonPressed !")
  }

}

结果:该按钮无法点击。单击按钮时不会打印日志。

在android中,我通过按钮import Material class ImgItemCell: UICollectionViewCell{ override init(frame: CGRect){ super.init(frame: frame) setupViews() } ... let editButton: RaisedButton = { let button = RaisedButton(title: "Edit", titleColor: .black) return button }() func setupViews(){ ... addSubview(editButton) ... } } 完成此操作,以执行每行的操作。我怎样才能在Swift 3中做同样的事情?

解决方案:(它为我工作)

大家好,谢谢你们提出的所有建议,他们更不用说我提出解决方案了。

我的问题的根本原因是视图层次结构(如@DatForis指出的那样)

说明:我想要一个单元格包含图像和按钮布局,以便我有如下的视图层次结构

OnClickListener

此层次结构以某种方式阻止了按钮的单击事件。

因此,我在层次结构中改变了一点

override func setupViews() {
    super.setupViews()

    addSubview(imgView)
    addSubview(buttonLayout)
    buttonLayout.addSubView(buttonList)
            buttonList.addSubview(editButton)
            buttonList.addSubview(shareButton)
  }

和BAM!它就像一个魅力。

事实上,我需要正确解释层次结构对儿童的影响。

顺便说一下,我认为这里的大多数回复都是可行的解决方案,但我选择了@DonMag作为最终答案,因为它干净清晰,并且有一个很酷的回调控制器。

但同样,我的根本问题来自视图层次结构。

6 个答案:

答案 0 :(得分:8)

您可能希望使用标记来实现更简单的方法,但是对于单元格内的按钮,我总是实现委托模式

protocol MyCollectionViewCellDelegate: class {
    func button(wasPressedOnCell cell: MyCollectionViewCell)
}
class MyCollectionViewCell: UICollectionViewCell {
    weak var delegate: MyCollectionViewCellDelegate?
    var data: String = "DATA"
    @IBAction func buttonWasPressed(sender: UIButton){
        delegate?.button(wasPressedOnCell: self)
    }

}
class MainViewController: UIViewController, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "reuse", for: indexPath) as! MyCollectionViewCell
        cell.delegate = self
        return cell
    }
}
extension MainViewController: MyCollectionViewCellDelegate{
    func button(wasPressedOnCell cell: MyCollectionViewCell) {
        //do what you want with the cell and data
    }
}

使用此方法将允许您在单元格内有多个按钮。为每个按钮使用不同的委托方法

答案 1 :(得分:7)

一种非常可靠和灵活的模式是为您的单元格分配“回调关闭”。将您的按钮操作处理程序放在单元格中,并让它“回调”到视图控制器。

这是一个基本示例(您应该可以使用自定义单元格实现它而没有问题):

//
//  CViewWithButtonCollectionViewController.swift
//  SWTemp2
//
//  Created by Don Mag on 6/5/17.
//  Copyright © 2017 DonMag. All rights reserved.
//

import UIKit

private let reuseIdentifier = "ImgItemCell"

class ImgItemCell: UICollectionViewCell {

    // this will be our "call back" action
    var btnTapAction : (()->())?

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

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupViews()
    }

    let editButton: UIButton = {
        let button = UIButton(type: UIButtonType.system)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.backgroundColor = .white
        button.setTitle("Edit", for: .normal)
        return button
    }()

    func setupViews(){

        // add a button
        addSubview(editButton)

        editButton.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
        editButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true

        // add the touchUpInside target
        editButton.addTarget(self, action: #selector(btnTapped), for: .touchUpInside)

    }

    func btnTapped() {
        print("Tapped!")

        // use our "call back" action to tell the controller the button was tapped
        btnTapAction?()
    }

}

class CViewWithButtonCollectionViewController: UICollectionViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
            layout.itemSize = CGSize(width: 300, height: 100)
        }

    }

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ImgItemCell

        cell.backgroundColor = .red

        // set a "Callback Closure" in the cell
        cell.btnTapAction = {
            () in
            print("Edit tapped in cell", indexPath)
            // start your edit process here...
        }

        return cell
    }

}

答案 2 :(得分:1)

我创建了相同的场景。唯一的区别是我使用了UIButton而不是RaisedButton。它工作得很好。

1。ImgItemCell

class ImgItemCell: UICollectionViewCell
{
    //MARK: View Lifecycle Methods
    override func awakeFromNib()
    {
        super.awakeFromNib()
        setupViews()
    }

    let editButton: UIButton = {
        let button = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 50))
        button.setTitle("Edit", for: .normal)
        return button
    }()

    func setupViews()
    {
        addSubview(editButton)
    }
}

2. MainController方法

//MARK: UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
    return 10
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: imgCellId, for: indexPath) as! ImgItemCell
    cell.editButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
    return cell
}

@objc func buttonPressed()
{
    print("buttonPressed !")
}

答案 3 :(得分:0)

您的buttonpress方法如何知道,您正在选择哪个单元格按钮。因此,您可以与tag区分开来 加入cellForItemAtindexPath

ButtonObject.tag = indexPath.item

func buttonPressed(_ sender: UIButton)
    {
        print("buttonPressed ! \(sender.tag)")
    }

答案 4 :(得分:0)

func setupViews() {
    ...
    addSubview(editButton)
    editButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
}

func buttonPressed(sender:UIButton){
    print("buttonPressed !")
}

答案 5 :(得分:0)

如果未检测到UIButton上的触摸动作。

要在Custom UICollectionCell的UIButton上启用触摸操作,请在Custom UICollectionCell类中添加以下方法。

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    var view = myButton.hitTest(myButton.convert(point, from: self), with: event)
    if view == nil {
        view = super.hitTest(point, with: event)
    }

    return view
}