How do you vertically align UICollectionViewCells in a UICollectionView?

I have cells with different heights on the horizontal scroll of the UICollectionView , which seems to evenly distribute the cells vertically, leaving blank space between the cells, and I would like them to align them and have a variable blank space at the bottom of each column.

+6
source share
3 answers

I have expanded my UICollectionViewFlowLayout provided by my UICollectionView. The following redefinition worked for me.

 #import "TopAlignedCollectionViewFlowLayout.h" const NSInteger kVerticalSpacing = 10; @implementation TopAlignedCollectionViewFlowLayout - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { NSArray* attributesToReturn = [super layoutAttributesForElementsInRect:rect]; for (UICollectionViewLayoutAttributes* attributes in attributesToReturn) { if (nil == attributes.representedElementKind) { NSIndexPath* indexPath = attributes.indexPath; attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame; } } return attributesToReturn; } - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewLayoutAttributes* currentItemAttributes = [super layoutAttributesForItemAtIndexPath:indexPath]; UIEdgeInsets sectionInset = [(UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout sectionInset]; if (indexPath.item == 0) { CGRect frame = currentItemAttributes.frame; frame.origin.y = sectionInset.top; currentItemAttributes.frame = frame; return currentItemAttributes; } NSIndexPath* previousIndexPath = [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section]; CGRect previousFrame = [self layoutAttributesForItemAtIndexPath:previousIndexPath].frame; CGFloat previousFrameRightPoint = previousFrame.origin.y + previousFrame.size.height + kVerticalSpacing; CGRect currentFrame = currentItemAttributes.frame; CGRect strecthedCurrentFrame = CGRectMake(currentFrame.origin.x, 0, currentFrame.size.width, self.collectionView.frame.size.height ); if (!CGRectIntersectsRect(previousFrame, strecthedCurrentFrame)) { CGRect frame = currentItemAttributes.frame; frame.origin.y = frame.origin.y = sectionInset.top; currentItemAttributes.frame = frame; return currentItemAttributes; } CGRect frame = currentItemAttributes.frame; frame.origin.y = previousFrameRightPoint; currentItemAttributes.frame = frame; return currentItemAttributes; } @end 
+12
source

I put this in Xamarin / MonoTouch for my project and thought it might be useful

 public class TopAlignedCollectionViewFlowLayout : UICollectionViewFlowLayout { const int VerticalSpacing = 10; public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect(RectangleF rect) { var attributesToReturn = base.LayoutAttributesForElementsInRect(rect); foreach (UICollectionViewLayoutAttributes attributes in attributesToReturn) { if (attributes.RepresentedElementKind == null) { var indexPath = attributes.IndexPath; attributes.Frame = this.LayoutAttributesForItem(indexPath).Frame; } } return attributesToReturn; } public override UICollectionViewLayoutAttributes LayoutAttributesForItem(NSIndexPath indexPath) { var currentItemAttributes = base.LayoutAttributesForItem(indexPath); UIEdgeInsets sectionInset = ((UICollectionViewFlowLayout) this.CollectionView.CollectionViewLayout).SectionInset; if (indexPath.Item == 0) { var frame1 = currentItemAttributes.Frame; frame1.Y = sectionInset.Top; currentItemAttributes.Frame = frame1; return currentItemAttributes; } var previousIndexPath = NSIndexPath.FromItemSection(indexPath.Item - 1, indexPath.Section); var previousFrame = this.LayoutAttributesForItem(previousIndexPath).Frame; var previousFrameRightPoint = previousFrame.Y + previousFrame.Size.Height + VerticalSpacing; var currentFrame = currentItemAttributes.Frame; var strecthedCurrentFrame = new RectangleF(currentFrame.X, 0, currentFrame.Size.Width, this.CollectionView.Frame.Size.Height); if (!previousFrame.IntersectsWith(strecthedCurrentFrame)) { var frame = currentItemAttributes.Frame; frame.Y = frame.Y = sectionInset.Top; currentItemAttributes.Frame = frame; return currentItemAttributes; } RectangleF frame2 = currentItemAttributes.Frame; frame2.Y = previousFrameRightPoint; currentItemAttributes.Frame = frame2; return currentItemAttributes; } } 
+3
source

I assume that you are using UICollectionViewFlowLayout to layout your cells. I do not think you can do this with a thread layout. You may have to write your own subclass of UICollectionViewLayout to align the top edges of each cell.

This is not a pretty solution, but what about all your cells being the same size and setting limits in your cell to align the content at the top? This can mimic the look you are going to use without subclassing UICollectionViewLayout.

0
source

Source: https://habr.com/ru/post/946993/


All Articles