I am creating a CompositionalLayout.
I have a question about using NSCollectionLayoutGroup initializer.
The creating layouts code is as follows.
func generateSharedAlbumsLayout() -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(140), heightDimension: .absolute(186))
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitem: item, count: 1)
// let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
group.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5)
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(44))
let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: AlbumsViewController.sectionHeaderElementKind, alignment: .top)
let section = NSCollectionLayoutSection(group: group)
section.boundarySupplementaryItems = [sectionHeader]
section.orthogonalScrollingBehavior = .groupPaging
return section
}
What is the difference between the following?
first, use subitem, count initializer.
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitem: item, count: 1)
second, use subitems initializer.
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
The first result is my expectation, but second is not.
What's the reason?
I have another question.
I think this layout is horizontal, but why does it use vertical?
If I use horizontal initializer, the result is wrong as follows.
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 1)
Thank you for reading it.
I'm looking forward to your response.
Related
I'm experimenting with UICollectionViewCompositionalLayout and trying to achieve a similar effect to the Apple Music app, especially to the "hint" indicating there are more cells to scroll:
So far, I have managed to make a similar grid, but I can't make the "visual hint" appear among all screen widths.
This is what I tried:
func createBasicListLayout() -> UICollectionViewLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
// we will be working with this part
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalHeight(1.0), heightDimension: .fractionalHeight(1))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
group.edgeSpacing = .init(leading: .fixed(10), top: nil, trailing: .fixed(10), bottom: nil)
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
section.interGroupSpacing = 0
section.contentInsets = .init(top: 0, leading: 20, bottom: 0, trailing: 20)
let layout = UICollectionViewCompositionalLayout(section: section)
layout.configuration.scrollDirection = .horizontal
return layout
}
Which results in:
How can I make the layout show a hint on a third cell? Thanks in advance!
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!
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?
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
Is it possible to use UICollectionViewCompositionalLayout to create a horizontally scrolling collection view that contains multiple sections?
I'm looking to create a layout similar to the emoji keyboard that has multiple sections, each appended to the end of the previous, in one horizontally scrolling "group", with a header stretching across each section.
With the following layout each section is stacked vertically and each scrolls horizontally:
UICollectionViewCompositionalLayout {
(sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let leadingItem = NSCollectionLayoutItem(
layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.7),
heightDimension: .fractionalHeight(1.0)))
leadingItem.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)
let trailingItem = NSCollectionLayoutItem(
layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(0.3)))
trailingItem.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)
let trailingGroup = NSCollectionLayoutGroup.vertical(
layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.3),
heightDimension: .fractionalHeight(1.0)),
subitem: trailingItem, count: 2)
let containerGroup = NSCollectionLayoutGroup.horizontal(
layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.85),
heightDimension: .fractionalHeight(0.4)),
subitems: [leadingItem, trailingGroup])
let section = NSCollectionLayoutSection(group: containerGroup)
section.orthogonalScrollingBehavior = .continuous
return section
}
You can set the primary scroll direction for the collectionViewLayout to horizontal with the following configuration:
let config = UICollectionViewCompositionalLayoutConfiguration()
config.scrollDirection = .horizontal
let sectionProvider = ...(your section provider here)
let cvLayout = UICollectionViewCompositionalLayout(sectionProvider: sectionProvider, configuration: config)
Within the sectionProvider you can create a header pinned to the top of each section as follows:
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(40))
let headerSupplementary = NSCollectionLayoutBoundarySupplementaryItem(
layoutSize: headerSize,
elementKind: UICollectionView.elementKindSectionHeader,
alignment: .topLeading)
section.boundarySupplementaryItems = [headerSupplementary]
This setup should achieve the scrolling behaviour you desire. Within each section you could use the following group to achieve the same grid layout as the emoji keyboard:
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitem: item, count: 5)