你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iosiOS開發之瀑布流

iosiOS開發之瀑布流

編輯:IOS開發綜合

想必大家已經對互聯網傳統的照片布局方式司空見慣了,這種行列分明的布局雖然對用戶來說簡潔明了,但是長久的使用難免會產生審美疲勞。現在網上流行一種叫做“瀑布流”的照片布局樣式,這種行與列參差不齊的狀態著實給用戶眼前一亮的感覺,這種不規則的方式也吸引著我,現在我們就來一起實現它吧 :)
首先我們來看一下這種樣式布局是如何體現的,請看示意圖:

\

 

別看這種界面的布局好像毫無規律,其實它的排列還是很有規則的。我們拿手機屏幕舉個例子,我們把屏幕等寬的劃分為幾個區域,由於手機屏幕比較小,我們就按照網上
最普遍的把屏幕分為等寬的三列,然後將圖片加載在每一列中,在加入到列之前,要先判斷哪一列的高度最低,然後把圖片加到列高度最低的那列中。聽起來是不是有些拗口,說簡單點就是“哪列高度低就加哪”,這樣聽我一說是不是覺得原理其實很簡單嘛!
下面我們就來用程序去實現他吧!首先看一張效果圖。

\

 

新建一個Xcode工程,名字隨便取吧(或者叫Album都可以),然後新建三個類,分別是:MainViewController用於控制主界面, MyScrollView繼承自UIScrollView用於控制界面滾動,以及圖片的管理類ImageLoader。
我們先來看一下ImageLoader類,它是一個圖片的處理類,負責對取到的圖片進行等比例壓縮,以至於加載到UImageView中時不會失真,代碼如下:

 

  1. #import"ImageLoader.h"
  2.  
  3. @interfaceImageLoader()
  4.  
  5. @end
  6.  
  7. @implementationImageLoader
  8. @synthesizeimagesArray=_imagesArray;
  9.  
  10. +(ImageLoader*)shareInstance{
  11. staticImageLoader*loader=nil;
  12. staticdispatch_once_tonceToken;
  13. dispatch_once(&onceToken,^{
  14. loader=[[ImageLoaderalloc]init];
  15. });
  16. returnloader;
  17. }
  18.  
  19. -(id)initWithNibName:(NSString*)nibNameOrNilbundle:(NSBundle*)nibBundleOrNil
  20. {
  21. self=[superinitWithNibName:nibNameOrNilbundle:nibBundleOrNil];
  22. if(self){
  23. //Custominitialization
  24. }
  25. returnself;
  26. }
  27.  
  28. -(void)viewDidLoad
  29. {
  30. [superviewDidLoad];
  31. //Doanyadditionalsetupafterloadingtheview.
  32. }
  33.  
  34. /*加載圖片*/
  35. -(void)loadImage:(NSMutableArray*)array{
  36. self.imagesArray=array;
  37. }
  38.  
  39. /*
  40. 壓縮圖片,根據圖片的大小按比例壓縮
  41. width:每列試圖的寬度
  42. 返回一個UIImageView
  43. */
  44. -(UIImageView*)compressImage:(float)widthimageName:(NSString*)name{
  45. UIImageView*imgView=[[UIImageViewalloc]init];
  46. imgView.image=[UIImageimageNamed:name];
  47.  
  48. floatorgi_width=[imgViewimage].size.width;
  49. floatorgi_height=[imgViewimage].size.height;
  50.  
  51. //按照每列的寬度,以及圖片的寬高來按比例壓縮
  52. floatnew_width=width-5;
  53. floatnew_height=(width*orgi_height)/orgi_width;
  54.  
  55. //重置imageView的尺寸
  56. [imgViewsetFrame:CGRectMake(0,0,new_width,new_height)];
  57.  
  58. returnimgView;
  59. }
  60.  
  61. -(void)didReceiveMemoryWarning
  62. {
  63. [superdidReceiveMemoryWarning];
  64. //Disposeofanyresourcesthatcanberecreated.
  65. }
  66.  
  67. -(void)dealloc{
  68. [self.imagesArrayrelease];
  69. [superdealloc];
  70. }
  71.  
  72. @end

 

