I nested collectionView inside collectionView Cell like this:
inside first collectionView Cell, I put this code :
class CaseCellView: UICollectionViewCell, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var lblHeader: UILabel!
#IBOutlet weak var collectionViewItemList: UICollectionView!
var sellingArray = ["1", "2", "3", "4", "5"]
override func awakeFromNib(){
super.awakeFromNib()
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .horizontal
flowLayout.itemSize = CGSize(width: collectionViewItemList.frame.width, height: collectionViewItemList.frame.width)
flowLayout.minimumLineSpacing = 5.0
flowLayout.minimumInteritemSpacing = 5.0
self.collectionViewItemList.collectionViewLayout = flowLayout
self.collectionViewItemList?.delegate = self
self.collectionViewItemList?.dataSource = self
self.collectionViewItemList.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.sellingArray.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionViewItemList.frame.width, height: collectionViewItemList.frame.width)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0, 0, 0, 0)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell1 = collectionView.dequeueReusableCell(withReuseIdentifier: "caseListCell", for: indexPath)as! CaseListCellView
cell1.lblItemList.text = self.sellingArray[indexPath.item]
cell1.lblItemList.textColor = .white
cell1.backgroundColor = UIColor.blue
return cell1
}
}
class CaseListCellView: UICollectionViewCell {
#IBOutlet weak var lblItemList: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
}
but when I run, the nested collectionView result did not appear inside the first collectionView, it just show first lblHeader from the first collectionView Cell.
How to correct my code to show nested collectionView Cell?
Related
I have taken collectionview in storyboard and in its cell i have taken ImageView and its below one label
i need to show only three rounded images horzontally and number of rows from JSON vertically in all screen sizes
like below image i need:
in cell for imageview costraints like below
leading = trailing = top = bottom = 5
and in coding:
class FriendsViewController: UIViewController {
// MARK: - IBOutlets
#IBOutlet weak var galleryCollectionView: UICollectionView!
// MARK: - LifeCycleMethods
override func viewDidLoad() {
super.viewDidLoad()
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
layout.scrollDirection = .vertical
let width = UIScreen.main.bounds.width/4
let height = width*1.1
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 5
layout.itemSize = CGSize(width: width, height: height)
self.galleryCollectionView.collectionViewLayout = layout
}
}
class FriendsCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imgView: UIImageViewX!
#IBOutlet weak var lblTitle: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
imgView.layer.cornerRadius = imgView.frame.height/2.0 }
}
so i am getting weird o/p in different screen sizes why?
o/p of ipodtouch7
In your collectionview cell Set constraints as shown in attached image, i.e. ur image view width should depend on imageview height, you can do it using ratio.
Then in willDisplay method calculate cornerRadius
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
{
guard let cell = cell as? TestCollectionViewCell else
{
return
}
let cellHeight : CGFloat = cell.frame.size.height
let labelHeight : CGFloat = cell.label?.frame.size.height ?? 0.0
cell.imageView?.layer.cornerRadius = (cellHeight - labelHeight) / 2.0
}
Below is the entire code
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
{
#IBOutlet weak var collectionView : UICollectionView? = nil
let horizontalSpaceBetweenCell : CGFloat = 16
let verticalSpaceBetweenCell : CGFloat = 16
let edgeInsets = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
override func viewDidLoad()
{
super.viewDidLoad()
setup()
}
func setup()
{
let nib = UINib(nibName: "TestCollectionViewCell", bundle: nil)
collectionView?.register(nib, forCellWithReuseIdentifier: "TestCollectionViewCell")
}
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 40
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TestCollectionViewCell", for: indexPath) as? TestCollectionViewCell
{
return cell
}
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
{
guard let cell = cell as? TestCollectionViewCell else
{
return
}
let cellHeight : CGFloat = cell.frame.size.height
let labelHeight : CGFloat = cell.label?.frame.size.height ?? 0.0
cell.imageView?.layer.cornerRadius = (cellHeight - labelHeight) / 2.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let numberOfCellsPerRow = 3
let otherSpace = (edgeInsets.left + edgeInsets.right)
let width = (collectionView.frame.size.width - otherSpace) / CGFloat(numberOfCellsPerRow)
return CGSize(width: width, height: 80) // Height can be anything 80, 90 ,100
}
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 16
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return edgeInsets
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
}
}
Please change Widhth to height :
imgView.layer.cornerRadius = imgView.frame.size.height/2.0
code Snippet
class TemporaryViewController: UIViewController {
#IBOutlet weak var itemCollectionView: UICollectionView! // Main Collection View
private var footerView: DashboardBottomViewCollectionViewCell?
override func viewDidLoad() {
super.viewDidLoad()
self.itemCollectionView.delegate = self
self.itemCollectionView.dataSource = self
self.itemCollectionView.register(UINib(nibName: nibParameter.DASHBOARD_CENTER_NIB, bundle: nil), forCellWithReuseIdentifier: nibParameter.DASHBOARD_CENTER_NIB)
self.itemCollectionView.register(UINib(nibName: "DashboardBottomViewCollectionViewCell", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "DashboardBottomViewCollectionViewCell")
}}
extension TemporaryViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionView.elementKindSectionHeader:
return nil
case UICollectionView.elementKindSectionFooter:
let footerView = itemCollectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "DashboardBottomViewCollectionViewCell", for: indexPath) as! DashboardBottomViewCollectionViewCell
self.footerView = footerView
self.footerView?.contentView?.clipsToBounds = true
footerView?.dashboardBottomDelegate = self
footerView?.clipsToBounds = true
return footerView!
default:
return headerView!
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: 600, height: 300.0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return CGSize(width: 100.0, height: 300.0)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = -10 + (collectionView.frame.width)
return CGSize(width: width,
height: 90)
}
}
Footer Class to Show collection View
class DashboardBottomViewCollectionViewCell: UICollectionReusableView {
weak var dashboardBottomDelegate: DashboardBottomViewCollectionViewDelegate?
#IBOutlet weak var itemCollectionView: UICollectionView!
#IBOutlet weak var imageView: UIView!
var estimateWidth = 160.0
var cellMarginSize = 16.0
var contentView : DashboardBottomViewCollectionViewCell?
override init(frame: CGRect) {
super.init(frame: frame)
let contents = Bundle.main.loadNibNamed("DashboardBottomViewCollectionViewCell", owner: self, options: nil)?.first as! DashboardBottomViewCollectionViewCell
self.addSubview(contents)
contentView = contents
contents.itemCollectionView.register(UINib(nibName: nibParameter.DASHBOARD_PURCHASE_NIB, bundle: nil), forCellWithReuseIdentifier:nibParameter.DASHBOARD_PURCHASE_NIB)
contents.itemCollectionView.delegate = self
contents.itemCollectionView.dataSource = self
let flow = contents.itemCollectionView?.collectionViewLayout as! UICollectionViewFlowLayout
flow.minimumInteritemSpacing = CGFloat(self.cellMarginSize)
flow.minimumLineSpacing = CGFloat(self.cellMarginSize)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func reloadData() {
contentView?.itemCollectionView.reloadData()
}
}
extension DashboardBottomViewCollectionViewCell: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 15
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: nibParameter.DASHBOARD_PURCHASE_NIB, for: indexPath) as! RecentPurchaseCollectionViewCell
cell.purchaseLabel.text = "trainers.trainerName"
cell.imageView.sd_setImage(with: URL(string: "trainers.tarinerProfilePictureUrl" != nil ? "trainers.tarinerProfilePictureUrl" : ""), placeholderImage: UIImage.init(named: "tour_placeholder"), options: .handleCookies, completed: nil)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = 0 + (collectionView.frame.width / 1)
return CGSize(width: width,
height: 100)
}
}
extension DashboardBottomViewCollectionViewCell : UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
dashboardBottomDelegate?.didSelect(tem: indexPath.item)
}
}
As per the code, I can see this:
I can see a collectionView in Footer but can't change the orientation to vertical instead of the Grid view like this:
I am stuck and couldn't find any hint. Any hint would be appreciable. Thanks
Have you tried putting your setup code DashboardBottomViewCollectionViewCell.init(frame:) in awakeFromNib() instead?
override func awakeFromNib() {
super.awakeFromNib()
//setup cell and stuffs
}
Also call footerView?.reloadData() to reload the contents.
I want to center a label based on a view. The label is inside a collectionView and I want to center this label based on a view that is NOT inside the collectionView at runtime.
What I tried to do is change the constant of the label's constraint to the view's frame midY but it doesn't work:
// THIS DOES NOT WORK. I want the `textLabel` centered inside the `yellowView`.
cell.textLabelCenterYVerticalConstraint.constant = yellowView.frame.midY
Here is the screen:
Here is the Storyboard:
This is my collectionView code
class ViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var yellowView: UIView!
let imageName = ["1", "2", "3"]
override func viewDidLoad() {
super.viewDidLoad()
collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 5)
}
}
// MARK: - UICollectionViewDataSource
extension ViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageName.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellID", for: indexPath) as! MyCollectionViewCell
let index = indexPath.row
let images = imageName[index]
cell.backgroundImageView.image = UIImage(named: images)
// THIS DOES NOT WORK. I want the `textLabel` centered inside the `yellowView`.
cell.textLabelCenterYVerticalConstraint.constant = yellowView.frame.midY
return cell
}
}
// MARK: - UICollectionViewDelegateFlowLayout
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.bounds.width, height: collectionView.bounds.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0.0, left: 5.0, bottom: 0.0, right: 5.0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10.0
}
}
This is my cell code
class MyCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var backgroundImageView: UIImageView!
#IBOutlet weak var textLabel: UILabel!
#IBOutlet weak var textLabelCenterYVerticalConstraint: NSLayoutConstraint!
}
Please see the comment in the code // THIS DOES NOT WORK. Any suggestions?
I'm trying to accomplish the following:
I've followed the answer in this question, but I get the image below:
This is the code for the collection view controller:
class MainMenuViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
#IBOutlet var collectionView: UICollectionView!
#IBOutlet weak var dateTimeLabel: MarqueeLabel!
#IBOutlet weak var iconButton: UIButton!
#IBOutlet var imageView: UIImageView!
var iconButtonTimer: Timer!
var upDateTimer: Timer!
var statusString: String!
var alertTitle: String!
var networkStatusString: String!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(UINib.init(nibName: "MainMenuCell", bundle: nil), forCellWithReuseIdentifier: "MainMenuCell")
collectionView.collectionViewLayout = MainMenuLayout()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 8
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
print(#function)
let padding: CGFloat = 50
let collectionViewSize = collectionView.frame.size.width - padding
return CGSize(width: collectionViewSize/2, height: collectionViewSize/2)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainMenuCell", for: indexPath)
cell.backgroundColor = UIColor.red
return cell
}
}
And this is the storyboard...
Conform to UICollectionViewDelegateFlowLayout and implement
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(10, 10, 10, 10)
}
Also comment this line
collectionView.collectionViewLayout = MainMenuLayout()
as no need for a custom layout to accomplish what you want
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!