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
Related
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!
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
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
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?
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)