I'd like to create a collection view where each collection cell is customizable and has a description and a button in each one, each cell should lead to another view controller, something like this.
-
So what's stopping you from creating a custom cell? What have you tried so far?almas– almas2017-06-19 23:45:54 +00:00Commented Jun 19, 2017 at 23:45
-
I have been able to only create a collection view with images but I really don't know how to convert those to custom button cellsFrancisco Ruiz– Francisco Ruiz2017-06-19 23:47:55 +00:00Commented Jun 19, 2017 at 23:47
-
Have you tried dragging a button into your custom cell in your storyboard?rob mayoff– rob mayoff2017-06-19 23:52:06 +00:00Commented Jun 19, 2017 at 23:52
-
yes but when I run the app on the simulator the cells disappear with the text, the button and the image inside it, also I can't make it so there are multiple cells in the storyboard that the ones that can't be seen easily, can be scrolled horizontally, just like in the images aboveFrancisco Ruiz– Francisco Ruiz2017-06-20 00:15:19 +00:00Commented Jun 20, 2017 at 0:15
-
UICollectionViewCells can behave just like buttons by implementing the UICollectionViewDelegate method didSelectItemAt:Brandon A– Brandon A2017-06-20 00:28:53 +00:00Commented Jun 20, 2017 at 0:28
2 Answers
Details
xCode 8.3.2, Swift 3.1
Full Sample
CollectionViewCell
import UIKit
protocol CollectionViewCellDelegate: class {
func touchUpInside(delegatedFrom cell: CollectionViewCell)
}
class CollectionViewCell: UICollectionViewCell {
@IBOutlet weak var button: UIButton!
weak var delegate: CollectionViewCellDelegate?
@IBAction func touchUpInside(_ sender: UIButton) {
delegate?.touchUpInside(delegatedFrom: self)
}
}
ViewController
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var collectionViewFlowLayout: UICollectionViewFlowLayout!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
collectionView.dataSource = self
collectionView.delegate = self
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let inset:CGFloat = 20.0
collectionViewFlowLayout.itemSize = collectionView.frame.size
collectionViewFlowLayout.itemSize.width -= inset*2
collectionViewFlowLayout.itemSize.height -= inset*2
collectionViewFlowLayout.sectionInset.left = inset
collectionViewFlowLayout.sectionInset.right = inset
}
}
extension ViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
cell.delegate = self
return cell
}
}
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Selected cell: \(indexPath)")
}
}
extension ViewController: CollectionViewCellDelegate {
func touchUpInside(delegatedFrom cell: CollectionViewCell) {
if let indexPath = collectionView.indexPath(for: cell) {
print("Button pressed in cell: \(indexPath)")
}
}
}
Main.storyboard
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="stackoverflow_44641545" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsVerticalScrollIndicator="NO" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="H99-jD-EE5">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="47T-Wc-WqB">
<size key="itemSize" width="351" height="610"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="CollectionViewCell" id="X5i-B5-0He" customClass="CollectionViewCell" customModule="stackoverflow_44641545" customModuleProvider="target">
<rect key="frame" x="0.0" y="18.5" width="351" height="610"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="351" height="610"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ng9-IJ-srl">
<rect key="frame" x="152.5" y="560" width="46" height="30"/>
<state key="normal" title="Button">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="touchUpInside:" destination="X5i-B5-0He" eventType="touchUpInside" id="mNT-vz-F9c"/>
</connections>
</button>
</subviews>
</view>
<color key="backgroundColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<constraints>
<constraint firstAttribute="bottomMargin" secondItem="ng9-IJ-srl" secondAttribute="bottom" constant="12" id="AGX-Ye-rNr"/>
<constraint firstItem="ng9-IJ-srl" firstAttribute="centerX" secondItem="X5i-B5-0He" secondAttribute="centerX" id="sFI-KT-pyQ"/>
</constraints>
<connections>
<outlet property="button" destination="ng9-IJ-srl" id="mnC-Ln-j2F"/>
</connections>
</collectionViewCell>
</cells>
</collectionView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="H99-jD-EE5" firstAttribute="bottom" secondItem="wfy-db-euE" secondAttribute="top" id="0hj-ig-J9f"/>
<constraint firstItem="H99-jD-EE5" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="NWe-0c-k9w"/>
<constraint firstItem="H99-jD-EE5" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" id="axO-mx-zBv"/>
<constraint firstAttribute="trailing" secondItem="H99-jD-EE5" secondAttribute="trailing" id="eP4-pi-EX2"/>
</constraints>
</view>
<connections>
<outlet property="collectionView" destination="H99-jD-EE5" id="Cje-QN-sIz"/>
<outlet property="collectionViewFlowLayout" destination="47T-Wc-WqB" id="qBp-S0-pyU"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="132" y="137.18140929535232"/>
</scene>
</scenes>
</document>
Result
Comments
For anyone that may be reading this after me, I found a way to use the other answer provided by Vasily Bodnarchuk to create buttons.
Following everything he did except for the Main.storyboard code (I was too confused to try to figure out how to implement it) I simply went into my ViewController and added a button to the UIViewControllerCell.
After that, I created a Segway from my UICollectionView to the next ViewController and gave it an identifier.
I tweaked the code provided above and added an "if" statement to his function that prints the selected cell:
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Selected cell: \(indexPath)")
if indexPath == [0,0] {
self.performSegue(withIdentifier: "toGridView", sender: self)
}
}
}
If you notice in the console, it prints the value of each cell and I used indexPath set to a value to reference the cell. In this code, the button (cell) at [0,0] will segue to the next ViewController when clicked.
You can do this for all of your buttons!
I'll attach screenshots just in case my description leaves you confused.






