瀑布流UIScrollView实现
本文实现的是瀑布流,通过UIScrollView简单实现的,主要简单实现瀑布流的效果,希望对各位读者有所帮助,
大体的实现思路是,通过创建一个plist文件来获取需要加载的图片,通过创建三列视图,添加到scrollView上依次向这个三列视图的添加图片,通过判断每一列视图高度得到哪列视图的高度最低,下次添加图片时往那个高度最低的视图上添加,添加一次判断一次,本人写的这篇实现较简单,并没有考虑太多情况,希望对各位读者有所帮助。
这个是瀑布流实现所定义的一些类和一个开源框架UrlImageView,这个开源框架主要是用来加载网络图片的。
1.个人写的这个瀑布流是先通过定义一个data.plist文件,把所有用到的关于图片信息的内容放入到这个plist文件中
这个每个item中添加的内容
2.通过定义两个model对象,一个是DataAccess和DataInfo
<1.>在DataAccess中主要定一个一个方法,通过这个方法读取plist文件
#import "DataAccess.h"
#import "DataInfo.h"
@implementation DataAccess
- (NSMutableArray *)getDataArray{
NSString * filePath = [[NSBundle mainBundle] pathForResource:@"dataList" ofType:@"plist"];
NSDictionary * dic = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSArray * imageList = [dic objectForKey:@"imageList"];
NSMutableArray * dataInfoArray = [NSMutableArray array];
for (NSDictionary * item in imageList) {
DataInfo * dataInfo = [[DataInfo alloc] init];
dataInfo.width = [item[@"width"] floatValue];
dataInfo.height = [item[@"height"] floatValue];
dataInfo.url = item[@"url"];
dataInfo.mess = item[@"mess"];
dataInfo.title = item[@"title"];
[dataInfoArray addObject:dataInfo];
}
return dataInfoArray;
}
@end
<2.>在dataInfo中定义的都是一个model属性
#import <Foundation/Foundation.h>
@interface DataInfo : NSObject
//源图片的宽度
@property (nonatomic,assign)float width;
//源图片的高度
@property (nonatomic,assign)float height;
//图片的url地址
@property (nonatomic,copy)NSString * url;
//图片的名字
@property (nonatomic,copy)NSString * title;
@property (nonatomic,copy)NSString * mess;
@end
3.在ViewController中主要实现数据的获取,瀑布流视图的创建
- (void)viewDidLoad
{
[super viewDidLoad];
//获取图片的数据
DataAccess * dataAccess = [[DataAccess alloc] init];
NSMutableArray * array = [dataAccess getDataArray];
//创建瀑布流视图,并通过自定init方法将图片数据传个瀑布流视图
self.whView = [[WHWaterView alloc] initWithData:array];
//将瀑布流视图添加到self.view
[self.view addSubview:self.whView];
}
@end
4.MessView这个类主要是对瀑布流视图中的每一个图片的显示和大小的布局主要是通过复写init方法
<1.>MessView.h
#import <UIKit/UIKit.h>
#import "DataInfo.h"
@interface MessView : UIView
- (id)initWithData:(DataInfo *)dataInfo yPoint:(float)y;
@end
<2.>MessView.m
#import "MessView.h"
#define WIDTH 320/3
#import "UrlImageView.h"
@implementation MessView
//复写init方法传入数据并且传入y坐标
- (id)initWithData:(DataInfo *)dataInfo yPoint:(float)y{
//获得缩略图的高度和宽度
float imgWidth = dataInfo.width;
float imgHeight = dataInfo.height;
float sImgWidth = WIDTH -4;
float sImgHeight = sImgWidth * imgHeight/imgWidth;
self = [super initWithFrame:CGRectMake(0, y, sImgWidth, sImgHeight)];
if (self) {
//通过开源框架UrlImageView直接创建imgView并且在网上加载图片
UrlImageView * imgView = [[UrlImageView alloc] initWithFrame:CGRectMake(2, 2, sImgWidth, sImgHeight)];
[imgView setImageWithURL:[NSURL URLWithString:dataInfo.url]];
[self addSubview:imgView];
//创建label
UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(2, self.frame.size.height - 28, WIDTH-4, 30)];
label.backgroundColor = [UIColor colorWithWhite:0 alpha:.8];
label.alpha = .5;
label.text = dataInfo.title;
label.textColor = [UIColor whiteColor];
[self addSubview:label];
}
return self;
}
5.WHWaterView这个视图继承于UIScrollView通过这个视图来创建完成瀑布流视图的实现
<1,>WHWaterView.h
#import <UIKit/UIKit.h>
#define WIDTH 320/3
@interface WHWaterView : UIScrollView{
//第1.2.3列视图
UIView * _view1;
UIView * _view2;
UIView * _view3;
int _highColume;//高度最高的那一列
int _lowColume;//高度最低的那一列
float _highColumeHeight;//最高列的高度
int _row;//行数
}
//复写初始化方法创建瀑布流视图对象并且传入数据
- (id)initWithData:(NSMutableArray *)arrayData;
@end
<2,>
WHWaterView.m
#import "WHWaterView.h"
#import "DataInfo.h"
#import "MessView.h"
@implementation WHWaterView
- (id)initWithData:(NSMutableArray *)arrayData{
self = [super initWithFrame:CGRectMake(0, 0, 320, 480)];
if (self) {
//初始化参数
[self initParams];
for (int i =0; i<arrayData.count;i++) {
if (i/3>0 && i%3==0) {
_row ++;
}
DataInfo * dataInfo =(DataInfo *)[arrayData objectAtIndex:i];
//如果为第一行的话添加messView
if (_row ==1) {
switch (i%3) {
case 0:
[self addMessView:_lowColume dataInfo:dataInfo];
break;
case 1:
[self addMessView:_lowColume dataInfo:dataInfo];
break;
case 2:
[self addMessView:_lowColume dataInfo:dataInfo];
break;
}
}else{
[self addMessView:_lowColume dataInfo:dataInfo];
}
//重新获得最低高度的列和最高高度的列
[self getHighColumeAndLowColume];
}
//并且设置当前视图的内容的size
[self setContentSize:CGSizeMake(320, _highColumeHeight)];
//将三个视图添加到当前视图
[self addSubview:_view1];
[self addSubview:_view2];
[self addSubview:_view3];
}
return self;
}
- (void)initParams{
//初始化三列视图
_view1 =[[UIView alloc] initWithFrame:CGRectMake(0, 0, WIDTH, 0)];
_view2 =[[UIView alloc] initWithFrame:CGRectMake(WIDTH, 0, WIDTH, 0)];
_view3 =[[UIView alloc] initWithFrame:CGRectMake(WIDTH*2, 0, WIDTH, 0)];
//初始化一系列参数
_highColume = 1;
_lowColume = 1;
_highColumeHeight = 1;
_row = 1;
}
//添加messView在高度最低的列
//将messView添加到高度最低的列
- (void)addMessView:(int)lowColume dataInfo:(DataInfo *)data{
MessView * messView = nil;
float hValue = 0;
switch (lowColume) {
case 1:
//创建messView,并且传入数据和messView的y坐标,_view1视图的高度就是messView的y坐标
messView = [[MessView alloc] initWithData:data yPoint:_view1.frame.size.height];
hValue = messView.frame.size.height;
//重新定义_view1的Frame (_view2,_view3与_view1雷同)
_view1.frame =CGRectMake(_view1.frame.origin.x, _view1.frame.origin.y, WIDTH, _view1.frame.size.height+hValue);
[_view1 addSubview:messView];
break;
case 2:
messView = [[MessView alloc] initWithData:data yPoint:_view2.frame.size.height];
hValue = messView.frame.size.height;
_view2.frame =CGRectMake(_view2.frame.origin.x, _view2.frame.origin.y, WIDTH, _view2.frame.size.height+hValue);
[_view2 addSubview:messView];
break;
case 3:
messView = [[MessView alloc] initWithData:data yPoint:_view3.frame.size.height];
hValue = messView.frame.size.height;
_view3.frame =CGRectMake(_view3.frame.origin.x, _view3.frame.origin.y, WIDTH, _view3.frame.size.height+hValue);
[_view3 addSubview:messView];
break;
}
}
//重新获得 高度最高的列 和 高度最低的列 和 高度最高列的高度
- (void)getHighColumeAndLowColume{
//这个判断是获得高度最高的列,并且设置
if (_view1.frame.size.height > _highColumeHeight) {
_highColumeHeight = _view1.frame.size.height;
_highColume = 1;
}else if (_view2.frame.size.height > _highColumeHeight){
_highColumeHeight = _view2.frame.size.height;
_highColume = 2;
}else if (_view3.frame.size.height > _highColumeHeight){
_highColumeHeight = _view3.frame.size.height;
_highColume = 3;
}
//这个判断是获得高度最低的列
float view1Height = _view1.frame.size.height;
float view2Height = _view2.frame.size.height;
float view3Height = _view3.frame.size.height;
if (view1Height < view2Height) {
if (view1Height < view3Height) {
_lowColume = 1;
}else{
_lowColume = 3;
}
}else{
if (view2Height < view3Height) {
_lowColume = 2;
}else{
_lowColume = 3;
}
}
}
@end