码迷,mamicode.com
首页 > 移动开发 > 详细

iOS开发UI篇—自定义瀑布流控件(基本实现)

时间:2014-07-29 21:11:44      阅读:582      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   使用   os   strong   文件   

iOS开发UI篇—自定义瀑布流控件(基本实现)

一、基本实现

说明:在View加载的时候,刷新数据。
 
1.实现代码
YYViewController.m文件
 1 //
 2 //  YYViewController.m
 3 //  06-瀑布流
 4 //
 5 //  Created by apple on 14-7-28.
 6 //  Copyright (c) 2014年 wendingding. All rights reserved.
 7 //
 8 
 9 #import "YYViewController.h"
10 #import "YYWaterflowView.h"
11 #import "YYWaterflowViewCell.h"
12 
13 @interface YYViewController ()<YYWaterflowViewDelegate,YYWaterflowViewDataSource>
14 
15 @end
16 
17 @implementation YYViewController
18 
19 - (void)viewDidLoad
20 {
21     [super viewDidLoad];
22     YYWaterflowView *waterflow=[[YYWaterflowView alloc]init];
23     waterflow.frame=self.view.bounds;
24     waterflow.delegate=self;
25     waterflow.dadaSource=self;
26     [self.view addSubview:waterflow];
27     
28     //刷新数据
29     [waterflow reloadData];
30 }
31 
32 #pragma mark-数据源方法
33 -(NSUInteger)numberOfCellsInWaterflowView:(YYWaterflowView *)waterflowView
34 {
35     return 100;
36 }
37 -(NSUInteger)numberOfColumnsInWaterflowView:(YYWaterflowView *)waterflowView
38 {
39     return 3;
40 }
41 -(YYWaterflowViewCell *)waterflowView:(YYWaterflowView *)waterflowView cellAtIndex:(NSUInteger)index
42 {
43     YYWaterflowViewCell *cell=[[YYWaterflowViewCell alloc]init];
44     //给cell设置一个随机色
45     cell.backgroundColor=YYRandomColor;
46     return cell;
47 }
48 
49 
50 #pragma mark-代理方法
51 -(CGFloat)waterflowView:(YYWaterflowView *)waterflowView heightAtIndex:(NSUInteger)index
52 {
53     switch (index%3) {
54         case 0:return 90;
55         case 1:return 110;
56         case 2:return 80;
57         default:return 120;
58     }
59 }
60 -(CGFloat)waterflowView:(YYWaterflowView *)waterflowView marginForType:(YYWaterflowViewMarginType)type
61 {
62     switch (type) {
63         case YYWaterflowViewMarginTypeTop:
64         case YYWaterflowViewMarginTypeBottom:
65         case YYWaterflowViewMarginTypeLeft:
66         case YYWaterflowViewMarginTypeRight:
67             return 10;
68         case YYWaterflowViewMarginTypeColumn:
69         case YYWaterflowViewMarginTypeRow:
70             return 5;
71     }
72 }
73 -(void)waterflowView:(YYWaterflowView *)waterflowView didSelectAtIndex:(NSUInteger)index
74 {
75     NSLog(@"点击了%d的cell",index);
76 }
77 @end

YYWaterflowView.h文件

 1 //
 2 //  YYWaterflowView.h
 3 //  06-瀑布流
 4 //
 5 //  Created by apple on 14-7-29.
 6 //  Copyright (c) 2014年 wendingding. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 //使用瀑布流形式展示内容的控件
12 typedef enum {
13     YYWaterflowViewMarginTypeTop,
14     YYWaterflowViewMarginTypeBottom,
15     YYWaterflowViewMarginTypeLeft,
16     YYWaterflowViewMarginTypeRight,
17     YYWaterflowViewMarginTypeColumn,//每一列
18     YYWaterflowViewMarginTypeRow,//每一行
19 
20 }YYWaterflowViewMarginType;
21 
22 @class YYWaterflowViewCell,YYWaterflowView;
23 
24 /**
25  *  1.数据源方法
26  */
27 @protocol YYWaterflowViewDataSource <NSObject>
28 //要求强制实现
29 @required
30 /**
31  * (1)一共有多少个数据
32  */
33 -(NSUInteger)numberOfCellsInWaterflowView:(YYWaterflowView *)waterflowView;
34 /**
35  *  (2)返回index位置对应的cell
36  */
37 -(YYWaterflowViewCell *)waterflowView:(YYWaterflowView *)waterflowView cellAtIndex:(NSUInteger)index;
38 
39 //不要求强制实现
40 @optional
41 /**
42  *  (3)一共有多少列
43  */
44 -(NSUInteger)numberOfColumnsInWaterflowView:(YYWaterflowView *)waterflowView;
45 
46 @end
47 
48 
49 /**
50  *  2.代理方法
51  */
52 @protocol YYWaterflowViewDelegate <UIScrollViewDelegate>
53 //不要求强制实现
54 @optional
55 /**
56  *  (1)第index位置cell对应的高度
57  */
58 -(CGFloat)waterflowView:(YYWaterflowView *)waterflowView heightAtIndex:(NSUInteger)index;
59 /**
60  *  (2)选中第index位置的cell
61  */
62 -(void)waterflowView:(YYWaterflowView *)waterflowView didSelectAtIndex:(NSUInteger)index;
63 /**
64  *  (3)返回间距
65  */
66 -(CGFloat)waterflowView:(YYWaterflowView *)waterflowView marginForType:(YYWaterflowViewMarginType)type;
67 @end
68 
69 
70 /**
71  *  3.瀑布流控件
72  */
73 @interface YYWaterflowView : UIScrollView
74 /**
75  *  (1)数据源
76  */
77 @property(nonatomic,weak)id<YYWaterflowViewDataSource> dadaSource;
78 /**
79  *  (2)代理
80  */
81 @property(nonatomic,weak)id<YYWaterflowViewDelegate> delegate;
82 
83 /**
84  *  刷新数据
85  */
86 -(void)reloadData;
87 @end

瀑布流的内部实现(计算每个cell的frame)

 YYWaterflowView.m文件的代码

  1 //
  2 //  YYWaterflowView.m
  3 //  06-瀑布流
  4 //
  5 //  Created by apple on 14-7-29.
  6 //  Copyright (c) 2014年 wendingding. All rights reserved.
  7 //
  8 
  9 #import "YYWaterflowView.h"
 10 #import "YYWaterflowViewCell.h"
 11 #define YYWaterflowViewDefaultNumberOfClunms  3
 12 #define YYWaterflowViewDefaultCellH  100
 13 #define YYWaterflowViewDefaultMargin 10
 14 
 15 @interface YYWaterflowView()
 16 @property(nonatomic,strong)NSMutableArray *cellFrames;
 17 @end
 18 
 19 @implementation YYWaterflowView
 20 
 21 #pragma mark-懒加载
 22 -(NSMutableArray *)cellFrames
 23 {
 24     if (_cellFrames==nil) {
 25         _cellFrames=[NSMutableArray array];
 26     }
 27     return _cellFrames;
 28 }
 29 
 30 - (id)initWithFrame:(CGRect)frame
 31 {
 32     self = [super initWithFrame:frame];
 33     if (self) {
 34     }
 35     return self;
 36 }
 37 
 38 /**
 39  *  刷新数据
 40  *  1.计算每个cell的frame
 41  */
 42 -(void)reloadData
 43 {
 44     //cell的总数是多少
 45     int numberOfCells=[self.dadaSource numberOfCellsInWaterflowView:self];
 46     
 47     //cell的列数
 48     int numberOfColumns=[self numberOfColumns];
 49     
 50     //间距
 51     CGFloat leftM=[self marginForType:YYWaterflowViewMarginTypeLeft];
 52     CGFloat rightM=[self marginForType:YYWaterflowViewMarginTypeRight];
 53     CGFloat columnM=[self marginForType:YYWaterflowViewMarginTypeColumn];
 54     CGFloat topM=[self marginForType:YYWaterflowViewMarginTypeTop];
 55     CGFloat rowM=[self marginForType:YYWaterflowViewMarginTypeRow];
 56     CGFloat bottomM=[self marginForType:YYWaterflowViewMarginTypeBottom];
 57     
 58     //(1)cell的宽度
 59     //cell的宽度=(整个view的宽度-左边的间距-右边的间距-(列数-1)X每列之间的间距)/总列数
 60     CGFloat cellW=(self.frame.size.width-leftM-rightM-(numberOfColumns-1)*columnM)/numberOfColumns;
 61 
 62     
 63     
 64     //用一个C语言的数组来存放所有列的最大的Y值
 65     CGFloat maxYOfColumns[numberOfColumns];
 66     for (int i=0; i<numberOfColumns; i++) {
 67         //初始化数组的数值全部为0
 68         maxYOfColumns[i]=0.0;
 69     }
 70     
 71     
 72     //计算每个cell的fram
 73     for (int i=0; i<numberOfCells; i++) {
 74         
 75         //(2)cell的高度
 76         //询问代理i位置的高度
 77         CGFloat cellH=[self heightAtIndex:i];
 78         
 79         //cell处在第几列(最短的一列)
 80         NSUInteger cellAtColumn=0;
 81         
 82         //cell所处那列的最大的Y值(当前最短的那一列的最大的Y值)
 83         //默认设置最短的一列为第一列(优化性能)
 84         CGFloat maxYOfCellAtColumn=maxYOfColumns[cellAtColumn];
 85         
 86         //求出最短的那一列
 87         for (int j=0; j<numberOfColumns; j++) {
 88             if (maxYOfColumns[j]<maxYOfCellAtColumn) {
 89                 cellAtColumn=j;
 90                 maxYOfCellAtColumn=maxYOfColumns[j];
 91             }
 92         }
 93         
 94         //(3)cell的位置(X,Y)
 95         //cell的X=左边的间距+列号*(cell的宽度+每列之间的间距)
 96         CGFloat cellX=leftM+cellAtColumn*(cellW +columnM);
 97         //cell的Y,先设定为0
 98         CGFloat cellY=0;
 99         if (maxYOfCellAtColumn==0.0) {//首行
100             cellY=topM;
101         }else
102         {
103             cellY=maxYOfCellAtColumn+rowM;
104         }
105         
106         //(4)设置cell的frame并添加到数组中
107         CGRect cellFrame=CGRectMake(cellX, cellY, cellW, cellH);
108         [self.cellFrames addObject:[NSValue valueWithCGRect:cellFrame]];
109         
110         //更新最短那一列的最大的Y值
111         maxYOfColumns[cellAtColumn]=CGRectGetMaxY(cellFrame);
112         
113         //显示cell
114         YYWaterflowViewCell *cell=[self.dadaSource waterflowView:self cellAtIndex:i];
115         cell.frame=cellFrame;
116         [self addSubview:cell];
117     }
118     
119     //设置contentSize
120     CGFloat contentH=maxYOfColumns[0];
121     for (int i=1; i<numberOfColumns; i++) {
122         if (maxYOfColumns[i]>contentH) {
123             contentH=maxYOfColumns[i];
124         }
125     }
126     contentH += bottomM;
127     self.contentSize=CGSizeMake(0, contentH);
128 }
129 
130 #pragma mark-私有方法
131 -(CGFloat)marginForType:(YYWaterflowViewMarginType)type
132 {
133     if ([self.delegate respondsToSelector:@selector(waterflowView:marginForType:)]) {
134        return  [self.delegate waterflowView:self marginForType:type];
135     }else
136     {
137         return YYWaterflowViewDefaultMargin;
138     }
139 }
140 
141 -(NSUInteger)numberOfColumns
142 {
143     if ([self.dadaSource respondsToSelector:@selector(numberOfColumnsInWaterflowView:)]) {
144         return [self.dadaSource numberOfColumnsInWaterflowView:self];
145     }else
146     {
147         return  YYWaterflowViewDefaultNumberOfClunms;
148     }
149 }
150 
151 -(CGFloat)heightAtIndex:(NSUInteger)index
152 {
153     if ([self.delegate respondsToSelector:@selector(waterflowView:heightAtIndex:)]) {
154         return [self.delegate waterflowView:self heightAtIndex:index];
155     }else
156     {
157         return YYWaterflowViewDefaultCellH;
158     }
159 }
160 @end

实现的瀑布流效果:

bubuko.com,布布扣     bubuko.com,布布扣

2.简单说明
说明
(1)瀑布流每一个的宽度是一样的,都是高度不一样
(2)补齐算法,哪里比较短就补哪里,不是简单的从左到右排(两列之间的差距越来越大)。
bubuko.com,布布扣
这就要求我们时刻知道每一列最大的Y值是多少,以比较哪里“最短”。
可以考虑使用一个C语言的数组来存放所有列的最大Y值
注意数组的初始化操作。
bubuko.com,布布扣
 
提示:瀑布流的最后一行一般都是参差不齐的。
可扩展性:
简单的修改cell的列数,即可修改布局。
(1)设置瀑布流为2列。
bubuko.com,布布扣
bubuko.com,布布扣
(2)设置瀑布流的列数为4列
bubuko.com,布布扣
bubuko.com,布布扣
(3)如果不设置列数,那么显示的列数默认为3列。
(4)如果不设置高度,那么显示的cell的高度为默认的高度,都是一样的。
  bubuko.com,布布扣
bubuko.com,布布扣
(5)cell的上下左右,行和列之间的间距也可以进行调整,这里不做演示。
(6)在cell中可以添加自定义的控件,如Button、imageView等,此时可以向使用UITableView和UITableViewcell一样来使用YYWaterflowView和YYWaterflowViewCell。
bubuko.com,布布扣
bubuko.com,布布扣
 
3.存在的问题
  上面的代码对cell的处理存在很大的性能问题,如果程序中又2000个cell,那么这里就创建了两千个cell,性能很差。
  可以通过在layoutSubviews方法中打印查看。
bubuko.com,布布扣
 
说明:之所以为2002,是因为创建了2000个cell+2个滚动条(水平方向上的滚动条被隐藏了,但是仍然存在)
优化思路:放入到缓存池。

iOS开发UI篇—自定义瀑布流控件(基本实现),布布扣,bubuko.com

iOS开发UI篇—自定义瀑布流控件(基本实现)

标签:style   blog   http   color   使用   os   strong   文件   

原文地址:http://www.cnblogs.com/wendingding/p/3876039.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!