UICollectionView compositional layout: custom item size for remaining space? - ios

I'm reading Apple's documentation on compositional layout, for following code example:
func createBasicListLayout() -> UICollectionViewLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(44))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
subitems: [item])
let section = NSCollectionLayoutSection(group: group)
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
I wonder if, say, there are two items in group, one with .absolute(X) for width dimension, is it possible to have another item taking up the remaining space in width dimension? Thanks!

Related

Collection view compositional layout issue

Overview
I'm trying to create a layout using the collection view UICollectionViewCompositionalLayout API.
This is the design I need to create:
Code
This is the code so far:
private func makeHelloLayoutSection() -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(
widthDimension: .absolute(100),
heightDimension: .absolute(200))
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(0.8),
heightDimension: .absolute(500))
let supplementarySize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1),
heightDimension: .absolute(50))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let group = NSCollectionLayoutGroup.horizontal(
layoutSize: groupSize,
subitems: [item])
let topInset = groupSize.heightDimension.dimension - itemSize.heightDimension.dimension
group.contentInsets.top = topInset
let section = NSCollectionLayoutSection(group: group)
section.contentInsets.leading = 16
section.orthogonalScrollingBehavior = .continuous
let sectionBackgroundDecoration = NSCollectionLayoutDecorationItem.background(
elementKind: sectionBackgroundDecorationElementKind)
section.decorationItems = [sectionBackgroundDecoration]
let sectionSupplementaryItem = NSCollectionLayoutBoundarySupplementaryItem(
layoutSize: supplementarySize,
elementKind: self.categoryHeaderID,
alignment: .topLeading)
section.boundarySupplementaryItems = [sectionSupplementaryItem]
return section
}
Problem
With the code above, it looks like this:
The problem is the text Hello. I can't position it to be on top of the blue items (cells) like in the design. I'm using a NSCollectionLayoutBoundarySupplementaryItem with .topLeading as the alignment.
Any thoughts on how to position the text correctly?

How to turn off scroll inside section in collectionView (UICollectionViewCompositionalLayout)?

Could you help me with my problems please.
I have collection view with different type of section:
Scrolling horizontally,
Tabs
Tab content.
I made tab as section and when user press tab I just call collectionView.scrollToItem(at indexPath + 1) and it is work great.
I have problems with content section. I made is like horizontal carousel and I have to turn off scroll at it.
This is the code of this section.
fileprivate static var tabContantLayout: NSCollectionLayoutSection {
get {
let sectionBackground = NSCollectionLayoutDecorationItem.background(
elementKind: "background")
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1),
heightDimension: .estimated(1))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
section.decorationItems = [sectionBackground]
return section
}
}
If I change section.orthogonalScrollingBehavior to none all items will be located vertically one by one.
collection view screen
Please, If you know say how I can turn off scroll only in this section? Thanks

UICollectionViewCompositionalLayout doesn't scroll to incomplete group

I have simple implementation with UICollectionViewCompositionalLayout. There are two sections, every has single row with horizontal scroll and every item at section has 1/4 width of whole container (now it's full screen).
I would like to have paging scroll, but when data source provides 4n+1 elements at the section I can't scroll to access last item.
How to fix it with pure animation for last item like with simple UICollectionViewFlowLayout?
func createCollectionViewLayout() -> UICollectionViewLayout {
UICollectionViewCompositionalLayout { sectionIndex, environment -> NSCollectionLayoutSection? in
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1 / 4), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalWidth(0.4))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 4)
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(44))
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .groupPaging
section.boundarySupplementaryItems = [header]
return section
}
}
Video with bug example
After complex research: seems like layout bug, one possible solution is to change programmatically the orthogonalScrollingBehavior depending on the number of items

Big gap in horizontal uicollectionview using orthogonalScrollingBehavior

As the title suggests I face weird bug (at least I did not expect that) where my items in my collection view have big gap like in this picture
I am using orthogonalScrollingBehavior from new compositional layout API
this is my code
let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(100), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = NSDirectionalEdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(200))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
return section
I was expecting that the only gap between them is made by contentInsets. Please help if you know the answer or the reason why this happens
same happening to me, maybe it's a bug since if visible cell widths are fitting the content width, then it does not get this annoying spacing. trying to find a workaround.
I had the same problem. Try to use widthDimension: .estimated(1) for the group
NSCollectionLayoutSize. Example:
func makeTestLayoutSection() -> NSCollectionLayoutSection {
let item = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .absolute(400), heightDimension: .absolute(500)))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .estimated(1), heightDimension: .absolute(500)), subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
return section
}
Tested on tvOS 15.0

UICollectionViewCompositionalLayout: right align cells within a section

I have this layout, where the main picture is a UICollectionView, and the thumbnails are in their own UICollectionView.
The design asks for the thumbnails to be right-aligned, so the content in the UICollectionView needs to be pushed to the right. How can I do that? I only need to support iOS 13 and up, so am using UICollectionViewCompositionalLayout.
private func createThumbsLayout() -> UICollectionViewLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalHeight(1), heightDimension: .fractionalHeight(1))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
section.interGroupSpacing = 16
section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)
return UICollectionViewCompositionalLayout(section: section)
}
I found this:
thumbsCollectionView.semanticContentAttribute = .forceRightToLeft
Which works, if I then also reverse the images and reverse all IndexPath math to deal with selection and all that. It's not ideal so would love a better solution. Surely there must be some kind of alignment property? Same would be useful for a bottom-aligned vertical collectionview?

Resources