I am trying to implement an Edit button inside a cell.
Please refer to image:
What I done so far:
MainController:
class MainCo
If touch action on UIButton is not detecting.
To enable touch action on the UIButton of your Custom UICollectionCell, add the below method in your Custom UICollectionCell class.
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
}
You might want to use a tag for a simpler approach, but I always implement a delegate pattern in the case of buttons inside cells
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
}
}
Using this method will allow you to have multiple buttons inside a cell. Use a different delegate method for each button
A very reliable and flexible pattern is to assign a "Callback Closure" to your cell. Put your button action handler inside the cell, and have it "call back" to the view controller.
Here is a basic example (you should be able to implement it with your custom cell with no problem):
//
// 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)
}
@objc 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
}
}
How your buttonpress
method will know,you are selecting which cell button.So you can differentiate with tag
Add in cellForItemAtindexPath
ButtonObject.tag = indexPath.item
and
func buttonPressed(_ sender: UIButton)
{
print("buttonPressed ! \(sender.tag)")
}
func setupViews() {
...
addSubview(editButton)
editButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
}
func buttonPressed(sender:UIButton){
print("buttonPressed !")
}
I have created the same scenario. The only difference is that I have used UIButton
instead of RaisedButton
. And it is working perfectly fine.
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
methods
//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 !")
}