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

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

Related

UICollectionView compositional layout: custom item size for remaining space?

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!

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

Place NSCollectionLayoutBoundarySupplementaryItem on top of cells

I'm having trouble with adding a footer in UICollectionViewCompositionalLayout on top of the cells. Specifically I want to have an interactive control in my footer (in my case a UIPageControl). This is an example layout,
func generateLayout() -> UICollectionViewCompositionalLayout {
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1)))
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1),
heightDimension: .absolute(213)
)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 1)
let section = NSCollectionLayoutSection(group: group)
section.boundarySupplementaryItems = [footer()]
return UICollectionViewCompositionalLayout(section: section)
}
The footer is configured like,
private func footer() -> NSCollectionLayoutBoundarySupplementaryItem {
let size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(20))
let item = NSCollectionLayoutBoundarySupplementaryItem(
layoutSize: size,
elementKind: "footer-kind",
alignment: .bottom,
absoluteOffset: .init(x: 0, y: -30)
)
item.zIndex = 1000
return item
}
Lets say I have a button in my Footer that I want to be tappable. I have changed the zIndex of the footer so it is higher than other views in my section.
class FooterCell: UICollectionReusableView {
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
super.apply(layoutAttributes)
layer.zPosition = CGFloat(layoutAttributes.zIndex)
}
}
The result of the snippets above is that the button is visible on top of the cells, but not tappable. After some inspections in the view debugger it is clear that the supplementary view is added to the view hierarchy before the cells and changing the zIndex only moves the layer to the front, not the complete view. Is there someway to change the order on how the views are added in the compositional layout? Or is there any other way to bring the footer view above the cells?

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