• 自定义流水布局(UICollectionViewFlowLayout的基本使用)


    最终显示的效果图

    思路:

    1、UICollection的基本设置,并且创建一个继承自UICollectionViewFlowLayout的类。(不能是UICollectionViewLayout,否则全部都需要自定义)

    2、在UICollectionViewFlowLayout类中完成四步

      - 1)重写prepareLayout方法进行基本的布局(cell在最左面的时候是在正中间),不能在init中布局,因为设置collectionView尺寸是在viewDidLoad中,而init在它之前调用,获得的collectionView的尺寸是空的

      - 2)重写shouldInvalidateLayoutForBoundsChange,当collectionView的显示范围发生改变的时候,让其内部重新布局(即让cell滚动起来)

      - 3)重写layoutAttributesForElementsInRect方法,让cell在左右滑动的时候,尺寸放大或缩小

      - 4)重写targetContentOffsetForProposedContentOffset方法,让最接近中心的cell在停在正中央。

    代码如下:

    viewContorller中:

     1 #import "ViewController.h"
     2 #import "ZWLineLayout.h"
     3 @interface ViewController () <UICollectionViewDataSource>
     4 @end
     5 @implementation ViewController
     6 static  NSString *ZWCellID = @"cell";
     7 - (void)viewDidLoad {
     8     [super viewDidLoad];
     9     //若为UICollectionViewLayout,itemSize和scrollDirection都需要自己写,下面的类继承自UICollectionViewLayout
    10     ZWLineLayout *layout = [[ZWLineLayout alloc] init];
    11     layout.itemSize = CGSizeMake(160, 160);
    12     CGRect rect = CGRectMake(0, 100, self.view.frame.size.width, self.view.frame.size.width * 0.6);
    13     UICollectionView *collection = [[UICollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
    14     collection.dataSource = self;
    15     collection.backgroundColor = [UIColor greenColor];
    16     [self.view addSubview:collection];
    17     [collection registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:ZWCellID];
    18 }
    19 
    20 #pragma mark - 数据源方法
    21 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    22 {
    23     return 10;
    24 }
    25 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    26 {
    27     UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ZWCellID forIndexPath:indexPath];
    28     cell.backgroundColor = [UIColor orangeColor];
    29     return cell;
    30 }

    ZWLineLayout.m中

     1 #import "ZWLineLayout.h"
     2 
     3 @implementation ZWLineLayout
     4 
     5 /**
     6  * 用来做布局的初始化操作(不建议在init方法中进行布局的初始化操作)
     7  */
     8 - (void)prepareLayout
     9 {
    10     [super prepareLayout];
    11     //水平滚动
    12     self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    13     
    14     //
    15     CGFloat margin = (self.collectionView.frame.size.width - self.itemSize.width) / 2;
    16     self.collectionView.contentInset = UIEdgeInsetsMake(0, margin, 0, margin);
    17 }
    18 
    19 /**
    20  * 当collectionView的显示范围发生改变的时候,是否需要重新刷新布局
    21  * 一旦重新刷新布局,就会重新调用下面的方法:
    22  * 1.prepareLayout
    23  * 2.layoutAttributesForElementsInRect:方法
    24  */
    25 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
    26 {
    27     return YES;
    28 }
    29 
    30 
    31 /**
    32  * 这个方法的返回值是一个数组(数组里面存放着rect范围内所有元素的布局属性)
    33  * 这个方法的返回值决定了rect范围内所有元素的排布(frame)
    34  */
    35 //需要在viewController中使用上ZWLineLayout这个类后才能重写这个方法!!
    36 - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
    37 {
    38     //让父类布局好样式
    39     NSArray *arr = [super layoutAttributesForElementsInRect:rect];
    40     //计算出collectionView的中心的位置
    41     CGFloat ceterX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;
    42     /**
    43      * 1.一个cell对应一个UICollectionViewLayoutAttributes对象
    44      * 2.UICollectionViewLayoutAttributes对象决定了cell的frame
    45      */
    46     for (UICollectionViewLayoutAttributes *attributes in arr) {
    47         //cell的中心点距离collectionView的中心点的距离,注意ABS()表示绝对值
    48         CGFloat delta = ABS(attributes.center.x - ceterX);
    49         //设置缩放比例
    50         CGFloat scale = 1.1 - delta / self.collectionView.frame.size.width;
    51         //设置cell滚动时候缩放的比例
    52         attributes.transform = CGAffineTransformMakeScale(scale, scale);
    53     }
    54     
    55     return arr;
    56 }
    57 
    58 /**
    59  * 这个方法的返回值,就决定了collectionView停止滚动时的偏移量
    60  */
    61 - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
    62 {
    63     // 计算出最终显示的矩形框
    64     CGRect rect;
    65     rect.origin.y = 0;
    66     rect.origin.x = proposedContentOffset.x;
    67     rect.size = self.collectionView.frame.size;
    68     
    69     //获得super已经计算好的布局的属性
    70     NSArray *arr = [super layoutAttributesForElementsInRect:rect];
    71     
    72     //计算collectionView最中心点的x值
    73     CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;
    74     
    75     CGFloat minDelta = MAXFLOAT;
    76     for (UICollectionViewLayoutAttributes *attrs in arr) {
    77         if (ABS(minDelta) > ABS(attrs.center.x - centerX)) {
    78             minDelta = attrs.center.x - centerX;
    79         }
    80     }
    81     proposedContentOffset.x += minDelta;
    82     return proposedContentOffset;
    83 }
    84 @end
  • 相关阅读:
    grpc stream剖析
    Pravega架构小结
    Flink之对时间的处理
    一张图说清楚Flink水印和Lateness
    Flink kuduSink开发
    Axsure动态面板下不同状态页面间的交互
    Axsure制作图片动态验证码
    透过用户思维谈程序员的进阶之路
    redis整合Spring之序列化对象与反序列化
    Java基础面试题
  • 原文地址:https://www.cnblogs.com/hissia/p/5723629.html
Copyright © 2020-2023  润新知