UICollectionViewCell

To render something more than solid color rectangles, we need a custom cell view that will be used to display the data. With that in mind, we have to create a custom cell class which inherits from UICollectionViewCell. Because we will construct those cells with code (not using a storyboard layout), then we have to implement a specific constructor. If we have to use a storyboard, then we should implement the  init(coder:NSCoder) method. It's called once the storyboard is rendered on the screen.

Here is how we can start:

/**
* Custom UICollectionViewCell which has a label on top.
*/
class AnimalCollectionViewCell :UICollectionViewCell {
private var _label: UILabel

override init(frame: CGRect) {
let fr = CGRect(x: 0, y: 0, width: frame.size.width,
height: frame.size.height)
_label = UILabel(frame:fr)
super.init(frame: frame)

_label.text = "?"
_label.textAlignment = NSTextAlignment.center
addSubview(_label)
}

// used when the UI is initializes from storyboard
required init?(coder aDecoder: NSCoder) {
_label = UILabel()
super.init(coder:aDecoder)
_label.text = "?"

addSubview(_label)
}

public var emoji:String? {
set {
_label.text = newValue
}

get {
return _label.text
}
}
}

With the preceding code, we have defined a custom cell, which has a label with the same size as the cell. The text is centered.

Now, we should let our CollectionView know about this new cell which we want to use. We should register the new cell class:

self.collectionView?.register(AnimalCollectionViewCell.self, forCellWithReuseIdentifier: "Cell") 

We are simply replacing our current default cell class with this new, much powerful one. In general, we can register more than one cell type and mix those, but for simplicity, we will stick to only one.

Then, we have to replace the function which is invoked when a new cell should be displayed:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:AnimalCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! AnimalCollectionViewCell
cell.backgroundColor = .green

let animal = self.data[indexPath.row]
cell.emoji = animal
return cell
}

The key changes here are:

  1. The type of the cell is changed to AnimalCollectionViewCell.
  2. We fetch the current data from the collection:
let animal = self.data[indexPath.row]
  1. We update the cell's content using its interface:
cell.emoji = animal
  1. When we run the example, we will see that each cell displays the animal's name:

This is cool, but let's try to make our example a bit fancy. Why not try to display the emoji instead of regular text? Yes, we can achieve this pretty easily.

  1. Let's create a dictionary, next to our controller instance:
var animalsToEmoji = ["Cat": "", "Dog": "", "Bird": "" , "Mouse" : "", "Elephant" :"","Bear":""] 
  1. Then store that map (dictionary) in the UICollectionView. First, add a property to the CollectionViewController:
var dataMap:[String:String]?
  1. Then, assign the dictionary to our controller instance:
controller.dataMap = animalsToEmoji
  1. Use the data from the map. Add the following rows before the return statement in the collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) method:
if self.dataMap != nil {
cell.emoji = self.dataMap?[animal]
} else {
cell.emoji = animal
}
  1. Here is the final result:

It's good to know when an item has been selected. To do so, we have to set a delegate to the UICollectionView and when an item is selected (touched), then a specific method from that delegate will be invoked.

The delegation is a design pattern which is used when specific duties should be delegated to an unknown type. The only restriction is that this type should implement a specific protocol (fulfill certain requirements). Usually, the class which delegates some actions defines a protocol, which will be used when those actions are activated. The delegate will be invoked when an action is triggered.

In our particular example, we need a UICollectionViewDelegate. We can create a new instance which conforms to the UICollectionViewDelegate protocol (we will see protocols later in this chapter) or we can use CollectionViewController, which already conforms to this protocol. The only thing is to override the function as follows:

override public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let animal = self.data[indexPath.row]
print(animal)
}

Once you see a working example, if you click on certain cells, the name of the animal will be printed in the console.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.186.167