IOS CollectionView 线性布局

这里写图片描述

线性布局,可以实现左右滑动,并在滑动的时候改变显示的大小。
具体包含以下几个类:
1、UIView 的扩展类目:

UIView+ChangeFrameValue.h
UIView+ChangeFrameValue.m

2、UICollectionViewFlowLayout 子类

LineFlowLayout.h
LineFlowLayout.m

3、UICollectionViewCell 子类

MyCollectionViewCell.h
MyCollectionViewCell.m

4、展示视图

DetailsViewController.h
DetailsViewController.m

源代码如下:

//
//  UIView+ChangeFrameValue.h
//  WaterFallLayout2
//
//  Created by zhengbing on 6/30/16.
//  Copyright © 2016 zhengbing. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UIView (ChangeFrameValue)

@property (nonatomic, assign) CGSize size;
@property (nonatomic, assign) CGPoint origin;
@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;

@end
//
//  UIView+ChangeFrameValue.m
//  WaterFallLayout2
//
//  Created by zhengbing on 6/30/16.
//  Copyright © 2016 zhengbing. All rights reserved.
//

#import "UIView+ChangeFrameValue.h"

@implementation UIView (ChangeFrameValue)

- (void)setOrigin:(CGPoint)origin{
    CGRect rect = self.frame;
    rect.origin = origin;
    self.frame = rect;
}
- (CGPoint)origin{
    return self.frame.origin;
}

- (void)setX:(CGFloat)x{
    CGRect rect = self.frame;
    rect.origin.x  = x;
    self.frame = rect;
}
- (CGFloat)x{
    return self.origin.x;
}

- (void)setY:(CGFloat)y{
    CGRect rect = self.frame;
    rect.origin.y  = y;
    self.frame = rect;
}
- (CGFloat)y{
    return self.origin.y;
}

- (void)setSize:(CGSize)size{
    CGRect rect = self.frame;
    rect.size = size;
    self.frame = rect;
}
- (CGSize)size{
    return self.frame.size;
}

- (void)setWidth:(CGFloat)width{
    CGRect rect = self.frame;
    rect.size.width  = width;
    self.frame = rect;
}
- (CGFloat)width{
    return self.size.width;
}

- (void)setHeight:(CGFloat)height{
    CGRect rect = self.frame;
    rect.size.height = height;
    self.frame = rect;
}
- (CGFloat)height{
    return self.size.height;
}

@end
//
//  LineFlowLayout.h
//  WaterFallLayout2
//
//  Created by zhengbing on 6/30/16.
//  Copyright © 2016 zhengbing. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface LineFlowLayout : UICollectionViewFlowLayout

@end
//
//  LineFlowLayout.m
//  WaterFallLayout2
//
//  Created by zhengbing on 6/30/16.
//  Copyright © 2016 zhengbing. All rights reserved.
//

#import "LineFlowLayout.h"
#import "UIView+ChangeFrameValue.h"

static CGFloat const itemHW = 100;
static CGFloat screenWidth;


@interface LineFlowLayout()
@property (nonatomic, assign) BOOL firstLoaded;
@end


@implementation LineFlowLayout

- (instancetype)init
{
    self = [super init];
    if (self) {

    }
    return self;
}
/**
 *  当layout准备好后 调用
 */
- (void)prepareLayout{
    [super prepareLayout];
    NSLog(@"prepareLayout");
    if (!_firstLoaded) {
        screenWidth = [UIScreen mainScreen].bounds.size.width;
        CGFloat cellInset = (self.collectionView.width - itemHW) * 0.5;
        self.itemSize = CGSizeMake(itemHW, itemHW);
        self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
        self.sectionInset = UIEdgeInsetsMake(0, cellInset, 0, cellInset);
        self.minimumLineSpacing = 70;
        _firstLoaded = YES;
    }
}

/**
 *  判断视图滚动后的位置并返回其offset
 *
 *  @param proposedContentOffset 预计滚动后的位置
 *  @param velocity              滚动速度
 *
 *  @return 返回滚动后所停留的位置
 */
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{
    CGRect lastRect;
    lastRect.origin = proposedContentOffset;
    lastRect.size = self.collectionView.size;
    NSArray *array = [self layoutAttributesForElementsInRect:lastRect];
    CGFloat spacing = MAXFLOAT;
    for (UICollectionViewLayoutAttributes *attr in array) {
        CGFloat newSpacing = attr.center.x - (proposedContentOffset.x + screenWidth * 0.5);
        if ( ABS(newSpacing) < ABS(spacing)) {
            spacing = newSpacing;
        }
    }
    CGPoint backPoint = CGPointMake(proposedContentOffset.x + spacing, proposedContentOffset.y);
    return backPoint;
}

/**
 *  设置为YES则每当显示框改变时 都会调用layout适配
 */
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
    return YES;
}

/**
 *  返回所有显示区域内item属性的方法
 *
 *  @param rect 显示区域内
 */
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
    NSArray *array = [super layoutAttributesForElementsInRect:rect];

    for (UICollectionViewLayoutAttributes *attr in array) {
        CGRect collectionRect;
        collectionRect.origin = self.collectionView.contentOffset;
        collectionRect.size = self.collectionView.size;
        if (CGRectIntersectsRect(collectionRect, attr.frame)) {
            [self changeShowLayoutAttributes:attr];
        }
    }
    return array;
}

/**
 *  改变显示的layoutattributes属性
 */
- (void)changeShowLayoutAttributes:(UICollectionViewLayoutAttributes *)attr{
    CGFloat spacing = attr.center.x - (self.collectionView.contentOffset.x + screenWidth * 0.5);
    spacing = ABS(spacing);
    CGFloat newAlpha = 0.7;
    CGFloat scale = 1;
    if (spacing <= screenWidth * 0.5) {
        scale += 0.5 - 0.5 * (spacing / (screenWidth * 0.5));
        newAlpha += 0.3 - 0.3 * (spacing / (screenWidth * 0.5));
    }
    attr.transform3D = CATransform3DMakeScale(scale, scale, 1.0f);
    attr.alpha = newAlpha;
}

@end
//
//  DetailsViewController.h
//  WaterFallLayout2
//
//  Created by zhengbing on 6/30/16.
//  Copyright © 2016 zhengbing. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface DetailsViewController : UIViewController

@end
//
//  DetailsViewController.m
//  WaterFallLayout2
//
//  Created by zhengbing on 6/30/16.
//  Copyright © 2016 zhengbing. All rights reserved.
//

#import "DetailsViewController.h"
#import "MyCollectionViewCell.h"
#import "WaterLayout.h"
#import "LineFlowLayout.h"

#define CELLID @"DetailsViewController"


@interface DetailsViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>
@property(nonatomic, strong)NSMutableArray * dataSource;
@property(nonatomic, strong)UICollectionView * collectionView;

@end

@implementation DetailsViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self initData];
    [self initUI];
}
-(void)initData{
    _dataSource = [NSMutableArray array];
    for (int i = 0; i < 20; i++) {
        NSString *imageName = [NSString stringWithFormat:@"%d",i+1];
        [_dataSource addObject:imageName];
    }
}
-(void)initUI{
    self.view.backgroundColor = [UIColor yellowColor];
    [self.view addSubview:self.collectionView];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark getter and setter
-(UICollectionView *)collectionView{
    if (!_collectionView) {

        //线性布局
        _collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, 250) collectionViewLayout:[[LineFlowLayout alloc] init]];
        _collectionView.delegate = self;
        _collectionView.dataSource = self;
        _collectionView.backgroundColor = [UIColor yellowColor];
        [_collectionView registerNib:[UINib nibWithNibName:@"MyCollectionViewCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:CELLID];
    }
    return _collectionView;
}


#pragma mark delegate
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    return _dataSource.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    MyCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:CELLID forIndexPath:indexPath];
    cell.imageName = _dataSource[indexPath.row];
    return cell;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值