iosiOS開發之瀑布流
編輯:IOS開發綜合
想必大家已經對互聯網傳統的照片布局方式司空見慣了,這種行列分明的布局雖然對用戶來說簡潔明了,但是長久的使用難免會產生審美疲勞。現在網上流行一種叫做“瀑布流”的照片布局樣式,這種行與列參差不齊的狀態著實給用戶眼前一亮的感覺,這種不規則的方式也吸引著我,現在我們就來一起實現它吧 :)
首先我們來看一下這種樣式布局是如何體現的,請看示意圖:
別看這種界面的布局好像毫無規律,其實它的排列還是很有規則的。我們拿手機屏幕舉個例子,我們把屏幕等寬的劃分為幾個區域,由於手機屏幕比較小,我們就按照網上
最普遍的把屏幕分為等寬的三列,然後將圖片加載在每一列中,在加入到列之前,要先判斷哪一列的高度最低,然後把圖片加到列高度最低的那列中。聽起來是不是有些拗口,說簡單點就是“哪列高度低就加哪”,這樣聽我一說是不是覺得原理其實很簡單嘛!
下面我們就來用程序去實現他吧!首先看一張效果圖。
新建一個Xcode工程,名字隨便取吧(或者叫Album都可以),然後新建三個類,分別是:MainViewController用於控制主界面, MyScrollView繼承自UIScrollView用於控制界面滾動,以及圖片的管理類ImageLoader。
我們先來看一下ImageLoader類,它是一個圖片的處理類,負責對取到的圖片進行等比例壓縮,以至於加載到UImageView中時不會失真,代碼如下:
- #import"ImageLoader.h"
-
- @interfaceImageLoader()
-
- @end
-
- @implementationImageLoader
- @synthesizeimagesArray=_imagesArray;
-
- +(ImageLoader*)shareInstance{
- staticImageLoader*loader=nil;
- staticdispatch_once_tonceToken;
- dispatch_once(&onceToken,^{
- loader=[[ImageLoaderalloc]init];
- });
- returnloader;
- }
-
- -(id)initWithNibName:(NSString*)nibNameOrNilbundle:(NSBundle*)nibBundleOrNil
- {
- self=[superinitWithNibName:nibNameOrNilbundle:nibBundleOrNil];
- if(self){
- //Custominitialization
- }
- returnself;
- }
-
- -(void)viewDidLoad
- {
- [superviewDidLoad];
- //Doanyadditionalsetupafterloadingtheview.
- }
-
- /*加載圖片*/
- -(void)loadImage:(NSMutableArray*)array{
- self.imagesArray=array;
- }
-
- /*
- 壓縮圖片,根據圖片的大小按比例壓縮
- width:每列試圖的寬度
- 返回一個UIImageView
- */
- -(UIImageView*)compressImage:(float)widthimageName:(NSString*)name{
- UIImageView*imgView=[[UIImageViewalloc]init];
- imgView.image=[UIImageimageNamed:name];
-
- floatorgi_width=[imgViewimage].size.width;
- floatorgi_height=[imgViewimage].size.height;
-
- //按照每列的寬度,以及圖片的寬高來按比例壓縮
- floatnew_width=width-5;
- floatnew_height=(width*orgi_height)/orgi_width;
-
- //重置imageView的尺寸
- [imgViewsetFrame:CGRectMake(0,0,new_width,new_height)];
-
- returnimgView;
- }
-
- -(void)didReceiveMemoryWarning
- {
- [superdidReceiveMemoryWarning];
- //Disposeofanyresourcesthatcanberecreated.
- }
-
- -(void)dealloc{
- [self.imagesArrayrelease];
- [superdealloc];
- }
-
- @end
這裡將ImageLoader類設置成了單例,以便於在MainViewContrioller和MyScrollView中獲取。
下面是MyScrollView的代碼片段:
- #import"MyScrollView.h"
-
- #defineCOORDINATE_X_LEFT5
- #defineCOORDINATE_X_MIDDLEMY_WIDTH/3+5
- #defineCOORDINATE_X_RIGHTMY_WIDTH/3*2+5
- #definePAGESIZE21
-
- @interfaceMyScrollView()
-
- @end
-
- @implementationMyScrollView
- @synthesizemainScroll=_mainScroll;
- @synthesizeisOnce=_isOnce;
- @synthesizeimagesName=_imagesName;
- @synthesizeloadedImageDic=_loadedImageDic;
- @synthesizeleftColumHeight=_leftColumHeight;
- @synthesizemidColumHeight=_midColumHeight;
- @synthesizerightColumHeight=_rightColumHeight;
- @synthesizeloadedImageArray=_loadedImageArray;
- @synthesizeimgTag=_imgTag;
- @synthesizeimgTagDic=_imgTagDic;
- @synthesizeimageLoad=_imageLoad;
- @synthesizepage=_page;
-
- +(MyScrollView*)shareInstance{
- staticMyScrollView*instance;
- staticdispatch_once_tonceToken;
- dispatch_once(&onceToken,^{
- instance=[[selfalloc]initWithFrame:CGRectMake(0,0,MY_WIDTH,MY_HEIGHT)];
- });
-
- returninstance;
- }
-
- /*
- 初始化scrollView的委托以及背景顏色,不顯示它的水平,垂直顯示條
- */
- -(id)initWithFrame:(CGRect)frame{
- self=[superinitWithFrame:frame];
- if(self){
- self.delegate=self;
- self.backgroundColor=[UIColorblackColor];
- self.pagingEnabled=NO;
- self.showsHorizontalScrollIndicator=NO;
- self.showsVerticalScrollIndicator=NO;
-
- self.isOnce=YES;
- self.loadedImageDic=[[NSMutableDictionaryalloc]init];
- self.loadedImageArray=[[NSMutableArrayalloc]init];
- self.imgTagDic=[[NSMutableDictionaryalloc]init];
-
- //初始化列的高度
- self.leftColumHeight=3.0f;
- self.midColumHeight=3.0f;
- self.rightColumHeight=3.0f;
- self.imgTag=10086;
- self.page=1;
-
- [selfinitWithPhotoBox];
- }
-
- returnself;
- }
-
- /*
- 將scrollView界面分為大小相等的3個部分,每個部分為一個UIView,並設置每一個UIView的tag
- */
- -(void)initWithPhotoBox{
- UIView*leftView=[[UIViewalloc]initWithFrame:CGRectMake(0,0,MY_WIDTH/3,self.frame.size.height)];
- UIView*middleView=[[UIViewalloc]initWithFrame:CGRectMake(leftView.frame.origin.x+MY_WIDTH/3,0,MY_WIDTH/3,
- self.frame.size.height)];
- UIView*rightView=[[UIViewalloc]initWithFrame:CGRectMake(middleView.frame.origin.x+MY_WIDTH/3,0,MY_WIDTH/3,
- self.frame.size.height)];
- //設置三個部分的tag
- leftView.tag=100;
- middleView.tag=101;
- rightView.tag=102;
-
- //設置背景顏色
- [leftViewsetBackgroundColor:[UIColorclearColor]];
- [middleViewsetBackgroundColor:[UIColorclearColor]];
- [rightViewsetBackgroundColor:[UIColorclearColor]];
-
- [selfaddSubview:leftView];
- [selfaddSubview:middleView];
- [selfaddSubview:rightView];
-
- //第一次加載圖片
- self.imageLoad=[ImageLoadershareInstance];
- for(inti=0;i NSString*imageName=[self.imageLoad.imagesArrayobjectAtIndex:i];
- UIImageView*imgView=[self.imageLoadcompressImage:MY_WIDTH/3imageName:imageName];
- [selfaddImage:imgViewname:imageName];
- [selfcheckImageIsVisible];
- }
- //第一頁
- self.page=1;
-
- [selfadjustContentSize:NO];
- }
-
- /*調整scrollview*/
- -(void)adjustContentSize:(BOOL)isEnd{
- UIView*leftView=[selfviewWithTag:100];
- UIView*middleView=[selfviewWithTag:101];
- UIView*rightView=[selfviewWithTag:102];
-
- if(_leftColumHeight>=_midColumHeight&&_leftColumHeight>=_rightColumHeight){
- self.contentSize=leftView.frame.size;
- }else{
- if(_midColumHeight>=_rightColumHeight){
- self.contentSize=middleView.frame.size;
- }else{
- self.contentSize=rightView.frame.size;
- }
- }
- }
-
- /*
- 得到最短列的高度
- */
- -(float)getTheShortColum{
- if(_leftColumHeight<=_midColumHeight&&_leftColumHeight<=_rightColumHeight){
- return_leftColumHeight;
- }else{
- if(_midColumHeight<=_rightColumHeight){
- return_midColumHeight;
- }else{
- return_rightColumHeight;
- }
- }
- }
-
- /*
- 添加一張圖片
- 規則:根據每一列的高度來決定,優先加載列高度最短的那列
- 重新設置圖片的x,y坐標
- imageView:圖片視圖
- imageName:圖片名
- */
- -(void)addImage:(UIImageView*)imageViewname:(NSString*)imageName{
- //圖片是否加載
- if([self.loadedImageDicobjectForKey:imageName]){
- return;
- }
-
- //若圖片還未加載則保存
- [self.loadedImageDicsetObject:imageViewforKey:imageName];
- [self.loadedImageArrayaddObject:imageView];
-
- [selfimageTagWithAction:imageViewname:imageName];
-
- floatwidth=imageView.frame.size.width;
- floatheight=imageView.frame.size.height;
- //判斷哪一列的高度最低
- if(_leftColumHeight<=_midColumHeight&&_leftColumHeight<=_rightColumHeight){
- UIView*leftView=[selfviewWithTag:100];
- [leftViewaddSubview:imageView];
- //重新設置坐標
- [imageViewsetFrame:CGRectMake(2,_leftColumHeight,width,height)];
- _leftColumHeight=_leftColumHeight+height+3;
- [leftViewsetFrame:CGRectMake(0,0,MY_WIDTH/3,_leftColumHeight)];
- }else{
- if(_midColumHeight<=_rightColumHeight){
- UIView*middleView=[selfviewWithTag:101];
- [middleViewaddSubview:imageView];
-
- [imageViewsetFrame:CGRectMake(2,_midColumHeight,width,height)];
- _midColumHeight=_midColumHeight+height+3;
- [middleViewsetFrame:CGRectMake(MY_WIDTH/3,0,MY_WIDTH/3,_midColumHeight)];
- }else{
- UIView*rightView=[selfviewWithTag:102];
- [rightViewaddSubview:imageView];
-
- [imageViewsetFrame:CGRectMake(2,_rightColumHeight,width,height)];
- _rightColumHeight=_rightColumHeight+height+3;
- [rightViewsetFrame:CGRectMake(22*MY_WIDTH/3,0,MY_WIDTH/3,_rightColumHeight)];
- }
- }
- }
-
- /*
- 將圖片tag保存,以及為UIImageView添加事件響應
- */
- -(void)imageTagWithAction:(UIImageView*)imageViewname:(NSString*)imageName{
- //將要顯示圖片的tag保存
- imageView.tag=self.imgTag;
- [self.imgTagDicsetObject:imageNameforKey:[NSStringstringWithFormat:@"%d",imageView.tag]];
- self.imgTag++;
-
- //圖片添加事件響應
- UITapGestureRecognizer*tapRecognizer=[[UITapGestureRecognizeralloc]initWithTarget:selfaction:@selector(imageClickWithTag:)];
- tapRecognizer.delegate=self;
- imageView.userInteractionEnabled=YES;
- [imageViewaddGestureRecognizer:tapRecognizer];
- [tapRecognizerrelease];
- }
-
-
-
- /*
- //若三列中最短列距離底部高度超過30像素,則請求加載新的圖片
- */
- -(void)scrollViewDidScroll:(UIScrollView*)scrollView{
- //可視檢查
- [selfcheckImageIsVisible];
- if((self.contentOffset.y+self.frame.size.height)-[selfgetTheShortColum]>30){
- [selfpullRefreshImages];
- }
- }
-
- /*
- 上拉時加載新的圖片
- */
- -(void)pullRefreshImages{
- intindex=self.page*PAGESIZE;
- intimgNum=[self.imageLoad.imagesArraycount];
-
- if(index>=imgNum){
- //圖片加載完畢
- [selfadjustContentSize:YES];
- [MyToastshowWithText:@"沒有更多圖片"];
- }else{
- if((imgNum-self.page*PAGESIZE)>PAGESIZE){
- for(inti=index;i NSString*imageName=[self.imageLoad.imagesArrayobjectAtIndex:i];
- UIImageView*imgView=[self.imageLoadcompressImage:MY_WIDTH/3imageName:imageName];
- [selfaddImage:imgViewname:imageName];
- [selfcheckImageIsVisible];
- }
- }else{
- for(inti=index;i NSString*imageName=[self.imageLoad.imagesArrayobjectAtIndex:i];
- UIImageView*imgView=[self.imageLoadcompressImage:MY_WIDTH/3imageName:imageName];
- [selfaddImage:imgViewname:imageName];
- [selfcheckImageIsVisible];
- }
- }
- self.page++;
- }
-
- [selfadjustContentSize:NO];
- }
-
- /*
- 檢查圖片是否可見,如果不在可見視線內,則把圖片替換為nil
- */
- -(void)checkImageIsVisible{
- for(inti=0;i<[self.loadedImageArraycount];i++){
- UIImageView*imgView=[self.loadedImageArrayobjectAtIndex:i];
-
- if((self.contentOffset.y-imgView.frame.origin.y)>imgView.frame.size.height||
- imgView.frame.origin.y>(self.frame.size.height+self.contentOffset.y)){
- //不顯示圖片
- imgView.image=nil;
- }else{
- //重新根據tag值顯示圖片
- NSString*imageName=[self.imgTagDicobjectForKey:[NSStringstringWithFormat:@"%d",imgView.tag]];
- if((NSNull*)imageName==[NSNullnull]){
- return;
- }
- UIImageView*view=[self.imageLoadcompressImage:MY_WIDTH/3imageName:imageName];
- imgView.image=view.image;
- }
- }
- }
-
- //點擊圖片事件響應
- -(void)imageClickWithTag:(UITapGestureRecognizer*)sender{
- UIImageView*view=(UIImageView*)sender.view;
- NSString*imageName=[self.imgTagDicobjectForKey:[NSStringstringWithFormat:@"%d",view.tag]];
- NSLog(@"%@",imageName);
-
- PhotoViewController*photoView=[[PhotoViewControlleralloc]init];
- photoView.imageName=imageName;
- [selfaddSubview:photoView.view];
- }
-
-
- -(void)dealloc{
- [self.imagesNamerelease];
- [self.imgTagDicrelease];
- [self.loadedImageArrayrelease];
- [superdealloc];
- }
-
- @end
在這個類中,我將三列等寬的UIView加入到ScrollView中,每次加入一張圖片的時候都會去判斷一下哪一列的高度最低。為了避免手機被圖片的占用內存過高導致程序
崩潰的問題,我還作了一個照片可見性的邏輯判斷,具體函數名為checkImageIsVisible,當照片不可見時,將imageView中的image設為nil,一旦照片出現了就根據照片的tag
獲取到照片名重新設置image。
最後,當照片加載出來以後當然不能少了點擊查看相冊的功能啊!於是新建一個UIViewController類取名為:PhotoViewController,代碼如下:
- #import"PhotoViewController.h"
-
- @interfacePhotoViewController()
-
- @end
-
- @implementationPhotoViewController
- @synthesizeheadView=_headView;
- @synthesizemainView=_mainView;
-
-
- -(id)initWithNibName:(NSString*)nibNameOrNilbundle:(NSBundle*)nibBundleOrNil
- {
- self=[superinitWithNibName:nibNameOrNilbundle:nibBundleOrNil];
- if(self){
- //Custominitialization
- }
- returnself;
- }
-
- -(void)viewDidLoad
- {
- [superviewDidLoad];
- //Doanyadditionalsetupafterloadingtheview.
- [self.viewsetFrame:CGRectMake(0,0,MY_WIDTH,MY_HEIGHT)];
- [self.viewsetBackgroundColor:[UIColorblackColor]];
-
- self.headView=[[UIViewalloc]initWithFrame:CGRectMake(0,0,MY_WIDTH,50)];
- UIButton*cancelBtn=[[UIButtonalloc]initWithFrame:CGRectMake(0,20,40,30)];
- [cancelBtnsetTitleColor:[UIColorwhiteColor]forState:UIControlStateNormal];
- [cancelBtnsetTitle:@"取消"forState:UIControlStateNormal];
- [self.headViewaddSubview:cancelBtn];
- [cancelBtnaddTarget:selfaction:@selector(closePhotoView)forControlEvents:UIControlEventTouchUpInside];
- [self.viewaddSubview:self.headView];
-
- self.mainView=[[UIViewalloc]initWithFrame:CGRectMake(0,80,MY_WIDTH,MY_HEIGHT)];
- [self.viewaddSubview:self.mainView];
- }
-
- -(void)viewWillAppear:(BOOL)animated{
- UIImageView*imageV=[selfcompressImage:MY_WIDTHimageName:_imageName];
- [self.mainViewaddSubview:imageV];
- }
-
- -(UIImageView*)compressImage:(float)widthimageName:(NSString*)name{
- UIImageView*imgView=[[UIImageViewalloc]init];
- imgView.image=[UIImageimageNamed:name];
-
- floatorgi_width=[imgViewimage].size.width;
- floatorgi_height=[imgViewimage].size.height;
-
- //按照每列的寬度,以及圖片的寬高來按比例壓縮
- floatnew_width=width-5;
- floatnew_height=(width*orgi_height)/orgi_width;
-
- //重置imageView的尺寸
- [imgViewsetFrame:CGRectMake(0,0,new_width,new_height)];
-
- returnimgView;
- }
-
- -(void)didReceiveMemoryWarning
- {
- [superdidReceiveMemoryWarning];
- //Disposeofanyresourcesthatcanberecreated.
- }
-
- //關閉
- -(void)closePhotoView{
-
- [self.viewremoveFromSuperview];
- }
-
- -(void)dealloc{
- [self.headViewrelease];
- [self.mainViewrelease];
-
- [superdealloc];
- }
-
-
- @end
這個類主要是用於顯示大圖片所用,用戶點擊小圖片後,程序根據圖片的tag來獲取點擊圖片的名字,然後將名字傳遞給該類,完成對相應圖片的顯示,當然這裡也要做對圖片的壓縮處理,使它顯示的時候不失真。(由於本人有點懶,這個類的界面美觀什麼的就懶得調了,多多包涵)示意圖如下:
以上就是這個例子的大部分代碼了,如果要下載完整工程的話,請到我的上傳中下載。
現在看一下整個效果;
- 上一頁:iOS與網頁JS交互
- 下一頁:iOS開發數據庫SQLite的使用
Copyright ©
Ios教程網 All Rights Reserved