一、自定义Flowlayout
UICollectionViewFlowLayout类是最重要的,整个横线就是从这个类里控制的,这里的横线是个横线的 图片加载到UICollectionview的decoration View上的decoration View
-(void)prepareLayout
实例化视图或更新视图或者查询视图信息之前,被自动调用,设定一些必要的layout的结构和初始需要参数等。
- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
1、返回在rect中的所有的元素的布局属性,是包含UICollectionViewLayoutAttributes的array.
2、UICollectionViewLayoutAttributes可以是cell,追加视图或装饰视图的信息,通过不同的UICollectionViewLayoutAttributes初始化方法可以得到不同类型的UICollectionViewLayoutAttribures:
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
返回对应于indexPath的位置的cell的布局属性
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath
返回对应于indexPath的位置的装饰视图的布局属性,没有装饰视图可以不重载此方法
代码:
(重点是自定义的FlowLayout)
GridLayout.h
<pre name="code" class="objc">//gridView视图对应的UICollectionViewLayout,向UICollectionView提供布局信息,
//包括cell的布局信息,也包括Supplementary Views(追加视图,类似与headerView或者FooterView)和Decoration Views(装饰视图,用作背景展示)的布局信息。
@interface GridLayout : UICollectionViewFlowLayout
@property (nonatomic, strong) NSDictionary *shelfRects;
- (id)initForIpad;
- (id)initForIphone;
@end
GridLayout.m
#import "GridLayout.h"
#import "ShelfView.h"
#import "GridLayoutAttributes.h"
@implementation GridLayout
/**
为Ipad初始化
@author maguang
@param parameter
@return result
*/
- (id)initForIpad
{
if (self = [super init]) {
self.scrollDirection = UICollectionViewScrollDirectionVertical;//垂直滚动
self.itemSize = (CGSize){150,200};//cell的大小
self.sectionInset = UIEdgeInsetsMake(30, 30, 30, 30);//定义每个cell的边缘,top,left,bottom,right
//根据程序运行环境(Ipad或者Iphone)定义headerView的大小
// self.headerReferenceSize = [[UIDevice currentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPad?(CGSize){50,50}:(CGSize){43,43};
// //定义footView的大小
// self.footerReferenceSize = (CGSize){44,44};
//横排cell之间最小间隔(对应左右)
self.minimumInteritemSpacing = 36;
//竖排cell之间最小间隔(对应上下)
self.minimumLineSpacing = 36;
//注册DecorationView
[self registerClass:[ShelfView class] forDecorationViewOfKind:[ShelfView kind]];
}
return self;
}
/**
为iphone初始化
@author maguang
@param parameter
@return result
*/
- (id)initForIphone
{
if (self = [super init]) {
self.scrollDirection = UICollectionViewScrollDirectionVertical;//垂直滚动
self.itemSize = (CGSize){80,120};//cell的大小
self.sectionInset = UIEdgeInsetsMake(20, 20, 20, 20);//定义每个cell的边缘,top,left,bottom,right
//根据程序运行环境(Ipad或者Iphone)定义headerView的大小
// self.headerReferenceSize = [[UIDevice currentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPad?(CGSize){50,50}:(CGSize){43,43};
// //定义footView的大小
// self.footerReferenceSize = (CGSize){44,44};
//横排cell之间最小间隔(对应左右)
self.minimumInteritemSpacing = 20;
//竖排cell之间最小间隔(对应上下)
self.minimumLineSpacing = 20;
//注册DecorationView
[self registerClass:[ShelfView class] forDecorationViewOfKind:[ShelfView kind]];
}
return self;
}
/**
重写父类方法,提供一个通用类以来初始化MyLayoutAttributes的实例
@param parameter
@return result
*/
+ (Class)layoutAttributesClass
{
return [GridLayoutAttributes class];
}
/**
实例化视图或更新视图或者查询视图信息之前,被自动调用,设定一些必要的layout的结构和初始需要参数等。
@param parameter
@return result
*/
- (void)prepareLayout
{
[super prepareLayout];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
//calculate where shelves go in a vertiacl layout
NSInteger sectionCount = [self.collectionView numberOfSections];
CGFloat y = 0;
//有效宽度
CGFloat availableWidth = self.collectionViewContentSize.width - (self.sectionInset.left+self.sectionInset.right);
//向下取整,水平方向cell的列数
int itemAcross = floorf((availableWidth + self.minimumInteritemSpacing) / (self.itemSize.width + self.minimumInteritemSpacing));
for (int section = 0; section < sectionCount; section++) {
y += self.headerReferenceSize.height;
y += self.sectionInset.top;
//获取指定section下cell的个数
NSInteger itemCount = [self.collectionView numberOfItemsInSection:section];
//获取指定section,垂直方向cell的行数
int rows = ceilf(itemCount/(float)itemAcross);
//for循环,设置线的位置,线的坐标为(0,y+5),线的高度为2
for (int row = 0; row < rows; row++) {
y += self.itemSize.height;
dictionary[[NSIndexPath indexPathForItem:row inSection:section]] = [NSValue valueWithCGRect:CGRectMake(0, y+5, self.collectionViewContentSize.width, 4)];
if (row < rows - 1) {
y += self.minimumLineSpacing;
}
}
y += self.sectionInset.bottom;
y += self.footerReferenceSize.height;
}
}else{
//Calculate where shelves go in a horizontal layout
CGFloat y = self.sectionInset.top;
//有效高度
CGFloat availableHeight = self.collectionViewContentSize.height - (self.sectionInset.top + self.sectionInset.bottom);
//向下取整,垂直方向cell的行数
int itemsAcross = floorf((availableHeight + self.minimumInteritemSpacing) / (self.itemSize.height + self.minimumInteritemSpacing));
//
CGFloat interval = ((availableHeight - self.itemSize.height) / (itemsAcross <= 1?1:itemsAcross - 1)) - self.itemSize.height;
for (int row = 0; row < itemsAcross; row++) {
y += self.itemSize.height;
dictionary[[NSIndexPath indexPathForItem:row inSection:0]] = [NSValue valueWithCGRect:CGRectMake(0, y+5, self.collectionViewContentSize.width, 4)];
y += interval;
}
}
self.shelfRects = [NSDictionary dictionaryWithDictionary:dictionary];
}
/**
1、返回在rect中的所有的元素的布局属性,是包含UICollectionViewLayoutAttributes的array.
2、UICollectionViewLayoutAttributes可以是cell,追加视图或装饰视图的信息,通过不同的UICollectionViewLayoutAttributes初始化方法可以得到不同类型的UICollectionViewLayoutAttribures:
(1)、layoutAttributesForCellWithIndexPath:
(2)、layoutAttributesForSupplementaryViewOfKind:withIndexPaht:
(3)、layoutAttributesForDecorationViewOfKind:withIndexPath:
@param parameter
@return result
*/
- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *array = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes *attributes in array) {
attributes.zIndex = 1;
//if (attributes.representedElementCategory != UICollectionElementCategoryCell)
/*if (attributes.representedElementCategory != UICollectionElementCategorySupplementaryView || [attributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader])
attributes.alpha = 0.5;
else if (attributes.indexPath.row > 0 || attributes.indexPath.section > 0)
attributes.alpha = 0.5; // for single cell closeup*/
if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal && attributes.representedElementCategory == UICollectionElementCategorySupplementaryView) {
attributes.transform3D = CATransform3DMakeRotation(-90 * M_PI / 180, 0, 0, 1);
attributes.size = CGSizeMake(attributes.size.height, attributes.size.width);
}
// if (attributes.representedElementCategory == UICollectionElementCategorySupplementaryView && [attributes isKindOfClass:[MyLayoutAttributes class]]) {
// MyLayoutAttributes *myAttributes = (MyLayoutAttributes*)attributes;
myAttributes.headerTextAlignment = NSTextAlignmentLeft;
// }
}
//Add our decoration Views(shelves)
NSMutableArray *aArray = [array mutableCopy];
[self.shelfRects enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if (CGRectIntersectsRect([obj CGRectValue], rect)) {
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:[ShelfView kind] withIndexPath:key];
attributes.frame = [obj CGRectValue];
NSLog(@"第一个x= %f,y = %f,with = %f,height = %f",attributes.frame.origin.x,attributes.frame.origin.y,attributes.frame.size.width,attributes.frame.size.height);
attributes.zIndex = 0;
// attributes.alpha = 0.5;
[aArray addObject:attributes];
}
}];
array = [NSArray arrayWithArray:aArray];
return array;
}
/**
返回对应于indexPath的位置的cell的布局属性
@param indexPath - cell的位置
@return result
*/
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForItemAtIndexPath:indexPath];
attributes.zIndex = 1;
return attributes;
}
/**
返回对应于indexPath的位置的装饰视图的布局属性,没有装饰视图可以不重载此方法
@param parameter
@return result
*/
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath
{
id shelfRect = self.shelfRects[indexPath];
if (!shelfRect) {
return nil;
}
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:[ShelfView kind] withIndexPath:indexPath];
attributes.frame = [shelfRect CGRectValue];
NSLog(@"第二个x= %f,y = %f,with = %f,height = %f",attributes.frame.origin.x,attributes.frame.origin.y,attributes.frame.size.width,attributes.frame.size.height);
attributes.zIndex = 0;//层次关系,O层
return attributes;
}
/**
返回对应于indexPath的位置的追加视图的布局属性,如果没有追加视图可不重载
@param parameter
@return result
*/
//- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
//{
// return nil;
//}
@end
ShelfView.h
#import <UIKit/UIKit.h>
@interface ShelfView : UICollectionReusableView
+ (NSString *)kind;
@end
ShelfView.m
#import "ShelfView.h"
#import <QuartzCore/QuartzCore.h>
const NSString *kShelfViewKind = @"ShelfView";
@implementation ShelfView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"bookGridShelf.png"]]];
// self.layer.shadowOpacity = 0.5;
// self.layer.shadowOffset = CGSizeMake(0,5);
}
return self;
}
- (void)layoutSubviews
{
// CGRect shadowBounds = CGRectMake(0, -5, self.bounds.size.width, self.bounds.size.height + 5);
// self.layer.shadowPath = [UIBezierPath bezierPathWithRect:shadowBounds].CGPath;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
+ (NSString *)kind
{
return (NSString *)kShelfViewKind;
}
@end
GridLayoutAttributes.h
#import <UIKit/UIKit.h>
@interface GridLayoutAttributes : UICollectionViewLayoutAttributes
@end
GridLayoutAttributes.m
#import "GridLayoutAttributes.h"
@implementation GridLayoutAttributes
@end