Perform action on selection of UICollectionViewCell? - ios

I would like to call a function when a cell is pressed and I would like to be able to change what that function does based on what cell is pressed. Here is my code currently:
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
//#warning Incomplete method implementation -- Return the number of sections
return 4
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//#warning Incomplete method implementation -- Return the number of items in the section
return 10
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! UICollectionViewCell
// Configure the cell
return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
return CGSizeMake(90, 90)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets
{
return UIEdgeInsetsMake(10, 10, 10, 10)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat
{
return 10
}
// MARK: UICollectionViewDelegate
// Uncomment this method to specify if the specified item should be highlighted during tracking
override func collectionView(collectionView: UICollectionView, shouldHighlightItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
// Uncomment this method to specify if the specified item should be selected
override func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
// Uncomment these methods to specify if an action menu should be displayed for the specified item, and react to actions performed on the item
override func collectionView(collectionView: UICollectionView, shouldShowMenuForItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func collectionView(collectionView: UICollectionView, canPerformAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) -> Bool {
return true
}
override func collectionView(collectionView: UICollectionView, performAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) {
self.printThatItWorked()
}
func printThatItWorked()
{
println("It worked")
}
the function printThatItWorked() should be called whenever a cell is selected, and eventually I would like to be able to have it print that cell number x was pressed. How do I go about doing this?

The delegate method didSelectCell... is where you want to put that code.
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
// You can use indexPath to get "cell number x", or get the cell like:
let cell = collectionView.cellForItemAtIndexPath(indexPath)
printThatItWorked()
}

I figured it out. Implement this:
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
// You can use indexPath to get "cell number x", or get the cell like:
let cell = collectionView.cellForItemAtIndexPath(indexPath)
printThatItWorked()
}

Related

UIMenuController not showing custom action on UICollectionViewController subclass

I am trying to display a custom action using UIMenuController on a UICollectionViewController subclass, and even though the cut, copy and paste actions appears as expected, for some reason my custom action doesn't.
I followed a lot of references from the web but none of them makes it work, here the code:
class CollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
fileprivate var items = [MyClass]()
// MARK: - UICollectionViewDataSource
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellIdentifier", for: indexPath)
/* update cell properties */
return cell
}
// MARK: - UICollectionViewDelegate
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: itemSize, height: itemSize)
}
override func collectionView(_ collectionView: UICollectionView, canPerformAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
return true
}
override func collectionView(_ collectionView: UICollectionView, performAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) {
/* Do Something */
}
override func collectionView(_ collectionView: UICollectionView, shouldShowMenuForItemAt indexPath: IndexPath) -> Bool {
return true
}
public func menuAction(_ sender: UIMenuItem) {
/* Action method*/
}
}
Tried to add the menu item as follows:
let menuItem = UIMenuItem(title: SFLocalization.localizedString("Common-remove"), action: #selector(CollectionViewController.menuAction(_:)))
let menuController = UIMenuController.shared
// menuController.menuItems?.append(menuItem)
menuController.menuItems = [menuItem]
on both viewDidLoad and collectionView(_ collectionView:, shouldShowMenuForItemAt) -> Bool
Any ideas?
Omer - check out this link: http://dev.glide.me/2013/05/custom-item-in-uimenucontroller-of.html
Basically, moving these methods:
(BOOL)canPerformAction:(SEL)action withSender:(id)sender {
(BOOL)canBecomeFirstResponder {
... to the CollectionView cell subclass works. You then have to pass this selector back up to the cell delegate.
With this, I was able to get my custom menu to appear!

Multiple selections on collection view cells

I am trying to make an app with similar functionality to the Photos app that comes with iOS, I have the functionality that allows you to tap on a cell which expands the image to fit the screen, then tap the image to dismiss it. I now want to add the select button so that you can select multiple images that can be downloaded. I'm fairly new to this and have looked around but can't find an example that does both of these things. Any help would be great.
Update:
My current code:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imagesURLArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as! PhotoCell
cell.backgroundColor = .clear
cell.imageView.image = UIImage(contentsOfFile: imagesURLArray[indexPath.row].path)
cell.checkmarkView.isHidden = true
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,sizeForItemAt indexPath: IndexPath) -> CGSize {
let paddingSpace = sectionInsets.left * (itemsPerRow + 1)
let availableWidth = view.frame.width - paddingSpace
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: widthPerItem, height: widthPerItem)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,insetForSectionAt section: Int) -> UIEdgeInsets {
return sectionInsets
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return sectionInsets.left
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
addZoomedImage(indexPath.row)
addGestureToImage()
addBackGroundView()
view.addSubview(selectedImage)
}
Im not sure whereto go from here, whether its easier to add long tap gestures to select multiple images to download or to have the select button in the photos app both of which im a little clueless on where to start.
OK - one approach:
Design a custom button (or find one already made) that provides "CheckMark" functionality (tap to check/uncheck)
Add that button to your PhotoCell - maybe upper-left or upper-right corner
When the cell is tapped on the CheckMark button, toggle it checked/unchecked and send a message back to your controller to track its state
If the cell is tapped but not on the checkmark button, handle it as you do now with didSelectItemAt indexPath:
That's the general idea. A good next place for you is probably to take a look at some examples found by searching for uicollectionviewcell check mark
//works in swift 3.3 Hope it helps
//my model struct
struct Brands {
var brandId: Int = 0
var productId: Int = 0
var name: String = ""
var isChecked:Bool = false
}
var arrBrands = []//initialise arr of model
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return arrBrands.count
}
func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let identifier: String = "brandCell"
let cell: YourCustomCell? =
collectionView.dequeueReusableCell(withReuseIdentifier: identifier,
for: indexPath) as? YourCustomCell;
let isChecked = arrBrands[indexPath.row].isChecked
cell?.brandName.font = (isChecked) ?fontForTimesRoman(withStyle:"bold", andFontsize: 14):fontForTimesRoman(withStyle: "regular",
andFontsize: 14)
cell?.brandName.text = arrBrands[indexPath.row].name
cell?.brandCheckButt.setImage((isChecked) ?UIImage(named:"filled_checkmark.png"):UIImage(named:"empty_checkmark.png"), for: .normal)
return cell!
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
checkUncheckBrand(index: indexPath.row)
}
func collectionView(_ collectionView: UICollectionView,
didDeselectItemAt indexPath: IndexPath) {
checkUncheckBrand(index: indexPath.row)
}
func checkUncheckBrand(index:Int){
arrBrands[index].isChecked = ! (arrBrands.isChecked)
brandFilterCV.reloadData()
}

