线性布局,可以实现左右滑动,并在滑动的时候改变显示的大小。
具体包含以下几个类:
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