您的位置:首页 > 其它

瀑布流接口的设计以及应用(一)

2015-07-15 22:47 260 查看
//

// MyWaterFlowView.h

// 瀑布流

//

// Created by Jose on 15-7-11.

// Copyright (c) 2015年 Jose. All rights reserved.

//

#import <UIKit/UIKit.h>

//枚举方法

typedef enum {

MyWaterFlowViewMarginTypeTop,

MyWaterFlowViewMarginTypeBottom,

MyWaterFlowViewMarginTypeLeft,

MyWaterFlowViewMarginTypeRight,

//每一列

MyWaterFlowViewMarginTypeColumn,

//没一行

MyWaterFlowViewMarginTypeRow

}MyWaterFlowViewMarginType;

@class MyWaterFlowView,MyWaterFlowViewCell;

/**

* 数据源方法

*/

@protocol MyWaterFlowViewDataSource <NSObject>

@required

// 一共有多少个数据

// NSUInteger是无符号类型,即没有负数

-(NSUInteger)NumberOfCellInWaterFlowView:(MyWaterFlowView *)mywaterflowview;

// 返回index位置对应的cell

-(MyWaterFlowViewCell *)WaterFlowViewCell:(MyWaterFlowView *)mywaterflowview CellAtIndex:(NSUInteger)index;

@optional

// 返回一共有多少列

-(NSUInteger)NumberOfColumsInWaterFlowView:(MyWaterFlowView *)mywateflowview;

@end

/**

* 代理方法

*/

@protocol MyWaterFlowViewDelegate <UIScrollViewDelegate>

@optional

// 返回第index位置cell的高度

-(CGFloat)MyWaterFlowView:(MyWaterFlowView *)mywaterflowview HeightAtIndex:(NSUInteger)index;

// 选中在index位置的cell

-(void)MyWaterFlowView:(MyWaterFlowView *)mywaterflowview DidSelectAtIndex:(NSUInteger)index;

//返回间隙

-(CGFloat)MyWaterFlowView:(MyWaterFlowView *)mywaterflowview MarginType:(MyWaterFlowViewMarginType)type;

@end

@interface MyWaterFlowView : UIScrollView

/** 数据源*/

@property(nonatomic,weak)id<MyWaterFlowViewDataSource>MyDataSource;

/** 代理方法*/

@property(nonatomic,weak)id<MyWaterFlowViewDelegate>MyDelegate;

/** 刷新数据(只要调用这个方法,会重新向数据源和代理发送请求)*/

-(void)ReloadData;

/** 根据标识去缓存池查可重复利用的cell*/

- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier;

/** cell的宽度*/

-(CGFloat)cellWidth;

@end

*************************************************************************************************************************************

************************************************************************************************************************************

*************************************************************************************************************************************

//

// MyWaterFlowView.m

// 瀑布流

//

// Created by Jose on 15-7-11.

// Copyright (c) 2015年 Jose. All rights reserved.

//

#import "MyWaterFlowView.h"

#import "MyWaterFlowViewCell.h"

#define CellHeight 70

#define CellColums 3

#define CellMargin 8

@interface MyWaterFlowView()

/** 存放cell的frame的数组*/

@property(nonatomic,strong)NSMutableArray *CellFrames;

/** 存放正在展示的cell*/

@property(nonatomic,strong)NSMutableDictionary *displayingCells;

/** 缓存池用set存放离开屏幕的cell*/

@property(nonatomic,strong)NSMutableSet *reusableCells;

@end

@implementation MyWaterFlowView

#pragma mark - 初始化

-(NSMutableArray *)CellFrames{

if (_CellFrames==nil) {

self.CellFrames=[NSMutableArray array];

}

return _CellFrames;

}

-(NSMutableDictionary *)displayingCells{

if (_displayingCells==nil) {

self.displayingCells=[NSMutableDictionary dictionary];

}

return _displayingCells;

}

-(NSMutableSet *)reusableCells{

if (_reusableCells==nil) {

self.reusableCells=[NSMutableSet set];

}

return _reusableCells;

}

-(id)initWithFrame:(CGRect)frame{

self=[super initWithFrame:frame];

if (self) {

}

return self;

}

//对于内存控制很重要

-(void)willMoveToSuperview:(UIView *)newSuperview{

[self ReloadData];

}

/**

* 公共接口

*/