UIcollectionview cell issue Swift

I have a simple collectionview controller like this:
class ViewController1: UICollectionViewController{
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView?.delegate = self
self.collectionView?.dataSource = self
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "P", for: indexPath)
return cell
}
}
In the cell there is only an uiimageview and it has this constraints:
My problem is this:
when I execute this code on iPhone 6 simulator I get this (right way):
but when I execute this code on iPhone 5 simulator I get this (wrong way: the imageview starts before the screen on the left and the width and height are wrong respect to the constraints):
I am going crazy for this problem but I dont be able to solve.
Can you help me?
You need to extend your ViewController1 to conform to UICollectionViewDelegateFlowLayout protocol. And implement methods to set size for each collection view cell like so:
class ViewController1: UICollectionViewController, UICollectionViewDelegateFlowLayout {
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView?.delegate = self
self.collectionView?.dataSource = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print(self.collectionView!.frame)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "P", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.collectionView!.frame.size.width, height: 120.0)
}
}
It has hard coded values, but you should get the idea. Collection View width should be the max size for each item, so they won't get outside the box.

how can we achieve appearance of collection view as shown in image below?

Also i need to have circular scrolling enabled for that collection view.
Can anyone please help me out?
First of all drag collection view in your respective ViewController and then select scroll direction as Horizontal in activity inspector.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return collectionView.frame.size.width/2
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake((collectionView.frame.size.height) , (collectionView.frame.size.height))
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return img_Arr.count
}
// make a cell for each cell index path
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell3", forIndexPath: indexPath) as! ImageCaptureCell
cell.CapturedImage.clipsToBounds = true
cell.contentView.frame = cell.bounds
let capt = UIImage(data:img_Arr[indexPath.row] as! NSData,scale:1.0)
cell.CapturedImage.image = capt
return cell
}
// MARK: - UICollectionViewDelegate protocol
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
// handle tap events
print("You selected cell #\(indexPath.item)!")
}
func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath)
{
let cell = collectionView.cellForItemAtIndexPath(indexPath)
//cell?.backgroundColor = UIColor.redColor()
}
// change background color back when user releases touch
func collectionView(collectionView: UICollectionView, didUnhighlightItemAtIndexPath indexPath: NSIndexPath) {
let cell = collectionView.cellForItemAtIndexPath(indexPath)
// cell?.backgroundColor = UIColor.yellowColor()
}
Additionaly give search bar on top and connet to the table delegate

Item spacing in UICollectionView iOS

I am creating an application in which i want to use UICollectionView. I have used this, but i am seeing the black space between to items and two items are moved to left and right side of screen.
internal func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 20
}
internal func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("productCell", forIndexPath: indexPath) as! ProductCell
return cell
}
internal func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
{
return 1
}

Resources