关注支持下,马上码好上传,先看看别的吧
一般性布局
//
// DDYCollectionVC.m
// DDYProject
//
// Created by Rain Dou on 15/5/18.
// Copyright © 2015年 634778311 All rights reserved.
//
/**
* 和UITabelView不同,UICollectionView必须自定义Cell
*
* UICollectionViewFlowLayout 布局
*
* 遵循代理:UICollectionViewDataSource,
* UICollectionViewDelegate,
* UICollectionViewDelegateFlowLayout
* 设置代理
*/
#import "DDYCollectionVC.h"
#import "DDYReusableView.h"
#import "DDYCollectionViewCell.h"
static NSString *cellID = @"cellID";
static NSString *headID = @"headID";
@interface DDYCollectionVC ()<UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, DDYReusableViewDelegate>
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) NSMutableArray *dataArray;
@end
@implementation DDYCollectionVC
- (NSMutableArray *)dataArray
{
if (!_dataArray) {
_dataArray = [NSMutableArray array];
}
return _dataArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
[self layoutCollectionView];
[self loadData];
}
- (void)layoutCollectionView
{
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
[flowLayout setHeaderReferenceSize:CGSizeMake(DDYSCREENW, 100)];
flowLayout.sectionInset = UIEdgeInsetsMake(0, 10, 0, 10);
flowLayout.minimumInteritemSpacing = 0;
_collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:flowLayout];
[self.view addSubview:_collectionView];
_collectionView.delegate = self;
_collectionView.dataSource = self;
_collectionView.backgroundColor = DDYColor(240, 240, 240, 0.9);
// 注册cell和ReusableView(相当于头部)
[_collectionView registerClass:[DDYCollectionViewCell class] forCellWithReuseIdentifier:cellID];
[self.collectionView registerClass:[DDYReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headID];
}
#pragma mark - UICollectionViewDataSource Delegate
#pragma mark 组数
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
#pragma mark 每组item数
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 30;
}
#pragma mark cell的内容
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
DDYCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
UIColor *color = DDYRandomColor;
[cell initWithImg:[UIImage imageWithColor:color size:CGSizeMake(50, 50)] title:[NSString stringWithFormat:@"测试%ld",indexPath.row]];
return cell;
}
#pragma mark 头部视图
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
DDYReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:
UICollectionElementKindSectionHeader withReuseIdentifier:headID forIndexPath:indexPath];
headerView.delegate = self;
if (indexPath.row%3 == 0) {
[headerView loadDataWithDict:@{@"title":@"test"} type:DDYHeaderTypeBlue];
}
if (indexPath.row%3 == 1) {
[headerView loadDataWithDict:@{@"title":@"test"} type:DDYHeaderTypeRed];
}
if (indexPath.row%3 == 2) {
[headerView loadDataWithDict:@{@"title":@"test"} type:DDYHeaderTypeGreen];
}
return headerView;
}
#pragma mark - UICollectionViewDelegateFlowLayout
#pragma mark 定义每个UICollectionView 的大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(DDYSCREENW/4-5, 135);
}
#pragma mark 定义每个UICollectionView 的间距
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0, 5, 0, 5);
}
#pragma mark 定义每个UICollectionView 横向的间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 1.0f;
}
#pragma mark 定义每个UICollectionView 纵向的间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 5.0f;
}
#pragma mark - UICollectionViewDelegate
#pragma mark UICollectionView被选中时调用的方法
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"选择%ld",indexPath.row);
}
#pragma mark 返回这个UICollectionView是否可以被选择
-(BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
#pragma mark - DDYReusableViewDelegate
#pragma mark 点击的是哪个类型
- (void)clickBtnType:(DDYHeaderType)type
{
DDYLog(@"点击");
}
- (void)loadData
{
for (int i = 0; i < 30; i++) {
[self.dataArray addObject:[NSString stringWithFormat:@"%d",i]];
}
[self.collectionView reloadData];
}
- (void)longpress:(UILongPressGestureRecognizer*)ges {
if(ges.state == UIGestureRecognizerStateBegan){
//获取目标cell
NSInteger row = ges.view.tag;
//删除操作
if(self.dataArray.count>1) {
id objc = [self.dataArray objectAtIndex:ges.view.tag];
[self.dataArray removeObject:objc];
[self.collectionView reloadData];
}else{
[self.collectionView reloadData];
}
}
}
@end
瀑布流
WaterfallCollectionLayout.h
#import <UIKit/UIKit.h>
typedef CGFloat(^itemHeightBlock)(NSIndexPath* index);
@interface WaterfallColectionLayout : UICollectionViewLayout
@property(nonatomic, strong) itemHeightBlock heightBlock ;
- (instancetype)initWithItemsHeightBlock:(itemHeightBlock)block;
@end
WaterfallCollectionLayout.m
#import "WaterfallColectionLayout.h"
#define colMargin 5
#define colCount 4
#define rolMargin 5
@interface WaterfallColectionLayout ()
//数组存放每列的总高度
@property(nonatomic,strong)NSMutableArray* colsHeight;
//单元格宽度
@property(nonatomic,assign)CGFloat colWidth;
@end
@implementation WaterfallColectionLayout
-(instancetype)initWithItemsHeightBlock:(itemHeightBlock)block{
if ([super init]) {
self.heightBlock = block;
}
return self;
}
-(void)prepareLayout{
[super prepareLayout];
self.colWidth =( self.collectionView.frame.size.width - (colCount+1)*colMargin )/colCount;
self.colsHeight = nil;
}
-(CGSize)collectionViewContentSize{
NSNumber * longest = self.colsHeight[0];
for (NSInteger i =0;i<self.colsHeight.count;i++) {
NSNumber* rolHeight = self.colsHeight[i];
if(longest.floatValue<rolHeight.floatValue){
longest = rolHeight;
}
}
return CGSizeMake(self.collectionView.frame.size.width, longest.floatValue);
}
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewLayoutAttributes* attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
NSNumber * shortest = self.colsHeight[0];
NSInteger shortCol = 0;
for (NSInteger i =0;i<self.colsHeight.count;i++) {
NSNumber* rolHeight = self.colsHeight[i];
if(shortest.floatValue>rolHeight.floatValue){
shortest = rolHeight;
shortCol=i;
}
}
CGFloat x = (shortCol+1)*colMargin+ shortCol * self.colWidth;
CGFloat y = shortest.floatValue+colMargin;
//获取cell高度
CGFloat height=0;
NSAssert(self.heightBlock!=nil, @"未实现计算高度的block ");
if(self.heightBlock){
height = self.heightBlock(indexPath);
}
attr.frame= CGRectMake(x, y, self.colWidth, height);
self.colsHeight[shortCol]=@(shortest.floatValue+colMargin+height);
return attr;
}
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
NSMutableArray* array = [NSMutableArray array];
NSInteger items = [self.collectionView numberOfItemsInSection:0];
for (int i = 0; i<items;i++) {
UICollectionViewLayoutAttributes* attr = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
[array addObject:attr];
}
return array;
}
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
return YES;
}
-(NSMutableArray *)colsHeight{
if(!_colsHeight){
NSMutableArray * array = [NSMutableArray array];
for(int i =0;i<colCount;i++){
//这里可以设置初始高度
[array addObject:@(0)];
}
_colsHeight = [array mutableCopy];
}
return _colsHeight;
}
@end
应用
#import "ViewController.h"
#import "WaterfallColectionLayout.h"
@interface CollectionViewCell()
@end
@implementation CollectionViewCell
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.contentView.backgroundColor=[self randomColor];
}
return self;
}
-(UIColor *) randomColor
{
CGFloat hue = ( arc4random() % 256 / 256.0 ); //0.0 to 1.0
CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0,away from white
CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; //0.5 to 1.0,away from black
return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1];
}
@end
@interface ViewController ()<UICollectionViewDataSource,UICollectionViewDelegate>
@property(nonatomic,strong)UICollectionView* collectionView;
@property(nonatomic,strong)UICollectionViewLayout* layout;
@property(nonatomic,strong)NSArray* heightArr;
@end
@implementation ViewController
static NSString * identifer = @"CollectionCell";
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// self.edgesForExtendedLayout=UIRectEdgeNone;
[self.view addSubview:self.collectionView];
}
#pragma mark collectionViewDelegate-collectionViewDatesource
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
CollectionViewCell* cell = (CollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:identifer forIndexPath:indexPath];
return cell;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return self.heightArr.count;
}
#pragma mark getter-setter
-(UICollectionView *)collectionView{
if(!_collectionView){
_collectionView = [[UICollectionView alloc]initWithFrame:self.view.frame collectionViewLayout:self.layout];
_collectionView.backgroundColor = [UIColor whiteColor];
_collectionView.delegate=self;
_collectionView.dataSource=self;
[_collectionView registerClass:[CollectionViewCell class] forCellWithReuseIdentifier:identifer];
}
return _collectionView;
}
-(UICollectionViewLayout *)layout{
if(!_layout){
_layout = [[WaterfallColectionLayout alloc]initWithItemsHeightBlock:^CGFloat(NSIndexPath *index) {
return [self.heightArr[index.item] floatValue];
}];
}
return _layout;
}
-(NSArray *)heightArr{
if(!_heightArr){
//随机生成高度
NSMutableArray *arr = [NSMutableArray array];
for (int i = 0; i<100; i++) {
[arr addObject:@(arc4random()%50+80)];
}
_heightArr = [arr copy];
}
return _heightArr;
}
@end
CoverFlow
圆弧布局
球形布局
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
MyLayout * layout = [[MyLayout alloc]init];
UICollectionView * collect = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, 320, 400) collectionViewLayout:layout];
collect.delegate=self;
collect.dataSource=self;
//这里设置的偏移量是为了无缝进行循环的滚动,具体在上一篇博客中有解释
collect.contentOffset = CGPointMake(320, 400);
[collect registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellid"];
[self.view addSubview:collect];
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
//我们返回30的标签
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 30;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellid" forIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 30, 30)];
label.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row];
[cell.contentView addSubview:label];
return cell;
}
//这里对滑动的contentOffset进行监控,实现循环滚动
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.y<200)
{
scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, scrollView.contentOffset.y+10*400);
}
else if(scrollView.contentOffset.y>11*400)
{
scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, scrollView.contentOffset.y-10*400);
}
if (scrollView.contentOffset.x<160)
{
scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x+10*320,scrollView.contentOffset.y);
}
else if(scrollView.contentOffset.x>11*320)
{
scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x-10*320,scrollView.contentOffset.y);
}
}
layout
-(void)prepareLayout{
[super prepareLayout];
}
// 返回的滚动范围增加了对x轴的兼容
- (CGSize)collectionViewContentSize
{
return CGSizeMake( self.collectionView.frame.size.width*([self.collectionView numberOfItemsInSection:0]+2), self.collectionView.frame.size.height*([self.collectionView numberOfItemsInSection:0]+2));
}
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewLayoutAttributes * atti = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//获取item的个数
int itemCounts = (int)[self.collectionView numberOfItemsInSection:0];
atti.center = CGPointMake(self.collectionView.frame.size.width/2+self.collectionView.contentOffset.x, self.collectionView.frame.size.height/2+self.collectionView.contentOffset.y);
atti.size = CGSizeMake(30, 30);
CATransform3D trans3D = CATransform3DIdentity;
trans3D.m34 = -1/900.0;
CGFloat radius = 15/tanf(M_PI*2/itemCounts/2);
//根据偏移量 改变角度
//添加了一个x的偏移量
float offsety = self.collectionView.contentOffset.y;
float offsetx = self.collectionView.contentOffset.x;
//分别计算偏移的角度
float angleOffsety = offsety/self.collectionView.frame.size.height;
float angleOffsetx = offsetx/self.collectionView.frame.size.width;
CGFloat angle1 = (float)(indexPath.row+angleOffsety-1)/itemCounts*M_PI*2;
//x,y的默认方向相反
CGFloat angle2 = (float)(indexPath.row-angleOffsetx-1)/itemCounts*M_PI*2;
//这里我们进行四个方向的排列
if (indexPath.row%4==1) {
trans3D = CATransform3DRotate(trans3D, angle1, 1.0,0, 0);
}else if(indexPath.row%4==2){
trans3D = CATransform3DRotate(trans3D, angle2, 0, 1, 0);
}else if(indexPath.row%4==3){
trans3D = CATransform3DRotate(trans3D, angle1, 0.5,0.5, 0);
}else{
trans3D = CATransform3DRotate(trans3D, angle1, 0.5,-0.5,0);
}
trans3D = CATransform3DTranslate(trans3D, 0, 0, radius);
atti.transform3D = trans3D;
return atti;
}
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
NSMutableArray * attributes = [[NSMutableArray alloc]init];
//遍历设置每个item的布局属性
for (int i=0; i<[self.collectionView numberOfItemsInSection:0]; i++) {
[attributes addObject:[self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]];
}
return attributes;
}
附: