美文网首页
UICollectionview 设置 section ba

UICollectionview 设置 section ba

作者: Zxinli | 来源:发表于2018-12-28 11:42 被阅读0次
    1.需求:

    在同一个页面展示分类items,类别之间使用特定的“容器”视图包裹此分类下的所有元素,分类头部和尾部要显示相关数据。如下图:

    image
    2.可选方案:
    1. 使用UITableView或者UICollectionView,一个分类就是一个cell或者item, 每个cell或item内再绘制类别下所有元素。
    2. 使用UICollectionView,每个元素都是一个item,这时候就需要想办法,把相应的item给“包”起来。

    方案“1”无疑是最简单的实现,但是如果当一个类别的元素特别多,而且类别需要显示的UI特别复杂(例如一个cell里面有N多个元素),就会因为这个大cell需要一次性绘制,包括没有显示在屏幕内的元素,会造成性能问题。
    所以我们来探讨一下方案“2”的实现。

    3. 实现:

    每个类别header、section、footer上中下三层,底下一个DecorationView。

    image image

    创建一个UICollectionView,使用自定义的layout(继承UICollectionViewFlowLayout)。

    #import "ViewController.h"
    #import "HVWLayout.h"
    #import "HVWHeader.h"
    #import "HVWFooter.h"
    
    @interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate>
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    
        self.view.backgroundColor = [UIColor whiteColor];
        self.automaticallyAdjustsScrollViewInsets = NO;
    
        HVWLayout *layout = [[HVWLayout alloc] init];
        layout.itemSize = CGSizeMake(80, 80);
        layout.headerReferenceSize = CGSizeMake(self.view.bounds.size.width, 90);
        layout.footerReferenceSize = CGSizeMake(self.view.bounds.size.width, 70);
        layout.sectionInset = UIEdgeInsetsMake(0, 30, 0, 30);
        layout.minimumLineSpacing = 20;
        layout.minimumInteritemSpacing = ([UIScreen mainScreen].bounds.size.width - 80 * 3 - 60) / 2;
    
        UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
        collectionView.backgroundColor = [UIColor whiteColor];
        [self.view addSubview:collectionView];
    
        collectionView.dataSource = self;
        collectionView.delegate = self;
    
        [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
        [collectionView registerClass:[HVWHeader class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];
        [collectionView registerClass:[HVWFooter class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"footer"];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    #pragma mark - UICollectionViewDataSource
    - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
        return 10;
    }
    
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
        return section + 4;
    }
    
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
        UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
        cell.backgroundColor = [UIColor orangeColor];
        return cell;
    }
    
    - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
        if (kind == UICollectionElementKindSectionHeader) {
            return [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header" forIndexPath:indexPath];
    
        } else if (kind == UICollectionElementKindSectionFooter) {
            return [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"footer" forIndexPath:indexPath];
        }
    
        return nil;
    }
    
    #pragma mark - UICollectionViewDelegate
    
    @end
    
    

    在layout里面配置DecorationView,计算出位置。

    #import "HVWLayout.h"
    #import "HVWDecorationView.h"
    
    @implementation HVWLayout
    
    - (void)prepareLayout {
        [super prepareLayout];
    
        [self registerClass:[HVWDecorationView class] forDecorationViewOfKind:@"decorationView"];
    }
    
    - (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath top:(CGFloat)top {
        UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:elementKind withIndexPath:indexPath];
    
        NSUInteger numberOfItems = [self.collectionView numberOfItemsInSection:indexPath.section];
        int itemsPerRow = 3;
        NSUInteger rows = (numberOfItems + itemsPerRow - 1) / itemsPerRow;
        CGFloat cellHeight = 80;
        CGFloat cellSpace = 20;
        CGFloat headerHeigh = 90;
        CGFloat footerHeight = 70;
        CGFloat height = headerHeigh + cellHeight * rows + cellSpace * (rows - 1) + footerHeight;
    
        attrs.frame = CGRectMake(0, top, [UIScreen mainScreen].bounds.size.width, height);
        attrs.zIndex = -1;
    //    NSLog(@"%s", __func__);
    
        return attrs;
    }
    
    - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
        NSArray *superAttrs = [super layoutAttributesForElementsInRect:rect];
        NSMutableArray *attrs = [NSMutableArray arrayWithArray:superAttrs];
    
        for (UICollectionViewLayoutAttributes *attr in superAttrs) {
            if (attr.representedElementKind == UICollectionElementKindSectionHeader) {
                [attrs addObject:[self layoutAttributesForDecorationViewOfKind:@"decorationView" atIndexPath:attr.indexPath top:attr.frame.origin.y]];
            }
        }
    
    //    NSLog(@"%s", __func__);
    
        return attrs;
    }
    
    

    在DecorationView中,重写方法applyLayoutAttributes,重新计算布局view内的元素。

    注意不能靠重写setFrame或者layoutSubViews来布局,因为这两方法只在初始化的时候调用一次,重用就不会调用了。

    #import "HVWDecorationView.h"
    
    @interface HVWDecorationView()
    
    @property(nonatomic, strong) UIImageView *imageView;
    
    @end
    
    @implementation HVWDecorationView
    
    - (instancetype)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
    //        self.backgroundColor = [UIColor grayColor];
    
            _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, frame.size.width - 20, frame.size.height - 20)];
            UIImage *image = [UIImage imageNamed:@"bg"];
            _imageView.image = [image stretchableImageWithLeftCapWidth:image.size.width/2 topCapHeight:image.size.height/2];
            [self addSubview:_imageView];
        }
    
        return self;
    }
    
    - (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
        [super applyLayoutAttributes:layoutAttributes];
    //    NSLog(@"%s", __func__);
    
        _imageView.frame = CGRectMake(10, 10, layoutAttributes.frame.size.width - 20, layoutAttributes.frame.size.height - 20);
    }
    

    作者:西蒙SIMON
    链接:https://www.jianshu.com/p/565dfb3c23d1
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    相关文章

      网友评论

          本文标题:UICollectionview 设置 section ba

          本文链接:https://www.haomeiwen.com/subject/swdslqtx.html