一个好用的iOS 动态宽度自适应layout LBAttributeLayout

效果图
请添加图片描述

LBAttributeLayout

场景

该布局的使用场景有很多:搜索记录
,商品sku, 一些标签等等

实现原理

UICollectionFlowLayout 是 在prepareLayout
创建布局属性,然后 通过
collectionViewContentSize 方法返回内容的size
通过layoutAttributesForElementsInRect 方法
返回各个item的布局的,
所以,我们自定义layout 的时候,需要重写这三个方法

  • (void)prepareLayout {

  • (CGSize)collectionViewContentSize {
    }

  • (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
    }

核心逻辑

这种自适应宽度布局,最关键的是我们要给不同的
item设置不同的宽度,
其他的如高度,间隙等都可以通过属性来配置,只有宽度是动态的,
所以我们可以在 prepareLayout 中通过代理即时
获取某个item的宽度

关键代码

- (void)prepareLayout {
    [super prepareLayout];
    [self updateLayout];
}
- (void)updateLayout {
    // 移除旧的布局
    [self.layoutAttributesArray removeAllObjects];
    self.contentSize = CGSizeMake(self.contentWidth, 0);
    // 计算新的布局
    NSInteger count = 0;
    if ([self.collectionView.dataSource respondsToSelector:@selector(collectionView:numberOfItemsInSection:)]) {
        count = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:0];
    }
    if (count > 0) {
        CGFloat x = self.contentInset.left;
        if ([UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) {
            x = self.contentSize.width - self.contentInset.left;
        }
        CGFloat y = self.contentInset.top;
        for (int i = 0; i < count; i++) {
            CGFloat currentX = x;
            CGFloat currentY = y;
            CGFloat cellWidth = [self cellWidthForItemAtIndex:i];
            CGFloat cellHeight = self.cellHeight;
            // 换行检测
            if ([UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionLeftToRight) {
                if (currentX + cellWidth + self.contentInset.right > self.contentSize.width) {
                    currentX = self.contentInset.left;
                    currentY = currentY + cellHeight + self.cellVerticalSpace;
                }
            } else {
                if (currentX - cellWidth - self.contentInset.right < 0) {
                    currentX = self.contentSize.width - self.contentInset.left;
                    currentY = currentY + cellHeight + self.cellVerticalSpace;
                }
            }
         
            layoutAttributes.frame = CGRectMake(currentX, currentY, cellWidth, cellHeight);
            if ([UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) {
                layoutAttributes.frame = CGRectMake(currentX - cellWidth, currentY, cellWidth, cellHeight);
            }
            [self.layoutAttributesArray addObject:layoutAttributes];
            // 计算下一个item的origin,以及布局更新结束检测
            if (i < count - 1) {
                x = currentX + cellWidth + self.cellHorizontalSpace;
                if ([UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) {
                    x = currentX - cellWidth - self.cellHorizontalSpace;
                }
                y = currentY;
            } else {
                self.contentSize = CGSizeMake(self.contentWidth, currentY + cellHeight + self.contentInset.bottom);
            }
        }
    }
}

使用方法

//创建 collectionView
- (UICollectionView *)collectionView
{
    if (!_collectionView) {
        LBAttributeLayout *layout = [[LBAttributeLayout alloc] initWithConfiguration:self.configuration];
        layout.delegate = self;
        _collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 100, CGRectGetWidth(self.view.bounds), 200) collectionViewLayout:layout];
        [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:NSStringFromClass([UICollectionViewCell class])];
        _collectionView.dataSource = self;
        _collectionView.delegate = self;
    }
    return _collectionView;
}

#计算内容高度

NSMutableArray *widthArray = [NSMutableArray array];
for (int i = 0; i < self.dataSource.count; i ++) {
    CGFloat width = [self cellWidthForItemAtIndex:i];
    [widthArray addObject:@(width)];
}
CGFloat height = [LBAttributeLayout contentHeightWithConfiguration:self.configuration cellWidthArray:widthArray];
self.collectionView.frame = CGRectMake(0, 100, CGRectGetWidth(self.view.bounds), height);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值