這裡將ImageLoader類設置成了單例,以便於在MainViewContrioller和MyScrollView中獲取。
下面是MyScrollView的代碼片段:

  1. #import"MyScrollView.h"
  2.  
  3. #defineCOORDINATE_X_LEFT5
  4. #defineCOORDINATE_X_MIDDLEMY_WIDTH/3+5
  5. #defineCOORDINATE_X_RIGHTMY_WIDTH/3*2+5
  6. #definePAGESIZE21
  7.  
  8. @interfaceMyScrollView()
  9.  
  10. @end
  11.  
  12. @implementationMyScrollView
  13. @synthesizemainScroll=_mainScroll;
  14. @synthesizeisOnce=_isOnce;
  15. @synthesizeimagesName=_imagesName;
  16. @synthesizeloadedImageDic=_loadedImageDic;
  17. @synthesizeleftColumHeight=_leftColumHeight;
  18. @synthesizemidColumHeight=_midColumHeight;
  19. @synthesizerightColumHeight=_rightColumHeight;
  20. @synthesizeloadedImageArray=_loadedImageArray;
  21. @synthesizeimgTag=_imgTag;
  22. @synthesizeimgTagDic=_imgTagDic;
  23. @synthesizeimageLoad=_imageLoad;
  24. @synthesizepage=_page;
  25.  
  26. +(MyScrollView*)shareInstance{
  27. staticMyScrollView*instance;
  28. staticdispatch_once_tonceToken;
  29. dispatch_once(&onceToken,^{
  30. instance=[[selfalloc]initWithFrame:CGRectMake(0,0,MY_WIDTH,MY_HEIGHT)];
  31. });
  32.  
  33. returninstance;
  34. }
  35.  
  36. /*
  37. 初始化scrollView的委托以及背景顏色,不顯示它的水平,垂直顯示條
  38. */
  39. -(id)initWithFrame:(CGRect)frame{
  40. self=[superinitWithFrame:frame];
  41. if(self){
  42. self.delegate=self;
  43. self.backgroundColor=[UIColorblackColor];
  44. self.pagingEnabled=NO;
  45. self.showsHorizontalScrollIndicator=NO;
  46. self.showsVerticalScrollIndicator=NO;
  47.  
  48. self.isOnce=YES;
  49. self.loadedImageDic=[[NSMutableDictionaryalloc]init];
  50. self.loadedImageArray=[[NSMutableArrayalloc]init];
  51. self.imgTagDic=[[NSMutableDictionaryalloc]init];
  52.  
  53. //初始化列的高度
  54. self.leftColumHeight=3.0f;
  55. self.midColumHeight=3.0f;
  56. self.rightColumHeight=3.0f;
  57. self.imgTag=10086;
  58. self.page=1;
  59.  
  60. [selfinitWithPhotoBox];
  61. }
  62.  
  63. returnself;
  64. }
  65.  
  66. /*
  67. 將scrollView界面分為大小相等的3個部分,每個部分為一個UIView,並設置每一個UIView的tag
  68. */
  69. -(void)initWithPhotoBox{
  70. UIView*leftView=[[UIViewalloc]initWithFrame:CGRectMake(0,0,MY_WIDTH/3,self.frame.size.height)];
  71. UIView*middleView=[[UIViewalloc]initWithFrame:CGRectMake(leftView.frame.origin.x+MY_WIDTH/3,0,MY_WIDTH/3,
  72. self.frame.size.height)];
  73. UIView*rightView=[[UIViewalloc]initWithFrame:CGRectMake(middleView.frame.origin.x+MY_WIDTH/3,0,MY_WIDTH/3,
  74. self.frame.size.height)];
  75. //設置三個部分的tag
  76. leftView.tag=100;
  77. middleView.tag=101;
  78. rightView.tag=102;
  79.  
  80. //設置背景顏色
  81. [leftViewsetBackgroundColor:[UIColorclearColor]];
  82. [middleViewsetBackgroundColor:[UIColorclearColor]];
  83. [rightViewsetBackgroundColor:[UIColorclearColor]];
  84.  
  85. [selfaddSubview:leftView];
  86. [selfaddSubview:middleView];
  87. [selfaddSubview:rightView];
  88.  
  89. //第一次加載圖片
  90. self.imageLoad=[ImageLoadershareInstance];
  91. for(inti=0;i NSString*imageName=[self.imageLoad.imagesArrayobjectAtIndex:i];
  92. UIImageView*imgView=[self.imageLoadcompressImage:MY_WIDTH/3imageName:imageName];
  93. [selfaddImage:imgViewname:imageName];
  94. [selfcheckImageIsVisible];
  95. }
  96. //第一頁
  97. self.page=1;
  98.  
  99. [selfadjustContentSize:NO];
  100. }
  101.  
  102. /*調整scrollview*/
  103. -(void)adjustContentSize:(BOOL)isEnd{
  104. UIView*leftView=[selfviewWithTag:100];
  105. UIView*middleView=[selfviewWithTag:101];
  106. UIView*rightView=[selfviewWithTag:102];
  107.  
  108. if(_leftColumHeight>=_midColumHeight&&_leftColumHeight>=_rightColumHeight){
  109. self.contentSize=leftView.frame.size;
  110. }else{
  111. if(_midColumHeight>=_rightColumHeight){
  112. self.contentSize=middleView.frame.size;
  113. }else{
  114. self.contentSize=rightView.frame.size;
  115. }
  116. }
  117. }
  118.  
  119. /*
  120. 得到最短列的高度
  121. */
  122. -(float)getTheShortColum{
  123. if(_leftColumHeight<=_midColumHeight&&_leftColumHeight<=_rightColumHeight){
  124. return_leftColumHeight;
  125. }else{
  126. if(_midColumHeight<=_rightColumHeight){
  127. return_midColumHeight;
  128. }else{
  129. return_rightColumHeight;
  130. }
  131. }
  132. }
  133.  
  134. /*
  135. 添加一張圖片
  136. 規則:根據每一列的高度來決定,優先加載列高度最短的那列
  137. 重新設置圖片的x,y坐標
  138. imageView:圖片視圖
  139. imageName:圖片名
  140. */
  141. -(void)addImage:(UIImageView*)imageViewname:(NSString*)imageName{
  142. //圖片是否加載
  143. if([self.loadedImageDicobjectForKey:imageName]){
  144. return;
  145. }
  146.  
  147. //若圖片還未加載則保存
  148. [self.loadedImageDicsetObject:imageViewforKey:imageName];
  149. [self.loadedImageArrayaddObject:imageView];
  150.  
  151. [selfimageTagWithAction:imageViewname:imageName];
  152.  
  153. floatwidth=imageView.frame.size.width;
  154. floatheight=imageView.frame.size.height;
  155. //判斷哪一列的高度最低
  156. if(_leftColumHeight<=_midColumHeight&&_leftColumHeight<=_rightColumHeight){
  157. UIView*leftView=[selfviewWithTag:100];
  158. [leftViewaddSubview:imageView];
  159. //重新設置坐標
  160. [imageViewsetFrame:CGRectMake(2,_leftColumHeight,width,height)];
  161. _leftColumHeight=_leftColumHeight+height+3;
  162. [leftViewsetFrame:CGRectMake(0,0,MY_WIDTH/3,_leftColumHeight)];
  163. }else{
  164. if(_midColumHeight<=_rightColumHeight){
  165. UIView*middleView=[selfviewWithTag:101];
  166. [middleViewaddSubview:imageView];
  167.  
  168. [imageViewsetFrame:CGRectMake(2,_midColumHeight,width,height)];
  169. _midColumHeight=_midColumHeight+height+3;
  170. [middleViewsetFrame:CGRectMake(MY_WIDTH/3,0,MY_WIDTH/3,_midColumHeight)];
  171. }else{
  172. UIView*rightView=[selfviewWithTag:102];
  173. [rightViewaddSubview:imageView];
  174.  
  175. [imageViewsetFrame:CGRectMake(2,_rightColumHeight,width,height)];
  176. _rightColumHeight=_rightColumHeight+height+3;
  177. [rightViewsetFrame:CGRectMake(22*MY_WIDTH/3,0,MY_WIDTH/3,_rightColumHeight)];
  178. }
  179. }
  180. }
  181.  
  182. /*
  183. 將圖片tag保存,以及為UIImageView添加事件響應
  184. */
  185. -(void)imageTagWithAction:(UIImageView*)imageViewname:(NSString*)imageName{
  186. //將要顯示圖片的tag保存
  187. imageView.tag=self.imgTag;
  188. [self.imgTagDicsetObject:imageNameforKey:[NSStringstringWithFormat:@"%d",imageView.tag]];
  189. self.imgTag++;
  190.  
  191. //圖片添加事件響應
  192. UITapGestureRecognizer*tapRecognizer=[[UITapGestureRecognizeralloc]initWithTarget:selfaction:@selector(imageClickWithTag:)];
  193. tapRecognizer.delegate=self;
  194. imageView.userInteractionEnabled=YES;
  195. [imageViewaddGestureRecognizer:tapRecognizer];
  196. [tapRecognizerrelease];
  197. }
  198.  
  199.  
  200.  
  201. /*
  202. //若三列中最短列距離底部高度超過30像素,則請求加載新的圖片
  203. */
  204. -(void)scrollViewDidScroll:(UIScrollView*)scrollView{
  205. //可視檢查
  206. [selfcheckImageIsVisible];
  207. if((self.contentOffset.y+self.frame.size.height)-[selfgetTheShortColum]>30){
  208. [selfpullRefreshImages];
  209. }
  210. }
  211.  
  212. /*
  213. 上拉時加載新的圖片
  214. */
  215. -(void)pullRefreshImages{
  216. intindex=self.page*PAGESIZE;
  217. intimgNum=[self.imageLoad.imagesArraycount];
  218.  
  219. if(index>=imgNum){
  220. //圖片加載完畢
  221. [selfadjustContentSize:YES];
  222. [MyToastshowWithText:@"沒有更多圖片"];
  223. }else{
  224. if((imgNum-self.page*PAGESIZE)>PAGESIZE){
  225. for(inti=index;i NSString*imageName=[self.imageLoad.imagesArrayobjectAtIndex:i];
  226. UIImageView*imgView=[self.imageLoadcompressImage:MY_WIDTH/3imageName:imageName];
  227. [selfaddImage:imgViewname:imageName];
  228. [selfcheckImageIsVisible];
  229. }
  230. }else{
  231. for(inti=index;i NSString*imageName=[self.imageLoad.imagesArrayobjectAtIndex:i];
  232. UIImageView*imgView=[self.imageLoadcompressImage:MY_WIDTH/3imageName:imageName];
  233. [selfaddImage:imgViewname:imageName];
  234. [selfcheckImageIsVisible];
  235. }
  236. }
  237. self.page++;
  238. }
  239.  
  240. [selfadjustContentSize:NO];
  241. }
  242.  
  243. /*
  244. 檢查圖片是否可見,如果不在可見視線內,則把圖片替換為nil
  245. */
  246. -(void)checkImageIsVisible{
  247. for(inti=0;i<[self.loadedImageArraycount];i++){
  248. UIImageView*imgView=[self.loadedImageArrayobjectAtIndex:i];
  249.  
  250. if((self.contentOffset.y-imgView.frame.origin.y)>imgView.frame.size.height||
  251. imgView.frame.origin.y>(self.frame.size.height+self.contentOffset.y)){
  252. //不顯示圖片
  253. imgView.image=nil;
  254. }else{
  255. //重新根據tag值顯示圖片
  256. NSString*imageName=[self.imgTagDicobjectForKey:[NSStringstringWithFormat:@"%d",imgView.tag]];
  257. if((NSNull*)imageName==[NSNullnull]){
  258. return;
  259. }
  260. UIImageView*view=[self.imageLoadcompressImage:MY_WIDTH/3imageName:imageName];
  261. imgView.image=view.image;
  262. }
  263. }
  264. }
  265.  
  266. //點擊圖片事件響應
  267. -(void)imageClickWithTag:(UITapGestureRecognizer*)sender{
  268. UIImageView*view=(UIImageView*)sender.view;
  269. NSString*imageName=[self.imgTagDicobjectForKey:[NSStringstringWithFormat:@"%d",view.tag]];
  270. NSLog(@"%@",imageName);
  271.  
  272. PhotoViewController*photoView=[[PhotoViewControlleralloc]init];
  273. photoView.imageName=imageName;
  274. [selfaddSubview:photoView.view];
  275. }
  276.  
  277.  
  278. -(void)dealloc{
  279. [self.imagesNamerelease];
  280. [self.imgTagDicrelease];
  281. [self.loadedImageArrayrelease];
  282. [superdealloc];
  283. }
  284.  
  285. @end

 

