Weird gap at the top of the collection view - ios

Not sure what's going on. Could this be a collectionView bug on iOS 8? The black at the top should not be there...
View Controller Code:
class SearchViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
#IBOutlet var collectionView: UICollectionView!
// MARK: - VC Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
var viewNib = UINib(nibName: "SearchFiltersCollectionReusableView", bundle: nil)
collectionView.registerNib(viewNib, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "filter")
var viewNib2 = UINib(nibName: "SearchResultCollectionViewCell", bundle: nil)
collectionView.registerNib(viewNib2, forCellWithReuseIdentifier: "searchCell")
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - CV Datasource
func numberOfSectionsInCollectionView(collectionView: UICollectionView!) -> Int {
return 2
}
func collectionView(collectionView: UICollectionView!, numberOfItemsInSection section: Int) -> Int {
var itemsCount = section == 1 ? 10 : 0
return itemsCount
}
func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell! {
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("searchCell", forIndexPath: indexPath) as UICollectionViewCell
return cell
}
// MARK: - CV Delegate
func collectionView(collectionView: UICollectionView!, viewForSupplementaryElementOfKind kind: String!, atIndexPath indexPath: NSIndexPath!) -> UICollectionReusableView! {
var section = indexPath.section
var identifier = indexPath.section == 0 ? "nav" : "filter"
var view = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: identifier, forIndexPath: indexPath) as UICollectionReusableView
return view
}
// MARK: - CV DelegateFlow
func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize {
var width = collectionView.bounds.size.width
return CGSizeMake(width, 70)
}
func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, referenceSizeForHeaderInSection section: Int) -> CGSize {
var width = collectionView.bounds.size.width
var height : CGFloat = section == 0 ? 240.0 : 70.0
return CGSizeMake(width, height)
}
}

Try setting the view controller automaticallyAdjustsScrollViewInsets property to NO.

Related

CollectionView delegate methods are not calling from TableViewCell

Delegate isn't being called from tableViewCell. Here is UICollectionViewDelegate and UICollectionViewDataSource code
extension HomeVC:UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout{
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProductCell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("ok")
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let lay = collectionViewLayout as! UICollectionViewFlowLayout
lay.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
lay.minimumInteritemSpacing = 0
lay.minimumLineSpacing = 0
collectionView.collectionViewLayout = lay
let size = (collectionView.frame.size.width-10) / 2
return CGSize(width: size, height: size)
}
}
swift 5
//MARK:- Tableview Datasource method
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"RecentLoanApplicationCell") as! RecentLoanApplicationCell
cell.collectionVC.delegate = self
cell.collectionVC.dataSource = self
cell.btnViewAll.addTarget(self, action: #selector(btnViewALLTap(button:)), for: .touchUpInside)
DispatchQueue.main.async {
cell.collectionVC.reloadData()
}
return cell
}
//MARK:- Tableview Cell in side custom cell Register for collectionView cell
class RecentLoanApplicationCell: UITableViewCell {
#IBOutlet var collectionVC:UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
self.collectionVC.register(UINib.init(nibName:"RecentLoanCollectionViewCell", bundle: nil), forCellWithReuseIdentifier:"RecentLoanCollectionViewCell")
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
// Same ControllerView call
//MARK:- Collection DataSource & Delegate
extension HomeViewController : UICollectionViewDelegate,UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier:"RecentLoanCollectionViewCell", for: indexPath) as! RecentLoanCollectionViewCell
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
debugPrint("didSelectItemAt ==>\(indexPath.row)")
}
Here is the code how I done for same inside TableViewCell using collectionView and performed selection :
Code inside TableView datasource method :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BasicCarColorCell", for: indexPath) as! BasicCarColorCell
cell.dataSource = preloads.colors
cell.collectionViewSetup()
cell.delegate = self
return cell
}
Code for TableViewCell:
protocol BasicCarColorCellDelegate {
func colorCell(cell:BasicCarColorCell, didSelect color: Color)
}
class BasicCarColorCell: UITableViewCell {
var dataSource = Array<Color>()
var selectedColor = Color()
#IBOutlet weak var textView: RSKPlaceholderTextView!
#IBOutlet weak var guideLineMessage:UILabel!
#IBOutlet weak var collectionView: UICollectionView!
var delegate: BasicCarColorCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func collectionViewSetup() {
let nib = UINib(nibName: "BasicCarColorCollectionCell", bundle: nil)
self.collectionView.register(nib, forCellWithReuseIdentifier: "BasicCarColorCollectionCell")
let flowLayout = UICollectionViewFlowLayout()
flowLayout.minimumLineSpacing = 0
flowLayout.minimumInteritemSpacing = 0
flowLayout.scrollDirection = .horizontal
collectionView.collectionViewLayout = flowLayout
collectionView.dataSource = self
collectionView.delegate = self
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension BasicCarColorCell: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.dataSource.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BasicCarColorCollectionCell", for: indexPath) as! BasicCarColorCollectionCell
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height = collectionView.bounds.size.height-2
let width = height-20
return CGSize(width: width, height:height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 1, left: 10, bottom: 1, right: 10)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let color = self.dataSource[indexPath.item]
self.selectedColor = color
delegate?.colorCell(cell: self, didSelect: self.selectedColor)
collectionView.reloadData()
}
}
And to handle the selection of collectionView just implement the method of custom protocol written in TableViewCell in ViewController:
func colorCell(cell: BasicCarColorCell, didSelect color: Color) {
//self.selectedCarColor = color.value
}
You can do it in same pattern as per your need.
Hope it'll help!
You need to set datasource and delegate for collectionView, every time in Tableview delegate CellForRowAtIndexPath.

