iOS Revisited: UICollectionView

Hot

Post Top Ad

Showing posts with label UICollectionView. Show all posts
Showing posts with label UICollectionView. Show all posts

2 Nov 2017

PageView using UICollectionView in iPhone X - Swift,UIPageViewController

11/02/2017 12:08:00 pm 0
In most of the apps you use pageviewcontroller. Here we will show how to create page view easily with collection view.

In this article we are going to add subviews programmatically.

PageView  Using  UICollectionView

Download complete project at the bottom of this article.
First create a new project and name it as you like and save.

Add collection View:

First we need to add collection view. We do this using constraints.

Initially open ViewController.swift, add the following property:

var collectionView : UICollectionView!

Next add the following method:

func addCollectionView() {
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    
    collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
    collectionView.dataSource = self
    collectionView.delegate = self
    collectionView.backgroundColor = UIColor.white
    
    self.view.addSubview(collectionView)
    
    collectionView.translatesAutoresizingMaskIntoConstraints = false
    
    collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0).isActive = true
    collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0).isActive = true
    collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0).isActive = true
    collectionView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0.0).isActive = true
}

In above method we added collection view as subview to the main view using constraints.

Add cellId property as follow:

let cellId = "Cell"

Next add the following lines of code in viewDidLoad() method:

addCollectionView()
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)

Then add the delegates methods as follow:

extension ViewController: UICollectionViewDelegateFlowLayout,UICollectionViewDelegate,UICollectionViewDataSource {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return imageNames.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath as IndexPath) as! CustomCollectionViewCell
        cell.backgroundColor = UIColor.red
        return cell
    }
}

Now build and run we see normal collection view as follow:

UICollectionView in Swift

Create Custom Collection Cell:

Create new file and name it as "CustomCollectionViewCell". This must be subclass UICollectionViewCell .

Open CustomCollectionViewCell.swift file and add the following code:

let imageView : UIImageView = {
    let imageView = UIImageView()
    imageView.contentMode = .scaleAspectFill
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.clipsToBounds = true
    return imageView
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    
    addSubview(imageView)
    imageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0.0).isActive = true
    imageView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0.0).isActive = true
    imageView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0.0).isActive = true
    imageView.topAnchor.constraint(equalTo: topAnchor, constant: 0.0).isActive = true
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

Next replace the following line in viewDidLoad() method:

collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)

With

collectionView.register(CustomCollectionViewCell.self, forCellWithReuseIdentifier: cellId)

Then add the following code in addCollectionView() right after the layout creation:

layout.scrollDirection = .horizontal
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0

Add some images to project and add the image names as array:

let imageNames = ["Image1", "Image2", "Image3", "Image4"]

Next add the following delegate method inside extension as follow:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: view.frame.width, height: view.frame.height)
}

Finally add paging enabled to collection view. Add the following line inside addCollectionView() method:

collectionView.isPagingEnabled = true

Now build and run we see page View as follow:

PageView using UICollectionView

Looking good! But page control is missing.....

Adding Page Control:

For adding page control first add property as follow:

let pageControl = UIPageControl()

Next add the following two methods:

func addPageControl() {
    self.view.addSubview(pageControl)
    
    pageControl.translatesAutoresizingMaskIntoConstraints = false
    
    pageControl.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0).isActive = true
    pageControl.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0).isActive = true
    pageControl.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0).isActive = true
    pageControl.heightAnchor.constraint(equalToConstant: 50).isActive = true
    
    pageControl.backgroundColor = UIColor.clear
    pageControl.numberOfPages = imageNames.count
    pageControl.currentPage = 0
    pageControl.pageIndicatorTintColor = UIColor.red
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    pageControl.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width)
}

Call addPageControl() method in viewDidLoad() method after addCollectionView() method:

Now Run the project, finally we see actual page view with page control.

PageView using UICollectionView in Swift - UIPageViewController

Download sample project with example :

Read More

13 Sept 2017

Toggle between ListView(UITableView) and GridView(UICollectionView) - iOS, Swift 4

9/13/2017 04:09:00 am 1
In this article we are creating a sample project on how to switch between ListView and GridView.

Toggle between ListView(UITableView) and GridView(UICollectionView) - iOS, Swift 4

This Article Covers Following Related questions  :

How to Switch Between List View and Grid View in iOS.
UICollectionView - ListView and GridView.
Change the flow layout of a collectionView – from grid to list view.
Converting a UICollectionView to a UITableView.
Swift ios switching between listview and gridview
uitableview uicollectionview switch
uicollectionview table layout


In iOS native We call ListView as UITableView and GridView as UICollectionView.

Every one thinks that we need to take both UITableView & UICollectionView to achieve our goal. But that's Wrong.

We can achieve using UICollectionView itself. Let's see how simple to create ListView and GridView with UICollectionView.

