IOS实现自定义布局瀑布流

2020-01-14 18:52:33刘景俊

设置UICollectionView停止滚动是的偏移量,使其为与中心点


- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
  //计算最终显示的矩形框
  CGRect rect;
  rect.origin.x = proposedContentOffset.x;
  rect.origin.y = 0;
  rect.size = self.collectionView.frame.size;

  //获取最终显示在矩形框中的元素的布局属性
  NSArray *array = [super layoutAttributesForElementsInRect:rect];

  //获取UICollectionView的中点,以contentView的左上角为原点
  CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;

  //获取所有元素到中点的最短距离
  CGFloat minDelta = MAXFLOAT;
  for (UICollectionViewLayoutAttributes *attribute in array)
  {
    CGFloat delta = attribute.center.x - centerX;
    if (ABS(minDelta) > ABS(delta))
    {
      minDelta = delta;
    }
  }

  //改变UICollectionView的偏移量
  proposedContentOffset.x += minDelta;
  return proposedContentOffset;
}

自定义圆形普通布局
定义成员属性,保存所有的布局属性


@property (nonatomic, strong) NSMutableArray *attrsArray;

懒加载,初始化attrsArray


- (NSMutableArray *)attrsArray
{
  if (_attrsArray == nil)
  {
    _attrsArray = [NSMutableArray array];
  }
  return _attrsArray;
}

初始化布局


- (void)prepareLayout
{
  [super prepareLayout];

  //移除所有旧的布局属性
  [self.attrsArray removeAllObjects];

  //获取元素的个数
  NSInteger count = [self.collectionView numberOfItemsInSection:0];
  //布局所有的元素
  for (NSInteger i = 0; i<count; i++)
  {
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
    //设置并获取indexPath位置元素的布局属性
    UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
    //将indexPath位置元素的布局属性添加到所有布局属性数组中
    [self.attrsArray addObject:attrs];
  }
}

布局indexPath位置的元素


- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
  //获取元素的个数
  NSInteger count = [self.collectionView numberOfItemsInSection:0];

  /**设置圆心布局*/
  //设置圆形的半径
  CGFloat radius = 70;
  //圆心的位置
  CGFloat oX = self.collectionView.frame.size.width * 0.5;
  CGFloat oY = self.collectionView.frame.size.height * 0.5;
  //获取indexPath位置的元素的布局属性
  UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
  //设置尺寸
  attrs.size = CGSizeMake(50, 50);
  //设置位置
  if (count == 1)
  {
    attrs.center = CGPointMake(oX, oY);
  }
  else
  {
    CGFloat angle = (2 * M_PI / count) * indexPath.item;
    CGFloat centerX = oX + radius * sin(angle);
    CGFloat centerY = oY + radius * cos(angle);
    attrs.center = CGPointMake(centerX, centerY);
  }
  //返回indexPath位置元素的布局属性
  return attrs;
}