How to have different cell size in flowlayout

This is what I am able to make through a tutorial
This is the Screenshot of the app
But I have to make 1st and every 3rd Cell to be full width. How I supposed to do it?
The code is this
class MainViewController: UICollectionViewController
{
// data source
let publishers = Publishers()
private let leftAndRightPaddings: CGFloat = 32.0
private let numberOfItemsPerRow: CGFloat = 2.0
private let heigthAdjustment: CGFloat = 100
// MARK: - View controller life cycle
override func viewDidLoad() {
super.viewDidLoad()
let width = (CGRectGetWidth(collectionView!.frame) - leftAndRightPaddings) / numberOfItemsPerRow
let layout = collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSizeMake(width, heigthAdjustment)
print(width.description)
}
// MARK: - UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return publishers.numberOfPublishers
}
private struct Storyboard
{
static let CellIdentifier = "PublisherCell"
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(Storyboard.CellIdentifier, forIndexPath: indexPath) as UICollectionViewCell
return cell}
}
You need to implement this func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize method in your UICollectionViewDelegateFlowLayout

Swift - how to open another viewcontroller with CollectionViewCell inside UITableViewCell

I'm really new in iOS/Swift and i'm in a small project. In this project i have a UITableView inside ViewController. And i have another file custom CollectionViewCell in side UITableViewCell.
I want when user click a cell in collectionview it will open another ViewController and it get data from this collectionviewcell.
This is my uitableview swift file:
class IndexRow: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var names:[String] = ["Movie 1","Movie 2","Movie 3","Movie 4","Movie 5","Movie 6"]
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
collectionView.registerClass(indexOneMovie.self, forCellWithReuseIdentifier: "onemovie")
let nib = UINib(nibName: "indexOneMovie",bundle: nil)
collectionView.registerNib(nib, forCellWithReuseIdentifier: "onemovie")
self.collectionView.backgroundColor = UIColor.clearColor()
self.collectionView.delegate = self
self.collectionView.dataSource = self
print("Hello")
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return names.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCellWithReuseIdentifier("onemovie", forIndexPath: indexPath) as! indexOneMovie
cell.poster.image = UIImage(named: "poster.jpg")
cell.name.text = names[indexPath.row]
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print(indexPath.item)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let itemsPerRow:CGFloat = 2
let hardCodedPadding:CGFloat = 0
let itemWidth = (collectionView.bounds.width / itemsPerRow) - hardCodedPadding
let itemHeight = collectionView.bounds.height - (hardCodedPadding)
return CGSize(width: itemWidth, height: itemHeight)
}
How i can do it?
ok i have recently implemented the same in my app these are the links where i refered initially -
https://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell-in-swift/
http://www.thorntech.com/2015/08/want-your-swift-app-to-scroll-in-two-directions-like-netflix-heres-how/
you are making uicollectionview delegate confirms to uitableview cell so you cannot present or push to other view controller.
here is my code hope it will help you
homeController.swift which contains uitableview
extension HomeController : UITableViewDelegate {
func tableView(tableView: UITableView,willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? TableViewCell else { return }
//here setting the uitableview cell contains collectionview delgate conform to viewcontroller
tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row, andForSection: indexPath.section)
tableViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
}
func tableView(tableView: UITableView,didEndDisplayingCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? TableViewCell else { return }
storedOffsets[indexPath.row] = tableViewCell.collectionViewOffset
}
}
extension HomeController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView,numberOfItemsInSection section: Int) -> Int {
let element : [CollectionViewElement] = self.returnCollectionViewElementAccordingToIndex(collectionView.tag)
return element.count
}
func collectionView(collectionView: UICollectionView,cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell",forIndexPath: indexPath) as! horizontalCollectionViewCell
let element : [CollectionViewElement] = self.returnCollectionViewElementAccordingToIndex(collectionView.tag)
cell.cellTitleLabel.text = element[indexPath.row].videos.title
cell.cellGenerLabel.text = element[indexPath.row].videos.gener
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
print("collectionviewtag:\(collectionView.tag) + indexpathrow:\(indexPath.row)")
//from here you can do push or present to anyview controller
// collectionviewtag is tableView cell row value and indexpathrow return collectionView cell row value.
}
}
TableViewCell.swift :custom UITableViewCell which contains collectionView
class TableViewCell: UITableViewCell {
#IBOutlet private weak var collectionView: UICollectionView!
#IBOutlet weak var cellLabel: UILabel!
#IBOutlet weak var cellButton: UIButton!
#IBAction func CellButtonActionTry(sender: UIButton) {
print("Dude \(cellButton.tag)")
}
var collectionViewOffset: CGFloat {
get {
return collectionView.contentOffset.x
}
set {
collectionView.contentOffset.x = newValue
}
}
func setCollectionViewDataSourceDelegate<D: protocol<UICollectionViewDataSource, UICollectionViewDelegate>>
(dataSourceDelegate: D, forRow row: Int , andForSection section : Int) {
collectionView.delegate = dataSourceDelegate
collectionView.dataSource = dataSourceDelegate
collectionView.tag = row // tableView indexpathrow equals cell tag
collectionView.reloadData()
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
You can do it like this :
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print(indexPath.item)
let name = names[indexPath.item]
let distinationViewController = DistinationViewController()
distinationViewController.name = name
if let navVC: UINavigationController = UIApplication.sharedApplication().keyWindow?.rootViewController as? UINavigationController {
navVC.pushViewController(distinationViewController, animated: true)
}
}
This is just a way to do it i dont know which view you want to push or what your names array contains so kindly change those things accordingly.
get root navigationcontroller from uiapplication and perform push on it.

