Swift 3-如何在UICollectionViewCell中获取按钮
我正在尝试在单元格中实现“编辑”按钮。
请参考图片:
到目前为止我做了什么:
MainController:
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 !") } }
ImgItemCell:
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) ... } }
结果:该按钮无法点击。 单击按钮时不会打印日志。
在android中,我通过按钮的OnClickListener
完成此OnClickListener
,以执行每行的操作。 我怎样才能在Swift 3中做同样的事情?
解决方案:(这对我有用)
大家好,谢谢你的所有建议,他们更不用说我来解决问题了。
我的问题的根本原因是视图层次结构(正如@DatForis指出的那样)
说明:我想要一个单元格包含图像和按钮布局,以便我有如下的视图层次结构
override func setupViews() { super.setupViews() addSubview(imgView) addSubview(buttonLayout) buttonLayout.addSubView(buttonList) buttonList.addSubview(editButton) buttonList.addSubview(shareButton) }
这个层次结构以某种方式阻止了按钮的click事件。
因此,我在层次结构中改变了一点
override func setupViews() { super.setupViews() addSubview(imgView) addSubview(buttonLayout) buttonLayout.addSubview(editButton) buttonLayout.addSubview(shareButton) }
和BAM! 它就像一个魅力。
事实上,我需要一个正确的解释,说明层次结构对儿童的影响。
顺便说一句,我认为这里的大多数回复都是可行的解决方案,但我选择了@DonMag作为最终答案,因为它干净而清晰,对Controller有很酷的回调。
但同样,我的根本问题来自视图层次结构。
一个非常可靠和灵活的模式是为您的单元格分配一个“回调关闭”。 将您的按钮操作处理程序放在单元格中,并让它“回调”到视图控制器。
这是一个基本示例(您应该可以使用自定义单元格实现它而没有问题):
// // 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 } }
您可能希望使用标记来实现更简单的方法,但是对于单元格内的按钮,我总是实现委托模式
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 } }
使用此方法将允许您在单元格内有多个按钮。 为每个按钮使用不同的委托方法
你的buttonpress
方法如何知道,你正在选择哪个单元格按钮。所以你可以区分tag
添加cellForItemAtindexPath
ButtonObject.tag = indexPath.item
和
func buttonPressed(_ sender: UIButton) { print("buttonPressed ! \(sender.tag)") }
我创建了相同的场景。 唯一的区别是我使用了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 } func buttonPressed() { print("buttonPressed !") }
func setupViews() { ... addSubview(editButton) editButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside) } func buttonPressed(sender:UIButton){ print("buttonPressed !") }