Not all cells are shown in a CollectionViewController Swift - ios

I'm currently developing a periodic table and to show the table I'm using a collection view. The periodic table has 118 elements and I'm trying to show them all in the same page but when I run the app on the simulator, only 77 cells are shown.
Here's the code I used in my Swift file: source code
I was wondering how can I show all the cells on the same screen. I searched online but I couldn't find anything.

steps:
1. first count the number of items or element in your periodic table, i.e divide the whole frame in to grids, to see how many small square boxes are there..
now create a modal for your elements, say for first item Hydrogen, it goes in [Datamodel] array 0 index, and for next 16 array element its empty object as there is no element.. in this way create your modal
now create your collectionview cells and populate the data with your modal, where the data are blank object show black image, and for those where there is an element, show respectively
now for the size of each element, there is a UICollectionViewDelegateFlowLayout method
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
let width = self.collectionview.frame.size.width/18 as there are 18 columns
return CGSize(width: width, height: width)
}
this way all your cells will be visible in horizontal view.. but then again all cell might not be visible in landscape mode, like elements with 58, 59
so for height of each element you need to do
let height = height/9 as there are 9 rows
but this way, you. might not get square cells

Related

Why is only half of a collection view getting displayed?

I have used MMPlayerView (GitHub link here) to add videos into a collection view, in the collection view the image gets replaced by a video in the code (from the demo). I took the MMPlayerView's demo project and changed stuff to fit my needs and then implemented it into my project to get something like this show in this video.
Now I'd like to obviously move the collection view up towards the buttons at the top of the screen, and later on I will use multiple collection views like that to get the style of the app store more like, just showing videos. Since I took the code from the demo I'm not too sure on some things, when I copied the project's demo the collection view was made for scrolling through it vertically, so it takes up the whole screen, so the collection view was constrained to the bottom of the view:
Which causes this to show in the app (I don't understand why it's so far away from the top when its constrained by 10 points):
Now I want to obviously want to remove the bottom constraint and constrain it by it's height instead so I can have multiple collection views, (probably through the use of table views), so I removed the constraint to the bottom of the view and added a height constraint for 250 points:
Which caused the app to look like this:
Why?? I'm guessing it has something to do with this part of the view controller code:
extension HomeViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let m = min(UIScreen.main.bounds.size.width, UIScreen.main.bounds.size.height)
return CGSize(width: m, height: m*0.75)
}
I want to keep the collection view's width the same width of the view, so the width is fine, it's just the height here. When I try and set the height to a constant value of 250 (the same as the height constraint) it does the same thing (only shows half of it) but shrinks the video a little bit. What can I change?
Taking a quick look at the Example app from MMPlayerView...
Change the height value in sizeForItemAt to the height of your collection view (250 per your question):
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let m = min(UIScreen.main.bounds.size.width, UIScreen.main.bounds.size.height)
return CGSize(width: m, height: 250.0)
//return CGSize(width: m, height: m*0.75)
}
I'm assuming you were getting the same error messages in debug console as I got:
The behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
and it should also have printed the Collection View properties, including:
adjustedContentInset: {0, 0, 200, 0};
So the collection view has a Bottom inset of 200.
If you search that example project for contentInset you'll find this line in the view controller's viewDidLoad() function:
playerCollect.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 200, right:0)
If you comment-out / remove that line, you should now see the full cell.
Might be a good idea to get a handle on collection views to begin with and then review that example project for the video implementations in your app.

How to determine UICollectionView width when scrolling is disabled

What I am building:
I am building a camera filter app. There are multiple filter categories, each containing filters within them. IE: A UICollectionView within a UICollectionView.
Problem: The UICollectionView (filters) within a UICollectionView (Filter categroy) is not displaying all the width when isScrollEnabled is set to false.
Here is the code that determines the width of the second UICollectionView. The width is being calculated by multiplying the size of one filter by the amount of filters needing to be displayed. This gives a perfect width that I can scroll through when isScrollEnabled is set to true, BUT, the problem is that when isScrollEnabled is set to false, since I can not scroll through the entire width, it appears as if the UICollectionView's width is too small
filtersCollection.frame.size.width = contentView.frame.width * CGFloat(filters.count) + 10
filtersCollection.register(FilterCell.self, forCellWithReuseIdentifier: "FilterCell")
filtersCollection.delegate = self
filtersCollection.dataSource = self
Essentially What I want: What I want is for it to be able to show all of the collectionviews width without scrolling.
Screenshots Explained: blue/red colors are for easier explanation.. The BLUE is a cell within the parent collectionView. The RED is a collectionView within the cell. The red collectionview's width is slightly too small. There are only two filters/cells in that collectionview and when scroll is enabled it's sized perfect (you can scroll to the end of the view). Though when isScrollEnabled is set to false obviously I am not able to view the whole width.
As you can see from the screenshot on the right, the problem gets worse with more cells, it appears the width is even less. (this gives me the thought it could have something to do with section insets)
What I have tried: 1. I thought it could be the UICollectionViewFlowLayout's section insets though I had commented my insets out so from what I see it has nothing to do with the section insets. (the reason the cells appear to have insets is because the image and text's x values are set to 5 pixels within the cell.) So in my calculating it is still using the frame of the entire cell... I am genuinely confused and I have done my very best to explain. Please do not down vote I have literally searched everywhere and not found it, If you do find something please link me there! Thanks!
In order to show the sub collection view in full width you have to meet these two requirements:
The cell which represents the sub collection view has the right width.
The sub collection view's size has to be exactly the same as the cell's size.
So for requirement #1 you have to override the following delegate method:
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
Change the size of the cell which represents your sub collection view to the full width (dependent on how many sub items).
I figured it out. The problem was the minimumLineSpacingForSectionAt. Apparently there was a default value putting a number of pixels between each cell. I solved this by using the UICollectionViewDelegateFlowLayout function minimumLineSpacingForSectionAt below:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
I simply returned 0 removing the spacing and then everything fit.
Though I still wanted spacing between the cells so I returned five instead like so
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 5
}
It messed it all up again though this time I knew what the minimumLineSpacingForSectionAt was so I included that in my equation for finding the width of the subbed collectionView as well as the size of the cell the collectionView is in.

Adjust UICollectionView Size Dynamically to Ensure No Inter Item Spacing

The goal is to have a UICollectionView with a specific number of columns per row, regardless of the size of the screen.
Currently I am using:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
//print(collectionView.frame.size.width)
let numberRows:CGFloat = 7
return CGSize(width: collectionView.frame.size.width/numberRows, height: collectionView.frame.size.width/numberRows)
}
To set the size of the cells so that they can fit inside the collection view without inter item spacing. However, the size of the collection view is set based on a percentage of the screen size. If the desired "numberRows" does not divide evenly, then there will be spacing between the cells.
How can I dynamically change the collection view size to ensure the cells will fit without spacing? How can this be accomplished in a more efficient way?
When you set the size of your collection view, you could round it down to a multiple of numberRows. This ensures it will divide evenly.
If you are using AutoLayout, you could set the width or height constraints of the collection view. Then call layoutSubviews: or setNeedsLayout
If you are not using AutoLayout, you can change the size of the collection view using setFrame or setBounds.
You can not break the mathematical rules here. If you get one point/pixel to much you can not break this pixel into two half-pixels.
What you can do is:
size the collection view accordingly so that the number of cells fit perfectly
accept that one of the cells will have one pixel more/less size then the others. (e.g. the last cell in the row)

How to adjust UICollectionView contentSize.height based on number of rows in swift

I'd really appreciate if someone can light up some ideas here. I've been trying to fix this for weeks now (not kidding).
I have a "to do list" using a collectionView where I hide the rows that were completed and move them to the end of the list. I then unhide the items if needed with a button. The collectionView looks exactly as a tableView with one item(cell) per row.
When the items are hidden the collectionView has a lot of empty scrolling space at the bottom instead of automatically deleting the space used by the hidden rows since they technically are still there.
I'm trying to cut that empty space so the collectionView height would be equal to the amount of cells/rows left visible.
override func viewDidAppear(animated: Bool) {
if isCellHidden { //checking if cells are hidden
var heightOfSection0 = 95 + (42 * self.collectionView.numberOfItemsInSection(0))
println(self.collectionView.contentSize.heigh) //returns 2350
self.collectionView.contentSize.height = CGFloat(heightOfSection0)
println(heightOfSection0) //returns 1019
println(self.collectionView.contentSize.heigh) //returns 1019.0 which is correct but as soon as I scroll down it resets to it's original size (2350) and let's me scroll through that empty space...
}}
If I try to read the collectionView height immediately after setting this, it displays the correct value but as soon as I try to scroll down it resets back to it's original height. I also tried disabling the auto layout and it doesn't make a difference
You should not manage contentSize directly - return appropriate number of items to be displayed from collectionView(_:numberOfItemsInSection:) instead (i.e. do not count your "hidden" cells).
You can use sizeForItemAtIndexPath: to change the size of collection view cell.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
var numberOfCellInRow : Int = 3
var padding : Int = 5
var collectionCellWidth : CGFloat = (self.view.frame.size.width/CGFloat(numberOfCellInRow)) - CGFloat(padding)
return CGSize(width: collectionCellWidth , height: collectionCellWidth)
}
Changing UI stuff in viewDidAppear() in theory is a good place to do so. However, at this point, you can't be sure that auto layout has operated on the subview that you're manipulating.
You can check when it has and when it's safe to manipulate the frame, by subclassing it and overriding layoutSubviews()
I had a similar issue here: https://stackoverflow.com/a/30446125/4396258

iOS- UICollectionViewCell asymmetric size of each cell

As per my understanding, collection view is collection of views having similar height and width of each cell.
Can i achieve below view with UICollectionview? Size to Fit content helps me to certain level but still how can i reduce/increase space between two cells in uicollectionview.
Can anyone just give pointers how i can achieve this with/without collectionview?
You can do that using collection view of course.
Need to adjust cell size according to content.
Here is a good example
The method you want to look at is in the UICollectionViewDelegateFlowLayout for example where tags in an array of tags strings
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let attributedString = NSAttributedString(string: tags[indexPath.row])
let size = CGSizeMake(attributedString.size().width, attributedString.size().height)
return size
}
If I'm recognizing the screenshot you posted correctly the app you're trying to imitate is Foursquare. If that's the case, you may be interested in FSQCollectionViewAlignedLayout, an open source project form Foursquare Labs which implements that very interface.

Resources