Before starting this tutorial please read How to create UICollectionView.

If already done then download the starter project from here.


Open the file UICollectionViewProgramitically-master then open 'UICollectionViewProgramitically.xcodeproj'.

Build and run we can see Collection View or Grid Layout.

UICollectionViewProgramitically
We are going to use same project for the ListView also.

Getting Started :

Initially change project name to ListAndGrid.

Xcode App name change

Then a new pop window comes like follow:

App name change Confirmation

Tap on rename, then OK. Build and Run nothing changed.

First step is we need to create List cell and Grid cell. Grid cell already present as Custom Cell. List cell is not exists.


Creating ListCell :

So first create List cell. Add the following code at the end of ViewController.Swift file.
class ListCell : UICollectionViewCell {
    override init(frame: CGRect) {
        super.init(frame: frame)
        setUpViews()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Next add imageView, Title Label and Description label to ListCell.

So, add the following code for adding sub views to ListCell :

let imgView : UIImageView = {
    let imageView = UIImageView()
    imageView.image = UIImage(named: "car.jpg")
    imageView.contentMode = .scaleAspectFill
    imageView.clipsToBounds = true
    imageView.translatesAutoresizingMaskIntoConstraints = false
    return imageView
}()

let titleLabel : UILabel = {
    let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.title2)
    
    return label
}()

let descriptionLabel : UILabel = {
    let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.numberOfLines = 0
    label.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
    return label
}()

After creating sub views we need to add them as sub views with proper layout.

Add the following method to the end of ListCell:

func setUpViews() {
    backgroundColor = UIColor.init(red: 245.0/255.0, green: 245.0/255.0, blue: 245.0/255.0, alpha: 1.0)
    addSubview(imgView)
    addSubview(titleLabel)
    addSubview(descriptionLabel)
    imgView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0).isActive = true
    imgView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0).isActive = true
    imgView.topAnchor.constraint(equalTo: topAnchor, constant: 0).isActive = true
    imgView.widthAnchor.constraint(equalToConstant: frame.height).isActive = true
    
    titleLabel.leadingAnchor.constraint(equalTo: imgView.trailingAnchor, constant: 8).isActive = true
    titleLabel.topAnchor.constraint(equalTo: imgView.topAnchor, constant: 4).isActive = true
    titleLabel.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
    
    descriptionLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4).isActive = true
    descriptionLabel.leadingAnchor.constraint(equalTo: imgView.trailingAnchor, constant: 8).isActive = true
    descriptionLabel.bottomAnchor.constraint(equalTo: imgView.bottomAnchor, constant: -4).isActive = true
    descriptionLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8).isActive = true
    descriptionLabel.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
}

Great we created ListCell. Next step is we need to add ListCell to UICollectionView.

Before that we need to add some Global variables. Add the following code after Cell Identifier :

let listCellIdentifier = "ListCell"

var isListView = false

var toggleButton = UIBarButtonItem()

Next, register the ListCell to create new cells in collection View and add Toggle Button to Navigation Bar. Add the following code inside viewDidLoad() method :
collectionView?.register(ListCell.self, forCellWithReuseIdentifier: listCellIdentifier)

