• 自定义流布局


    一、自定义布局【相册】

    需求:

    1.横向滚动

    2.照片离中心点越近图片越大,即图片的放大和缩小

    3.滚动停止时候总有一张照片居中显示

    1、自定义布局 - 继承自UICollectionViewFlowLayout

    重写prepareLayout方法

       作用:在这个方法中做一些初始化的操作

       注意:一定要调用[super prepareLayout]方法

    2、重写layoutAttributesForElementsInRect:方法

    作用 :

       这个方法的返回值是个数组

       这个数组中存放着的都是UICollectionViewLayoutAttribute对象

      (1)一个cell对应一个UICollectionViewLayoutAttributes对象

      (2)UICollectionViewLayoutAttribute对象决定了Cell的排布方式(frame)

    3、重写shouldInvalidateLayoutForBoundsChange方法

    作用 如果返回YES,那么CollectionView显示的范围发生改变的时候,就会重新刷新布局

    一旦重新刷新布局,就会按顺序调用下面的方法:

       prepareLayout

       layoutAttributesForElementsInRect:

    4、重写targetContentOffsetForProposedContentOffset:withScrollingVelocity:方法

    -作用 返回值决定了collectionView停止滚动时最终的偏移量(contentOffset)

    -参数:

       -proposedContentOffset:原本情况下,collectionView停止滚动时最终的偏移量

       -velocity:滚动速率,通过这个参数可以了解滚动的方向

    #import "ViewController.h"
    #import "WXPhotoCell.h"
    #import "WXLineLayout.h"
    
    @interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>
    
    @end
    
    @implementation ViewController
    
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //创建布局
        WXLineLayout *layout = [[WXLineLayout alloc]init];
        layout.itemSize = CGSizeMake(150, 150);
        
        //创建CollectionView
        CGFloat collectionW = self.view.frame.size.width;
        CGFloat collectionH = 200;
        UICollectionView *WXCollectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 100, collectionW, collectionH) collectionViewLayout:layout];
        WXCollectionView.delegate = self;
        WXCollectionView.dataSource = self;
        [self.view addSubview:WXCollectionView];
        
        //注册
        [WXCollectionView registerNib:[UINib nibWithNibName:NSStringFromClass([WXPhotoCell class]) bundle:nil] forCellWithReuseIdentifier:@"photoCell"];
        
    }
    
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
        return 5;
    }
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
        WXPhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"photoCell" forIndexPath:indexPath];
        if (!cell) {
            cell = [[WXPhotoCell alloc]init];
        }
        cell.imageName = [NSString stringWithFormat:@"%zd",indexPath.item+1];
        return cell;
    }

    自定义布局WXLineLayout继承自UICollectionViewFlowLayout

     缩放计算

    算出collectionView和cell 中心点的间距

    ABS(a-b)//取绝对值

    //
    //  WXLineLayout.m
    //  自定义流布局
    //
    //  Created by wangxu on 16/7/9.
    //  Copyright © 2016年 Somebody. All rights reserved.
    //
    
    #import "WXLineLayout.h"
    
    @implementation WXLineLayout
    
    
    - (instancetype)init{
        if (self = [super init]) {
            
        }
        return self;
    }
    /*
     当collectionView的显示范围发生改变的时候,是否需要重新刷新布局
     一旦重新刷新布局,就会调用下面两个方法
     1.prepareLayout
     2.layoutAttributesForElementsInRect:方法
     */
    - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
        
        return YES;
    }
    //用来做布局的初始化操作(不建议在init方法中进行布局的初始化操作)
    - (void)prepareLayout{
        [super prepareLayout];
        
        //设置水平滚动
        self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
        //设置内边距
        CGFloat inset = (self.collectionView.frame.size.width-self.itemSize.width)*0.5;
        self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
    }
    /*
     UICollectionViewLayoutAttributes *attrs;
     1.一个cell对应一个UICollectionViewLayoutAttributes对象
     2.UICollectionViewLayoutAttributes对象决定了Cell的frame
     */
    /*
     这个方法的返回值是一个数组,(数组里存放着rect范围内所有元素的布局属性)
     这个方法的返回值决定了rect范围内所有元素的排布(frame)
     */
    - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
        
        NSLog(@"=======");
        //获取super已经计算好的布局属性
        NSArray * array = [super layoutAttributesForElementsInRect:rect];
        
        //计算collectionView最中心的X值
        CGFloat collectionCenterX = self.collectionView.contentOffset.x+self.collectionView.frame.size.width * 0.5;
        //在原有布局的基础上,进行微调
        for (UICollectionViewLayoutAttributes *attrs in array) {
            //计算cell中心点X值
            CGFloat cellX = attrs.center.x;
            //计算collectionView中心点X值和Cell中心点X值间的距离
            CGFloat delta = ABS(cellX-collectionCenterX);
            
            //根据间距计算 cell的缩放比例
            CGFloat scale = 1 - delta/self.collectionView.frame.size.width;
            //设置缩放比例
            attrs.transform = CGAffineTransformMakeScale(scale, scale);
        }
        return array;
    }
    /*
     这个方法的返回值,决定了colletionView停止滚动时的偏移量
     */
    - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{
        
        //计算出最终显示的矩形框
        CGRect rect;
        rect.origin.x = proposedContentOffset.x;
        rect.origin.y = 0;
        rect.size = self.collectionView.frame.size;
        
        //获取滚动结束后super已经计算好的布局属性
        NSArray *array = [super layoutAttributesForElementsInRect:rect];
        //计算collectionView最中心点的X值
        CGFloat collectionCenterX = self.collectionView.frame.size.width*0.5 + proposedContentOffset.x;
        //存放最小的间距
        CGFloat minDelta = MAXFLOAT;
        for (UICollectionViewLayoutAttributes *attrs in array) {
            if (ABS(minDelta)>ABS(attrs.center.x-collectionCenterX)) {
                minDelta = attrs.center.x-collectionCenterX;
            }
        }
        //修改原有的偏移量
        proposedContentOffset.x+=minDelta;
        return proposedContentOffset;
    }
    
    
    @end

    自定义UICollectionViewCell

    //
    //  WXPhotoCell.h
    //  自定义流布局
    //
    //  Created by wangxu on 16/7/9.
    //  Copyright © 2016年 Somebody. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface WXPhotoCell : UICollectionViewCell
    /** 图片名*/
    @property (nonatomic, copy) NSString *imageName;
    @end
    //
    //  WXPhotoCell.m
    //  自定义流布局
    //
    //  Created by wangxu on 16/7/9.
    //  Copyright © 2016年 Somebody. All rights reserved.
    //
    
    #import "WXPhotoCell.h"
    @interface WXPhotoCell ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    
    @end
    @implementation WXPhotoCell
    
    - (void)awakeFromNib {
        [super awakeFromNib];
        //设置照片的白色边框
        self.imageView.layer.borderWidth = 5;
        self.imageView.layer.borderColor = [UIColor whiteColor].CGColor;
    }
    - (void)setImageName:(NSString *)imageName{
        
        //设置cell的图片
        _imageName = [imageName copy];
        self.imageView.image = [UIImage imageNamed:imageName];
    }
    
    @end

                      

    新手上路,还请大神们多多指教。

    致谢MJ老师。

  • 相关阅读:
    只要实现了IListSource, IEnumerable, or IDataSource的对象都可以作为DataSource进行Binding
    我的博客开张了!
    EnableViewState对Table, TableRow, TableCell不起作用?
    Bubble Sort (c#)
    trigger
    查询数据库中触发器的两种方法
    招聘要求
    调用搜索引擎代码
    JavaScript,只有你想不到
    [RIA]HTML5怎么就成了RIA“杀手”?
  • 原文地址:https://www.cnblogs.com/somebodywx/p/5658254.html
Copyright © 2020-2023  润新知