在這個類中,我將三列等寬的UIView加入到ScrollView中,每次加入一張圖片的時候都會去判斷一下哪一列的高度最低。為了避免手機被圖片的占用內存過高導致程序
崩潰的問題,我還作了一個照片可見性的邏輯判斷,具體函數名為checkImageIsVisible,當照片不可見時,將imageView中的image設為nil,一旦照片出現了就根據照片的tag
獲取到照片名重新設置image。
最後,當照片加載出來以後當然不能少了點擊查看相冊的功能啊!於是新建一個UIViewController類取名為:PhotoViewController,代碼如下:

  1. #import"PhotoViewController.h"
  2.  
  3. @interfacePhotoViewController()
  4.  
  5. @end
  6.  
  7. @implementationPhotoViewController
  8. @synthesizeheadView=_headView;
  9. @synthesizemainView=_mainView;
  10.  
  11.  
  12. -(id)initWithNibName:(NSString*)nibNameOrNilbundle:(NSBundle*)nibBundleOrNil
  13. {
  14. self=[superinitWithNibName:nibNameOrNilbundle:nibBundleOrNil];
  15. if(self){
  16. //Custominitialization
  17. }
  18. returnself;
  19. }
  20.  
  21. -(void)viewDidLoad
  22. {
  23. [superviewDidLoad];
  24. //Doanyadditionalsetupafterloadingtheview.
  25. [self.viewsetFrame:CGRectMake(0,0,MY_WIDTH,MY_HEIGHT)];
  26. [self.viewsetBackgroundColor:[UIColorblackColor]];
  27.  
  28. self.headView=[[UIViewalloc]initWithFrame:CGRectMake(0,0,MY_WIDTH,50)];
  29. UIButton*cancelBtn=[[UIButtonalloc]initWithFrame:CGRectMake(0,20,40,30)];
  30. [cancelBtnsetTitleColor:[UIColorwhiteColor]forState:UIControlStateNormal];
  31. [cancelBtnsetTitle:@"取消"forState:UIControlStateNormal];
  32. [self.headViewaddSubview:cancelBtn];
  33. [cancelBtnaddTarget:selfaction:@selector(closePhotoView)forControlEvents:UIControlEventTouchUpInside];
  34. [self.viewaddSubview:self.headView];
  35.  
  36. self.mainView=[[UIViewalloc]initWithFrame:CGRectMake(0,80,MY_WIDTH,MY_HEIGHT)];
  37. [self.viewaddSubview:self.mainView];
  38. }
  39.  
  40. -(void)viewWillAppear:(BOOL)animated{
  41. UIImageView*imageV=[selfcompressImage:MY_WIDTHimageName:_imageName];
  42. [self.mainViewaddSubview:imageV];
  43. }
  44.  
  45. -(UIImageView*)compressImage:(float)widthimageName:(NSString*)name{
  46. UIImageView*imgView=[[UIImageViewalloc]init];
  47. imgView.image=[UIImageimageNamed:name];
  48.  
  49. floatorgi_width=[imgViewimage].size.width;
  50. floatorgi_height=[imgViewimage].size.height;
  51.  
  52. //按照每列的寬度,以及圖片的寬高來按比例壓縮
  53. floatnew_width=width-5;
  54. floatnew_height=(width*orgi_height)/orgi_width;
  55.  
  56. //重置imageView的尺寸
  57. [imgViewsetFrame:CGRectMake(0,0,new_width,new_height)];
  58.  
  59. returnimgView;
  60. }
  61.  
  62. -(void)didReceiveMemoryWarning
  63. {
  64. [superdidReceiveMemoryWarning];
  65. //Disposeofanyresourcesthatcanberecreated.
  66. }
  67.  
  68. //關閉
  69. -(void)closePhotoView{
  70.  
  71. [self.viewremoveFromSuperview];
  72. }
  73.  
  74. -(void)dealloc{
  75. [self.headViewrelease];
  76. [self.mainViewrelease];
  77.  
  78. [superdealloc];
  79. }
  80.  
  81.  
  82. @end

 

這個類主要是用於顯示大圖片所用,用戶點擊小圖片後,程序根據圖片的tag來獲取點擊圖片的名字,然後將名字傳遞給該類,完成對相應圖片的顯示,當然這裡也要做對圖片的壓縮處理,使它顯示的時候不失真。(由於本人有點懶,這個類的界面美觀什麼的就懶得調了,多多包涵)示意圖如下:

 

\

 

以上就是這個例子的大部分代碼了,如果要下載完整工程的話,請到我的上傳中下載。

現在看一下整個效果;

\

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved