瀑布流 collectionView实现

来源:互联网 发布:淘宝网羽绒服布料 编辑:程序博客网 时间:2024/05/16 11:37

一 继承UICollectionViewLayout,重写子类PBCollectionViewLayout方法

#import <UIKit/UIKit.h>


@interface PBCollectionViewLayout : UICollectionViewLayout

@property (nonatomic,assign) NSInteger queueNum;

@property (nonatomic,strong) NSMutableArray *imageArray;

@end


#import "PBCollectionViewLayout.h"

@interface PBCollectionViewLayout()

@property (nonatomic,strong) NSMutableArray *hs;
@property (nonatomic,assign) NSInteger totalNum;
@property (nonatomic,strong) NSMutableArray *layoutAttributes;

@property (nonatomic,assign) CGFloat gap;
@property (nonatomic,assign) CGFloat width;

@end

@implementation PBCollectionViewLayout

- (instancetype)init
{
self = [super init];
if (self) {
_gap = 5;
_imageArray = [NSMutableArray array];
}
return self;
}

- (void)prepareLayout {
[super prepareLayout];
_hs = [NSMutableArray array];

for (int i = 0; i < _queueNum; i++) {
[_hs addObject:[NSString stringWithFormat:@"%d",5]];
}

// collectionView的item的个数
_totalNum = [self.collectionView numberOfItemsInSection:0];
_layoutAttributes = [NSMutableArray array];

NSIndexPath *indexPath = [[NSIndexPath alloc] init];

for (int index = 0; index < _totalNum; index++) {
indexPath = [NSIndexPath indexPathForRow:index inSection:0];
UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
[_layoutAttributes addObject:attributes];
}
}

// 每个cell的布局属性
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
_width = (self.collectionView.bounds.size.width - _gap*(_queueNum - 1))/_queueNum;
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
UIImage *im = _imageArray[indexPath.row];
attributes.size = CGSizeMake(_width, im.size.height * _width / im.size.width);
int nub = 0;
float h = 0;
NSArray *dataA = [self minH:_hs];
nub = [(NSNumber *)dataA[0] intValue];
h = [(NSNumber *)dataA[1] floatValue];

attributes.center = CGPointMake((nub+0.5)*(_gap+_width), h+(_width/attributes.size.width*attributes.size.height+_gap)/2);
_hs[nub] = [NSNumber numberWithFloat: (h+_width/attributes.size.width*attributes.size.height+_gap)];
return attributes;
}

// 返回collection 的contentsize
- (CGSize)collectionViewContentSize {
return CGSizeMake(self.collectionView.bounds.size.width, [self maxH:_hs]);
}

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
return _layoutAttributes.copy;
}

// 获取每个item的minY
- (NSArray *)minH:(NSArray *)hss {
int num = 0;
float min = [(NSNumber *)hss[0] floatValue];
for (int i = 1; i < hss.count ; i ++) {
if (min > [(NSNumber *)hss[i] floatValue]) {
min = [(NSNumber *)hss[i] floatValue];
num = i;
}
}
return @[[NSNumber numberWithInt:num],[NSNumber numberWithFloat:min]];
}

// 获取contentView的高度
- (CGFloat)maxH:(NSArray *)hhs {
CGFloat max = [(NSNumber *)hhs[0] floatValue];
for (int i = 1; i < hhs.count; i ++) {
if (max < [(NSNumber *)hhs[0] floatValue]) {
max = [(NSNumber *)hhs[0] floatValue];
}
}
return max;
}

@end

二 使用PBCollectionViewLayout,展示collectionview


#import "ViewController.h"
#import "PBCollectionViewLayout.h"

@interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>

@property (nonatomic,strong) UICollectionView *collectionView;

@property (nonnull,strong) NSMutableArray *images;

@end

static NSString *CellID = @"collectionViewCell";

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

self.view.backgroundColor = [UIColor yellowColor];