toggleButton = UIBarButtonItem(title: "List", style: .plain, target: self, action: #selector(butonTapped(sender:)))
self.navigationItem.setRightBarButton(toggleButton, animated: true)

Add the following method that calls when Ever toggle Button has been tapped.
@objc func butonTapped(sender: UIBarButtonItem) {
    if isListView {
        toggleButton = UIBarButtonItem(title: "List", style: .plain, target: self, action: #selector(butonTapped(sender:)))
        isListView = false
    }else {
        toggleButton = UIBarButtonItem(title: "Grid", style: .plain, target: self, action: #selector(butonTapped(sender:)))
        isListView = true
    }
    self.navigationItem.setRightBarButton(toggleButton, animated: true)
    self.collectionView?.reloadData()
}

The above method will check the condition whether to show list or grid then reloads the collection View to show the corresponding view.

Then Replace the code inside cellForItemAt method with the following code:

if isListView {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: listCellIdentifier, for: indexPath) as! ListCell
    cell.titleLabel.text = "Ferrari 812 Superfast"
    cell.descriptionLabel.text = "The car has a larger 6.5-liter V12 engine compared to the 6.3-liter used in the F12berlinetta. The engine produces 800 PS (588 kW, 789 bhp) at 8,500 rpm and 718 N·m (530 lbf·ft) of torque at 7,000 rpm. The 812 Superfast's V12 engine is, in 2017, the most powerful naturally aspirated production car engine ever made."
    return cell
}else {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! CustomCell
    return cell
}

The main and important thing for changing the ListView and GridView is the Size of CollectionViewCell.

So ListCell means the width must equal to the device width. So, replace the code inside sizeForItemAt method with the following code.

let width = view.frame.width
if isListView {
    return CGSize(width: width, height: 120)
}else {
    return CGSize(width: (width - 15)/2, height: (width - 15)/2)
}

Great, Build and Run now we will see GridView. Tap on List button the view changes from grid to list and Vice-versa.

Switching between ListView(UITableView) and GridView(UICollectionView) - iOS, Swift 4

Download sample project with examples :


Read More

5 Sept 2017

UICollectionView Programmatically With Out Main.storyboard - Swift, iOS

9/05/2017 10:04:00 am 0
In this article we are going to create a sample project which explains all about UICollectionView.

In other programming languages collection view is called as grid View.

How to create UICollectionView using Swift without storyboards.

This Article Covers All Related questions  :

How to create UICollectionView using Swift without storyboards.
create uicollectionview programmatically swift 3.
uicollectionview programmatically example.
custom uicollectionviewcell programmatically swift.
programmatically create uicollectionview swift.
uicollectionview swift example.
uicollectionview custom cell example.



UICollectionView :

An object that manages an ordered collection of data items and presents them using customizable layouts.

Mainly collection view layout is used for displaying images rather than content.


Sample Project :

Firstly create a new project  open Xcode -> File -> New -> Project -> Single View App, then tap next button. Type product name as 'UICollectionViewProgramitically' then tap next and select the folder to save project.

We are not going to use Main.storyboard, so delete it and tap on 'Move to trash'.

 

Main.storyboard, so delete it and tap on 'Move to trash'.

Now if you run the project, it will crash with a reason 'Could not find a storyboard named 'Main' in bundle'. So fix that, go to project general settings and under 'Deployment Info' delete Main from 'Main Interface'.




'Main Interface'  to empty

Now run we will see black screen with out any crash. Good!


Let's get started. Open ViewController.swift them change class name from ViewController to UICollectionViewController.

Open AppDelegate.swift, add the following code inside 'didFinishLaunchingWithOptions' method.

window = UIWindow(frame: UIScreen.main.bounds) // 1
window?.makeKeyAndVisible()
let layout = UICollectionViewFlowLayout() // 2
let viewController = ViewController(collectionViewLayout: layout) // 3
window?.rootViewController = UINavigationController(rootViewController: viewController) // 4

1. Creating a window of size equal to device size. This window will keep all View Controllers hierarchy.

2. UICollectionViewFlowLayout is a default layout for collection View.


3. Initializing the ViewController with default layout.


4. Setting up the rootViewController to the window. We embedded view Controller inside UINavigationController.

Build and Run we still see the black background but here we are having navigation bar too.

Navigation bar

Creating Custom CollectionViewCell:

Firstly we will start with Custom Cell. Add the following class at the end of view controller class.
class CustomCell: UICollectionViewCell{
    
}

First we need to initialize cell. So add the following code inside CustomCell.
override init(frame: CGRect) {
    super.init(frame: frame)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

In this collection view we are going to show images so, let's create imageView. Add the following code after init(frame: CGRect) method :
let imgView : UIImageView = {
    let imageView = UIImageView()
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.image = UIImage(named: "car.png")
    imageView.contentMode = .scaleAspectFill
    return imageView
}()

Here we are showing car image, so drag the image to the project and name it as car.png.

Then add the imgView to cell and provide auto layout as we required. Add the following code inside init(frame: CGRect) method :
addSubview(imgView)
imgView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
imgView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
imgView.topAnchor.constraint(equalTo: topAnchor).isActive = true
imgView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true

Great we created custom collection view cell.

Next step is adding custom cell to collection view.

Add Custom cell to Collection View :

First create cell identifier. Add the following line before viewDidLoad() method.
let cellIdentifier = "ImageCell"

Next register collection view with custom class. Add the following code inside viewDidLoad() method:
collectionView?.backgroundColor = UIColor.white
collectionView?.register(CustomCell.self, forCellWithReuseIdentifier: cellIdentifier)

There are two delegate methods which are required

1. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int

2. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

First one is for number of cells we need in a section.

Second one is for, which cell we are going to use. We can use different custom cells in one UICollectionView. Here we have one cell so no worries.

Add the following delegate methods : 

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 6
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! CustomCell
    
    return cell
}

Build and Run, we will see images. Great working fine but the padding between cell are not looking great.

create uicollectionview programmatically swift 3.


For that we have different delegate layout methods. We use some of them for our layout.


First add UICollectionViewDelegateFlowLayout delegate next to UICollectionViewController class.

Then add the following methods for layout and padding.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = view.frame.width
    return CGSize(width: (width - 15)/2, height: (width - 15)/2)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 5
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 5
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
}

Now Build and Run, we see car images with good looking.

create uicollectionview programmatically swift 3.
Download sample project with examples :

Read More

Post Top Ad