KWCustomLayout.m 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. //
  2. // KWCustomLayout.m
  3. // westkissMob
  4. //
  5. // Created by iOS on 2022/9/14.
  6. //
  7. #import "KWCustomLayout.h"
  8. @interface UICollectionViewLayoutAttributes (LeftAligned)
  9. - (void)leftAlignFrameWithSectionInset:(UIEdgeInsets)sectionInset;
  10. @end
  11. @implementation UICollectionViewLayoutAttributes (LeftAligned)
  12. - (void)leftAlignFrameWithSectionInset:(UIEdgeInsets)sectionInset
  13. {
  14. CGRect frame = self.frame;
  15. frame.origin.x = sectionInset.left;
  16. self.frame = frame;
  17. }
  18. @end
  19. @implementation KWCustomLayout
  20. #pragma mark - UICollectionViewLayout
  21. - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
  22. NSArray *originalAttributes = [super layoutAttributesForElementsInRect:rect];
  23. NSMutableArray *updatedAttributes = [NSMutableArray arrayWithArray:originalAttributes];
  24. for (UICollectionViewLayoutAttributes *attributes in originalAttributes) {
  25. if (!attributes.representedElementKind) {
  26. NSUInteger index = [updatedAttributes indexOfObject:attributes];
  27. updatedAttributes[index] = [self layoutAttributesForItemAtIndexPath:attributes.indexPath];
  28. }
  29. }
  30. return updatedAttributes;
  31. }
  32. - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
  33. UICollectionViewLayoutAttributes* currentItemAttributes = [[super layoutAttributesForItemAtIndexPath:indexPath] copy];
  34. UIEdgeInsets sectionInset = [self evaluatedSectionInsetForItemAtIndex:indexPath.section];
  35. BOOL isFirstItemInSection = indexPath.item == 0;
  36. CGFloat layoutWidth = CGRectGetWidth(self.collectionView.frame) - sectionInset.left - sectionInset.right;
  37. if (isFirstItemInSection) {
  38. [currentItemAttributes leftAlignFrameWithSectionInset:sectionInset];
  39. return currentItemAttributes;
  40. }
  41. NSIndexPath* previousIndexPath = [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section];
  42. CGRect previousFrame = [self layoutAttributesForItemAtIndexPath:previousIndexPath].frame;
  43. CGFloat previousFrameRightPoint = previousFrame.origin.x + previousFrame.size.width;
  44. CGRect currentFrame = currentItemAttributes.frame;
  45. CGRect strecthedCurrentFrame = CGRectMake(sectionInset.left,
  46. currentFrame.origin.y,
  47. layoutWidth,
  48. currentFrame.size.height);
  49. // if the current frame, once left aligned to the left and stretched to the full collection view
  50. // width intersects the previous frame then they are on the same line
  51. BOOL isFirstItemInRow = !CGRectIntersectsRect(previousFrame, strecthedCurrentFrame);
  52. if (isFirstItemInRow) {
  53. // make sure the first item on a line is left aligned
  54. [currentItemAttributes leftAlignFrameWithSectionInset:sectionInset];
  55. return currentItemAttributes;
  56. }
  57. CGRect frame = currentItemAttributes.frame;
  58. frame.origin.x = previousFrameRightPoint + [self evaluatedMinimumInteritemSpacingForSectionAtIndex:indexPath.section];
  59. currentItemAttributes.frame = frame;
  60. return currentItemAttributes;
  61. }
  62. - (CGFloat)evaluatedMinimumInteritemSpacingForSectionAtIndex:(NSInteger)sectionIndex
  63. {
  64. if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:minimumInteritemSpacingForSectionAtIndex:)]) {
  65. id<UICollectionViewDelegateLeftAlignedLayout> delegate = (id<UICollectionViewDelegateLeftAlignedLayout>)self.collectionView.delegate;
  66. return [delegate collectionView:self.collectionView layout:self minimumInteritemSpacingForSectionAtIndex:sectionIndex];
  67. } else {
  68. return self.minimumInteritemSpacing;
  69. }
  70. }
  71. - (UIEdgeInsets)evaluatedSectionInsetForItemAtIndex:(NSInteger)index
  72. {
  73. if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) {
  74. id<UICollectionViewDelegateLeftAlignedLayout> delegate = (id<UICollectionViewDelegateLeftAlignedLayout>)self.collectionView.delegate;
  75. return [delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:index];
  76. } else {
  77. return self.sectionInset;
  78. }
  79. }
  80. @end