_images = [NSMutableArray array];
for (int i = 0; i < 18; i ++) {
NSLog(@"%@",[NSString stringWithFormat:@"%.2d.png",i]);
UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:@"%.2d.png",i]];
[_images addObject:img];

}
PBCollectionViewLayout *layout = [[PBCollectionViewLayout alloc] init];
layout.queueNum = 3;
layout.imageArray = [NSMutableArray arrayWithArray:_images.copy];

_collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:CellID];
_collectionView.backgroundColor = [UIColor whiteColor];
_collectionView.delegate = self;
_collectionView.dataSource = self;
[self.view addSubview:_collectionView];
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return _images.count;
}


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellID forIndexPath:indexPath];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:cell.bounds];
imageView.image = _images[indexPath.row];
UIView *bView = [[UIView alloc] initWithFrame:cell.bounds];
[bView addSubview:imageView];
cell.backgroundView = bView;
return cell;

}

@end


Swift:

import UIKit

class PBCollectionViewLayout: UICollectionViewLayout {

var setSize:()->(Array<UIImage>) = {_ in return []}
var queueNum:Int = 3 // 列数
// override init() {
// super.init()
// }
//
// required init?(coder aDecoder: NSCoder) {
// fatalError("init(coder:) has not been implemented")
// }
private var hs:Array<CGFloat>!
private var totalNum:Int!
private var layoutAttributes:Array<UICollectionViewLayoutAttributes>!
override func prepareLayout() {
super.prepareLayout()
hs = []
//
for _ in 0..<queueNum{
hs.append(5)
}
// section0 共几个
totalNum = collectionView?.numberOfItemsInSection(0)
layoutAttributes = []
var indexpath:NSIndexPath
// 生成全部的每个item的布局属性
for index in 0..<totalNum{
indexpath = NSIndexPath(forRow: index, inSection: 0)
let attributes = layoutAttributesForItemAtIndexPath(indexpath)
layoutAttributes.append(attributes!)
}
}
private let gap:CGFloat = 5
private var width:CGFloat!
// 生成每个item的布局属性
override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
// 每个item的宽度
width = (collectionView!.bounds.size.width-gap*(CGFloat(queueNum)-1))/CGFloat(queueNum)
let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
let sizes = setSize()
attributes.size = CGSizeMake(width, sizes[indexPath.row].size.height*width/sizes[indexPath.row].size.width)
var nub:CGFloat = 0
var h:CGFloat = 0
// 循环计算collectionView的高度
(nub,h) = minH(hs)
attributes.center = CGPointMake((nub+0.5)*(gap+width), h+(width/attributes.size.width*attributes.size.height+gap)/2)
hs[Int(nub)] = h+width/attributes.size.width*attributes.size.height+gap
return attributes
}

override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return layoutAttributes
}

override func collectionViewContentSize() -> CGSize {
return CGSizeMake((collectionView?.bounds.width)!, maxH(hs))
}

private func minH(hhs:Array<CGFloat>)->(CGFloat,CGFloat){
var num = 0
var min = hhs[0]
for i in 1..<hhs.count{
// 计算最小值
if min>hhs[i] {
min = hhs[i]
num = i
}
}
return (CGFloat(num),min)
}
private func maxH(hhs:Array<CGFloat>)->CGFloat{
var max = hhs[0]
for i in 1..<hhs.count{
// 计算最大值
if max<hhs[i] {
max = hhs[i]
}
}
return max
}
}


自定义view

import UIKit

class PBButton: UIButton {

var pbImage:UIImage!{
didSet{
pbImageView.image = pbImage
}
}
private var pbImageView:UIImageView!
override init(frame: CGRect) {
super.init(frame: frame)
pbImageView = UIImageView.init(frame:bounds)
addSubview(pbImageView)
}

override func layoutSubviews() {
super.layoutSubviews()
pbImageView.frame = bounds
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

}


1 0