I’m trying to create this relationship that the pictures below depict of Parent -> Children -> Children -> etc. . . I’m trying to use a vertical collection view for the Parent collection view and then nested horizontal collection views for the children. But I’m struggling with moving the collection views cells down when the “View Children Button” is clicked. I thought I could do something like this when the button is clicked:
#IBAction func showChildrenBtnClicked(_ sender: Any) {
collectionView.contentInset.bottom = 200
collectionView.reloadData()
}
but this doesn’t seem to do anything. Does anyone know how to add empty space inside the collection view so that I could then create a horizontal collection view to hold the children elements.
These are some mock images of the behavior I'm trying to achieve:
Step 1)
Step 2)
Step 3)
Step 4)
Step 5)
Thank you in advance.
First take all the view as collection view.
When ViewchildrenButton get tapped, delegate it to the parent collection view controller class, and there
if let flowLayout = metaMoreCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.invalidateLayout()
}
This will call the
collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
and give the updated size there.
Related
I have made a TvOS app which has 2 collection views they will be scrollable horizontally.
Now both of them have items which open corresponding cell's detail page.
That new page is pushed on navigation stack, when I come back I want my focus to remain on same cell of the collection view which opened the new page.
So, I found and tried two methods.
Method 1:
Setting collectionView.remembersLastFocusedIndexPath = true for both collection views
Method 2:
Using indexPathForPreferredFocusedView(in:) in delegate of both collection views.
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// SOME WORK
focusedCellIndexPath = indexPath
}
override func indexPathForPreferredFocusedView(in collectionView: UICollectionView) -> IndexPath? {
return focusedCellIndexPath
}
Now when I used Method 1:
Say I have 10 cells in both collection view.
I was on cell 2 in first collection view, then I press down and scroll till the end on the second collection view and I press up then I go back to second cell of first collection view.
But when I used Mewthod 2:
When I press up then I don't go on second cell of first collection view but go on the cell just above currently focused cell of second collection view.
I want to know why they both behaved differently, looking at official documentation of method used in method2 in its discussion section it looks both things should behave similarly, but that is not the case here.
I am using collection view in my project.
there is always a tap padding comes between collection view and collection view cell.
I want to set the space between collection view cell and its collection view container.
How can I do this ?
Look at the UICollectionViewDelegateFlowLayout : https://developer.apple.com/documentation/uikit/uicollectionviewdelegateflowlayout
You can use this method to tell the collection view how much space you want between rows/columns:
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
Read about the method here: https://developer.apple.com/documentation/uikit/uicollectionviewdelegateflowlayout/1617705-collectionview
Make sure you have your collectionView delegate set.
I'm a newbie of IOS app develop. Now a day , I want to make a screen likes below picture.
How to make it?
I'm thinking about using UICollectionView but I don't know how to customize it?
You have implemented method named: "sizeForItemAt", it is used to set the size of every cell of your collection view. And your condition is satisfied because of bidirectional scrolling property of collection view. If you change the size of cell, than this may be worst for your UI.
Follow the steps:-
Select collection view from storyboard (if using).
Than go to Attributes Inspector.
And set the Scroll Direction Vertical to Horizontal.
(Vertical is default)
I can do that now by below workaround
class ViewController: UIViewController, UICollectionViewDelegateFlowLayout{
...
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 40.0, height: 500.0)
}
}
You can do it after seeing tutorial of content offset and content size of collection view. This two parameter help you to check for overlapped cell.
Check content offset of every cell with the x origin of green view.
create cocoa touch file.
step 1
step 2
Now you will have two files created.
use xib to design your UI and CollectionViewCell class to connect xib's outlets.
Now in the main view controller where you are confirming UIcollectionViewDelegate and UIcollectionViewDataSource register the xib for an identifier.
collectionView.register(UINib(nibName: "CollectionViewCell", bundle: Bundle.main), forCellWithReuseIdentifier: "yourIdentifier")
you can use this yourIdentifer to deque item for collection view in ItemForRowAtIndexPath.
Now to Change the Scroll Direction Property. Below is the image you can refer
Or programatically you can change it by following piece of code.
if let layout = self.yourCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .horizontal
}
I have collection view in the storyboard. I have a part of cells in storyboard and part of cells I created programmatically. What should I do in sizeForItemAtIndexPath method? Which value should I return? For my programmatically created cells I return size for him. But I don't want copy size from storyboard for cells from storyboard. I mean, I have:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return self.viewModels[indexPath.item].viewSize // for programmatically created cells
}
And in viewModel class:
class ViewModel {
var viewSize:CGSize = CGSizeMake(50, 50)//for example
}
Also, I have cells from storyboard and size of it I setted in storyboard. For example, I have 5 different cells in storyboard and each has different size. Should I do ?
let viewModel = self.viewModels[indexPath.item]
if viewModel.id == "CELL_1" { return CGSizeMake(10, 10) }
else if viewModel.id == "CELL_2" { return CGSizeMake(20, 20) }
//and so on
I don't want to make this :(
Do you know solution how I can get size of item from storyboard or create behaviour when this method is not implemented? (I mean, if you don't implement this method then collection view will get size from storyboard)
You can instantiate the cell using its reuse ID and call:
cell.setNeedsLayout()
cell.layoutIfNeeded()
then access the cell's frame to get it's actual size.
I have 2 collection views on the same screen, and I have the data source and delegate implemented for both in the same view controller. However, the delegate methods such as didSelectItemAtIndexPath is only called for one.
Other info:
Both collection views have a cell with an image.
AllowSelection and UserInteractionEnabled is set to true in both collection views
User interaction enabled on the images
Delegate and data source are set on the storyboard from both collection views to the view controller
Collection views are displayed properly
Both collection views have the same setup, yet only one delegate works. Would you have any clues what could be setting this up?
The collection views are inside a view that has a scroll view. Could this be somehow related?
EDIT 2:
Project with the same problem: https://github.com/iagomr/ProblemWithAutoLayout
EDIT 1:
Somehow this has to do with autolayout constraints, because if I pin the bottom collection view to the bottom of the screen instead of the bottom of other collection view, it starts working.
This is all due to the fact that I need to build a tall screen, and added everything into a view inside a scroll view 1000 points tall.
Code:
//MARK: - CollectionView Delegate
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
println("Called")
}
//MARK: - CollectionView DataSource
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == thisCV {
return 1
} else if collectionView == thisOtherCV{
return 1
}
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
if collectionView == "thisCV" {
if let thisCell = collectionView.dequeueReusableCellWithReuseIdentifier("thisCell", forIndexPath: indexPath) as? thisCollectionViewCell {
thisCell.image = image
return thisCell
}
} else if collectionView == "thisOtherCV"{
if let thisOtherCell = collectionView.dequeueReusableCellWithReuseIdentifier("thisOtherCell", forIndexPath: indexPath) as? OtherCollectionViewCell {
thisOtherCell.image = image
return thisOtherCell
}
}
return UICollectionViewCell()
}
I can confirm that didSelectItem is not getting called. If constant for top-bottom constraint between two collection views is changed from 501 to 0 it is working.
This problem is most likely related to the fact that you have two scroll views (collection views) inside of another scroll view. Overall, I would say, that you should modify your UI. I would suggest two ways of fixing it
Using single collection view
Use just one collection view with different sections for different content. Also, do NOT embed it in the scroll view - collection view already has a scroll view so you should be able to scroll easily. You can also dequeue different class of cells for different sections so you should be able to do everything which you want to do now.
If you want a starting point, here is a good tutorial which should help you with that.
Using scroll view
If you want to setup your UI in Interface Builder remove both collection views and simply add all of your UI inside of scroll view. Place UIButton in places where you want clicking to produce action.
You can even assign the same action to each button and then differentiate which one was triggered by assigning custom tags to each of them.