UICollectionView vertical flow layout keep in collection bounds

I have a UICollectionView with vertical cells alignment, but I want also vertical section alignment, I also want to keep the sections inside the current frame of the UICollectionView, that means if a section reach the end and it's longer then the collection itself, then it will go to next line.
This is how it looks right now:
This is the final result I want to end up with:
This is my code so far:
class LettersCollectionTestViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var collectionContainer: UIView!
var collectionView: UICollectionView?
private let ReuseIdentifierCollectionLetterCell = "LetterCollectionViewCell"
var collectionWords: NSArray?
var itemSize: CGFloat = 25.0
var itemSpacing: CGFloat = 5.0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let logoWord: String = "This is just this"
self.collectionWords = logoWord.componentsSeparatedByString(" ")
self.initializeCollection()
}
func initializeCollection() {
let collectionViewLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
collectionViewLayout.itemSize = CGSizeMake(self.itemSize, self.itemSize)
collectionViewLayout.minimumInteritemSpacing = 0
collectionViewLayout.minimumLineSpacing = self.itemSpacing
collectionViewLayout.scrollDirection = UICollectionViewScrollDirection.Vertical
let collectionView: UICollectionView = UICollectionView(frame: self.collectionContainer.bounds, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self;
collectionView.dataSource = self;
collectionView.showsHorizontalScrollIndicator = false
collectionView.showsVerticalScrollIndicator = false
collectionView.registerClass(LetterCollectionViewCell.self, forCellWithReuseIdentifier: self.ReuseIdentifierCollectionLetterCell)
collectionView.registerNib(UINib(nibName: self.ReuseIdentifierCollectionLetterCell, bundle: nil), forCellWithReuseIdentifier: self.ReuseIdentifierCollectionLetterCell)
self.collectionView = collectionView
self.collectionContainer.addSubview(collectionView)
}
// MARK: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print("clicked item at index: \(indexPath.row)")
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: LetterCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(self.ReuseIdentifierCollectionLetterCell, forIndexPath: indexPath) as! LetterCollectionViewCell
let scalingTransform: CGAffineTransform = CGAffineTransformMakeScale(-1, 1)
cell.transform = scalingTransform
return cell
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (self.collectionWords?.objectAtIndex(section).length)!
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return (self.collectionWords?.count)!
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: self.itemSpacing, left: self.itemSpacing, bottom: self.itemSpacing, right: self.itemSpacing)
}
}
What do I need to do? I know I should create a custom FlowLayout, but where should I start? I never did it before.
Thanks in advance!

UICollectionView not working using swift without storyboard

I am trying to set up UICollectionView in my view controller. I am created custom cell CVCell.xib. My collection view is not showing up at all. What's missing in my code?
In my viewController.swift file:
#IBOutlet var collectionViewNew: UICollectionView?
override func viewDidLoad() {
super.viewDidLoad()
self.collectionViewNew?.registerNib(UINib(nibName: "CVCell", bundle: nil), forCellWithReuseIdentifier: "CVCell")
}
func numberOfSectionsInCollectionView(
collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 6
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CVCell", forIndexPath: indexPath) as CVCell
cell.backgroundColor = UIColor.orangeColor()
return cell
}

Resources