一 继承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")
}
}