-(void)ReloadData{

//移除正在显示的cell

[self.displayingCells.allValues makeObjectsPerformSelector:@selector(removeFromSuperview)];

//清空之前的所有数据

[self.displayingCells removeAllObjects];

[self.CellFrames removeAllObjects];

[self.reusableCells removeAllObjects];

//获取cell的总数

int numberofcells=[self.MyDataSource NumberOfCellInWaterFlowView:self];

//获取总列数

int numberofcolums=[self NumberOfColumns];

//获取间距

CGFloat top=[self MarginForType:MyWaterFlowViewMarginTypeTop];

CGFloat bottom=[self MarginForType:MyWaterFlowViewMarginTypeBottom];

CGFloat left=[self MarginForType:MyWaterFlowViewMarginTypeLeft];

//CGFloat right=[self MarginForType:MyWaterFlowViewMarginTypeRight];

CGFloat column=[self MarginForType:MyWaterFlowViewMarginTypeColumn];

CGFloat row=[self MarginForType:MyWaterFlowViewMarginTypeRow];

//4.获取宽度

//CGFloat cellwidth=(self.width-left-right-(numberofcolums-1)*column)/numberofcolums;

CGFloat cellwidth=[self cellWidth];

//c语言数组用来存放每一列最大的y值

CGFloat MaxYOfColumns[numberofcolums];

for (int i=0; i<numberofcolums; i++) {

MaxYOfColumns[i]=0.0;

}

//计算所有cell的frame

for (int i=0; i<numberofcells;i++) {

//cell所处最短的那列

NSUInteger CellColumn=0;

//cell所处最短那列的最大y值

CGFloat MaxYOfCellColumn=MaxYOfColumns[CellColumn];

//求出最短的那一列

for (int j=1; j<numberofcolums; j++) {

if (MaxYOfColumns[j]<MaxYOfCellColumn) {

CellColumn=j;

MaxYOfCellColumn=MaxYOfColumns[j];

}

}

//询问代理i位置的高度

CGFloat cellheight=[self HeightAtIndex:i];

//cell的位置

CGFloat cellx=left+CellColumn*(cellwidth+column);

CGFloat celly=0;

//判断是否是首行

if (MaxYOfCellColumn==0.0) {

celly=top;

}

else{

celly=MaxYOfCellColumn+row;

}

//添加到frame数组中

CGRect cellframe=CGRectMake(cellx, celly, cellwidth, cellheight);

[self.CellFrames addObject:[NSValue valueWithCGRect:cellframe]];

//更新最短那一列的y值

MaxYOfColumns[CellColumn]=CGRectGetMaxY(cellframe);

//显示cell

/***

MyWaterFlowViewCell *cell=[self.MyDataSource WaterFlowViewCell:self CellAtIndex:i];

cell.frame=cellframe;

[self addSubview:cell];

**/

}

//设置contentsize

CGFloat contentheight=MaxYOfColumns[0];

for (int j=1; j<numberofcolums; j++) {

if (MaxYOfColumns[j]>contentheight) {

contentheight=MaxYOfColumns[j];

}

}

contentheight+=bottom;

self.contentSize=CGSizeMake(0,contentheight);

}

-(void)layoutSubviews{

[super layoutSubviews];

//向数据源索要对应位置的cell

NSUInteger numberOfCells=self.CellFrames.count;

for (int i=0; i<numberOfCells; i++) {

//取出i对应位置的frame

CGRect cellframe=[self.CellFrames[i]CGRectValue];

//优先从字典中取出i位置的cell

MyWaterFlowViewCell *cell=self.displayingCells[@(i)];

if ([self isInScreen:cellframe]) {

if (cell==nil) {

cell=[self.MyDataSource WaterFlowViewCell:self CellAtIndex:i];

cell.frame=cellframe;

[self addSubview:cell];

//存放到字典中

self.displayingCells[@(i)]=cell;

}

}

else{

if (cell) {

//从scrollview中移除cell

[cell removeFromSuperview];

//从字典中移除cell

[self.displayingCells removeObjectForKey:@(i)];

//将移除的cell存放到缓存池中

[self.reusableCells addObject:cell];

}

}

}

}

//返回cell的宽度

-(CGFloat)cellWidth{

//1.获取总列数

int numberofcolums=[self NumberOfColumns];

CGFloat left=[self MarginForType:MyWaterFlowViewMarginTypeLeft];

CGFloat right=[self MarginForType:MyWaterFlowViewMarginTypeRight];

CGFloat column=[self MarginForType:MyWaterFlowViewMarginTypeColumn];

return (self.bounds.size.width-left-right-(numberofcolums-1)*column)/numberofcolums;

}

//从缓存池中取出出可以重复利用的cell

-(id)dequeueReusableCellWithIdentifier:(NSString *)identifier{

__block MyWaterFlowViewCell *reusableCell=nil;

[self.reusableCells enumerateObjectsUsingBlock:^(MyWaterFlowViewCell *cell,BOOL *stop){

if ([cell.identifier isEqualToString:identifier]) {

reusableCell=cell;

*stop=YES;

}

}];

if (reusableCell) {

// 从缓存池移除

[self.reusableCells removeObject:reusableCell];

}

return reusableCell;

}

/**

* 私有方法

*/

//判断一个frame有没有显示在屏幕上

-(BOOL)isInScreen:(CGRect)frame{

return (CGRectGetMaxY(frame)>self.contentOffset.y)&&(CGRectGetMinY(frame)<self.contentOffset.y+self.bounds.size.height);

}

//获取index位置对应cell的高度

-(CGFloat)HeightAtIndex:(NSUInteger)index{

if ([self.MyDelegate respondsToSelector:@selector(MyWaterFlowView:HeightAtIndex:)]) {

return [self.MyDelegate MyWaterFlowView:self HeightAtIndex:index];

}

else{

return CellHeight;

}

}

//事件处理

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

if (![self.MyDelegate respondsToSelector:@selector(MyWaterFlowView:DidSelectAtIndex:)])return;

UITouch *touch=[touches anyObject];

CGPoint point=[touch locationInView:self];

__block NSNumber *selectIndex=nil;

[self.displayingCells enumerateKeysAndObjectsUsingBlock:^(id key,MyWaterFlowViewCell *cell,BOOL *stop){

if (CGRectContainsPoint(cell.frame, point)) {

selectIndex=key;

*stop=YES;

}

}];

if (selectIndex) {

[self.MyDelegate MyWaterFlowView:self DidSelectAtIndex:selectIndex.unsignedIntegerValue];

}

}

//获取列数

-(NSUInteger)NumberOfColumns{

if ([self.MyDataSource respondsToSelector:@selector(NumberOfColumsInWaterFlowView:)]) {

return [self.MyDataSource NumberOfColumsInWaterFlowView:self];

}

else{

return CellColums;

}

}

//获取间距

-(CGFloat)MarginForType:(MyWaterFlowViewMarginType)type{

if ([self.MyDelegate respondsToSelector:@selector(MyWaterFlowView:MarginType:)]) {

return [self.MyDelegate MyWaterFlowView:self MarginType:type];

}

else{

return CellMargin;

}

}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: