Why is only half of a collection view getting displayed? - ios

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.

Related

Not all cells are shown in a CollectionViewController Swift

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

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.

Auto layout calculating same height for each collectionViewCell

So I have a collection view that uses a custom layout that I found on Github called CHTCollectionViewWaterfallLayout I like it so far, however I am looking to make the custom collection view cell I made dynamic in height, and I am having trouble connecting Auto Layout to calculate this. I shared a simple sample project on Github that generates random string sizes and displays them, only problem is that Auto Layout generates the same cell height for each Collection View Cell. The project can be found here.
To give you a run down of my thought process, I calculate the cell height by using the method CHTCollectionViewDelegateWaterfallLayout sizeForItemAtIndexPath. Since I also use the delegates method columnCountforSection my thought is since I provide a finite number of columns based on the orientation, I take the collectionView frame width and I divide by the number of columns to get me my width for the cell.
func collectionView (collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
var cell = dict["heightCell"] as? CollectionViewCell
let randomString = RadomStrings[indexPath.item]
let float = CGFloat(columnCount)
let width = collectionView.bounds.size.width / float
if cell == nil {
cell = NSBundle.mainBundle().loadNibNamed("CollectionViewCell", owner: self, options: nil)[0] as? CollectionViewCell
dict["heightCell"] = cell
}
cell?.RandomStringLabel.text = randomString
cell!.frame = CGRectMake(0, 0, CGRectGetWidth(collectionView.bounds), CGRectGetHeight(cell!.frame))
cell!.setNeedsLayout()
cell!.layoutIfNeeded()
var size = cell?.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
size?.width = width
return CGSize(width: width, height: size!.height)
}
My constraints are pretty basic. I have a constraint on each axis. One on the top of the content view, leading, trailing and bottom. I also have a height on the label that is greater than or equal to 45.
Using Auto Layout to calculate TableViewCell heights is easy to me and I like it because I like the DRY principle behind this height calculation approach. So I would like to keep this height calculation process the same throughout my app. CollectionViews are a relatively new layout process for me, so I would love to learn what I am doing wrong here. Hopefully I am clear for everyone, thanks!
I figured it out! What I didn't do is put a width constraint on the custom cell I created! Duh!

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

Resources