自定義UICollectionViewLayout實現瀑布流
該瀑布流的列數,列與列,行與行,距離四周的間距均通過代理由外界傳入
// // ViewController.m // PuBuFlow // // Created by hq on 16/5/11. // Copyright © 2016年 hanqing. All rights reserved. // #import "ViewController.h" #import "HQFlowLayout.h" #import "HQCollectionViewCell.h" #import <MJRefresh.h> #import <MJExtension.h> #import "HQShop.h" @interface ViewController () <UICollectionViewDataSource,HQFlowLayoutDelegate> @property(nonatomic,strong) NSMutableArray *goodsArrays; @property(nonatomic,weak) UICollectionView *collectionView; @end static NSString * const
[email protected]"flow_cell"; @implementation ViewController -(NSMutableArray *)goodsArrays{ if (_goodsArrays==nil) { _goodsArrays=[NSMutableArray array]; } return _goodsArrays; } - (void)viewDidLoad { [super viewDidLoad]; [self setUpCollection]; [self setUpRefresh]; } -(void) setUpCollection{ HQFlowLayout *flow=[[HQFlowLayout alloc]init]; flow.delegate=self; UICollectionView *collectionView=[[UICollectionView alloc]initWithFrame:self.view.frame collectionViewLayout:flow]; collectionView.backgroundColor=[UIColor whiteColor]; collectionView.dataSource=self; [collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([HQCollectionViewCell class]) bundle:nil] forCellWithReuseIdentifier:cellID]; [self.view addSubview:collectionView]; self.collectionView=collectionView; } -(void) setUpRefresh{ //建立下拉重新整理 self.collectionView.mj_header=[MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; [self.collectionView.mj_header beginRefreshing]; //建立上拉重新整理 self.collectionView.mj_footer=[MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; } -(void) loadNewData{ [self.goodsArrays removeAllObjects]; NSMutableArray *array=[HQShop mj_objectArrayWithFilename:@"1.plist"]; [self.goodsArrays addObjectsFromArray:array]; [self.collectionView reloadData]; [self.collectionView.mj_header endRefreshing]; } -(void) loadMoreData{ NSMutableArray *array=[HQShop mj_objectArrayWithFilename:@"1.plist"]; [self.goodsArrays addObjectsFromArray:array]; [self.collectionView reloadData]; [self.collectionView.mj_footer endRefreshing]; } -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return self.goodsArrays.count; } -(UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ HQShop *shop=self.goodsArrays[indexPath.item]; HQCollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath]; cell.shop=shop; return cell; } #pragma mark 我們自定義的瀑布流HQFlowLayout當中的代理實現方法 //設定每個cell的高度 -(CGFloat)flowLayout:(HQFlowLayout *)flowLayout heightForItemAtIndex:(NSInteger)index itemWidth:(CGFloat)itemWidth{ HQShop *shop=self.goodsArrays[index]; //返回高度 return shop.h*itemWidth/shop.w; } //設定cell的列數 -(CGFloat)columNumbersFlowLayout:(HQFlowLayout *)flowLayout{ return 3; } //設定行與行之間的間距 -(CGFloat)rowMarginFlowLayout:(HQFlowLayout *)flowLayout{ return 10; } //設定列與列之間的間距 -(CGFloat)colMarginFlowLayout:(HQFlowLayout *)flowLayout{ return 10; } //設定四周邊緣的距離 -(UIEdgeInsets)edgeIndsetsFlowLayout:(HQFlowLayout *)flowLayout{ UIEdgeInsets sets=UIEdgeInsetsMake(10, 10, 10, 10); return sets; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end
核心方法如下
// // HQFlow.h // PuBuFlow // // Created by hq on 16/5/11. // Copyright © 2016年 hanqing. All rights reserved. // #import <UIKit/UIKit.h> @class HQFlowLayout; @protocol HQFlowLayoutDelegate <NSObject> @required //返回每行的高度 -(CGFloat) flowLayout:(HQFlowLayout *) flowLayout heightForItemAtIndex:(NSInteger) index itemWidth:(CGFloat) itemWidth; @optional //返回列數 -(CGFloat) columNumbersFlowLayout:(HQFlowLayout *) flowLayout; //返回行與行之間的間距 -(CGFloat) rowMarginFlowLayout:(HQFlowLayout *) flowLayout; //返回列與列之間的間距 -(CGFloat) colMarginFlowLayout:(HQFlowLayout *) flowLayout; //設定距離邊緣四周的距離 -(UIEdgeInsets) edgeIndsetsFlowLayout:(HQFlowLayout *) flowLayout; @end @interface HQFlowLayout : UICollectionViewLayout @property(nonatomic,weak) id<HQFlowLayoutDelegate> delegate; @end
//
// HQFlow.m
// PuBuFlow
//
// Created by hq on 16/5/11.
// Copyright © 2016年 hanqing. All rights reserved.
//
#import "HQFlowLayout.h"
#import <MJExtension.h>
#import <MJRefresh.h>
@interface HQFlowLayout()
@property(nonatomic,strong) NSMutableArray *dataArrays;
@property(nonatomic,strong) NSMutableArray *colHeightArrays;
@end
@implementation HQFlowLayout
//有3列
static NSInteger colNumber=3;
//每行之間的間距
static CGFloat rowMargin=10;
//每列之間的間距
static CGFloat colMargin=10;
//距離邊緣的間距
static UIEdgeInsets boderInsets={10,10,10,10};
#pragma mark 懶載入
-(NSMutableArray *)dataArrays{
if (_dataArrays==nil) {
_dataArrays=[NSMutableArray array];
}
return _dataArrays;
}
//儲存每行的高度
-(NSMutableArray *)colHeightArrays{
if (_colHeightArrays==nil) {
_colHeightArrays=[NSMutableArray array];
}
return _colHeightArrays;
}
#pragma mark 通過代理獲取屬性,獲取不到,則使用預設值
//獲取列數
-(NSInteger) getColumNumber{
if ([self.delegate respondsToSelector:@selector(columNumbersFlowLayout:)]) {
return [self.delegate columNumbersFlowLayout:self];
}
//沒有設定則用預設值
return colNumber;
}
//獲取行與行之間的間距
-(CGFloat) getRowMargin{
if ([self.delegate respondsToSelector:@selector(rowMarginFlowLayout:)]) {
return [self.delegate rowMarginFlowLayout:self];
}
//沒有設定則用預設值
return rowMargin;
}
//獲取列與列之間的間距
-(CGFloat) getColMargin{
if ([self.delegate respondsToSelector:@selector(colMarginFlowLayout:)]) {
return [self.delegate colMarginFlowLayout:self];
}
//沒有設定則用預設值
return colMargin;
}
-(UIEdgeInsets) getEdgeInsets{
if ([self.delegate respondsToSelector:@selector(edgeIndsetsFlowLayout:)]) {
return [self.delegate edgeIndsetsFlowLayout:self];
}
//沒有設定則用預設值
return boderInsets;
}
//初始化操作,必須寫super prepareLayout
//每次表格reloaddata,都會呼叫該方法
-(void)prepareLayout{
[self.dataArrays removeAllObjects];
[self.colHeightArrays removeAllObjects];
[super prepareLayout];
NSLog(@"%s",__func__);
//初始化我們每個col的高度,預設為距離頂部的高度
for (int i=0; i<[self getColumNumber]; i++) {
[self.colHeightArrays addObject:@([self getEdgeInsets].top)];
}
NSInteger cellCount=[self.collectionView numberOfItemsInSection:0];
//初始化我們所有cell屬性的陣列
for (int i=0; i<cellCount; i++) {
NSIndexPath *indexpath=[NSIndexPath indexPathForItem:i inSection:0];
UICollectionViewLayoutAttributes *attr=[self layoutAttributesForItemAtIndexPath:indexpath];
[self.dataArrays addObject:attr];
}
}
//所有元素的屬性
//該方法,每滾動一次就會被呼叫一次,因此我們把陣列的初始化放到preparelayout當中去
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
return self.dataArrays;
}
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewLayoutAttributes *attr=[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
CGFloat w=(self.collectionView.bounds.size.width-[self getColMargin]*([self getColumNumber]-1)-[self getEdgeInsets].left-[self getEdgeInsets].right)/[self getColumNumber];
// CGFloat h=arc4random_uniform(100)+80;
//通過代理方法獲取高度
CGFloat h=[self.delegate flowLayout:self heightForItemAtIndex:indexPath.item itemWidth:w];
//接下來計算哪個列最短
CGFloat minHeight=[self.colHeightArrays[0] doubleValue];
NSInteger minCol=0;
for (int i=1; i<[self getColumNumber]; i++) {
CGFloat currentHeight=[self.colHeightArrays[i] doubleValue];
if (currentHeight<minHeight) {
minCol=i;
minHeight=currentHeight;
}
}
CGFloat x=[self getEdgeInsets].left+(w+[self getColMargin])*minCol;
CGFloat y=minHeight+[self getRowMargin];
attr.frame=CGRectMake(x, y, w, h);
self.colHeightArrays[minCol][email protected](CGRectGetMaxY(attr.frame));
return attr;
}
-(CGSize)collectionViewContentSize{
//取出我們的最大高度
CGFloat maxHeight=[self.colHeightArrays[0] doubleValue];
for (int i=1; i<[self getColumNumber]; i++) {
CGFloat currentHeight=[self.colHeightArrays[i] doubleValue];
if (currentHeight>maxHeight) {
maxHeight=currentHeight;
}
}
return CGSizeMake(0, maxHeight);
}
@end
相關推薦
iOS 自定義UICollectionViewLayout實現瀑布流
前言hihi,勇敢的小夥伴兒們大家好,很高興今天又能更新了,首先照例說一下學習這個瀑布流的人生感悟(一本正經)。在2015年的時候我已經瞭解瀑布流這個概念了,也知道可以用UICollectionView來實現,但是有意思的是我從業幾年來,從未在專案中真正實踐過,所以我就一!直
自定義UICollectionViewLayout實現瀑布流佈局
移動端訪問不佳,請訪問我的個人部落格 最近專案中需要用到瀑布流的效果,但是用UICollectionViewFlowLayout又達不到效果,自己動手寫了一個瀑布流的layout,下面是我的心路路程 因為是用UICollectionView來
自定義UICollectionViewLayout實現瀑布流
該瀑布流的列數,列與列,行與行,距離四周的間距均通過代理由外界傳入 // // ViewController.m // PuBuFlow // // Created by hq on 16/5/11. // Copyright © 2016年 hanqing.
自定義ViewGroup實現瀑布流效果
今天情人節,我卻在家裡看書寫程式碼,真屌絲啊哈~ 回顧:ViewGroup的時間分發流程: dispatchTouchEvent ----- onInterceptTouchEvent----- onTouchEvent 最外層的ViewGroup首先接收到觸控事件,然後
詳細分享UICollectionView的自定義布局(瀑布流, 線性, 圓形...)
init hide 屬性 png 繼承 del 屏幕旋轉 結束 效果 前言: 本篇文章不是分享collectionView的詳細使用教程, 而是屬於比較‘高級‘的collectionView使用技巧, 閱讀之前, 我想你已經很熟悉collectionView的基本使用,
Xamarin自定義佈局系列——瀑布流佈局
原文: Xamarin自定義佈局系列——瀑布流佈局 Xamarin.Forms以Xamarin.Android和Xamarin.iOS等為基礎,自己實現了一整套比較完整的UI框架,包含了絕大多數常用的控制元件,如下圖 雖然XF(Xamarin.Forms簡稱XF,下同)為我們提供大這麼多的控制元件,但在
pig自定義FilterFunc實現資料流的過濾
假設test.txt檔案中有如下資料: xiaojun 28 shanghai yangna 24 lanzhou yangna 24 shanghai xiaojun 28 上海 想實現過濾其中為上海的資料。我們可以寫 : a
iOS自定義UICollectionViewLayout佈局實現瀑布流
自定義 UICollectionViewLayout 佈局,實現瀑布流;UICollectionView和UICollectionViewCell 另行建立,這只是佈局檔案, 外界控制器只要遵守協議併成為他的代理並實現代理方法heightForItemAtIndex:返回每個cell的高
RecyclerView自定義LayoutManager實現橫向瀑布流
最近由於公司專案需要,做了一個橫向瀑布流的元件,如下圖;這個元件是通過自定義LayoutManager實現,LayoutManager為我們提供了強大的自定義功能,但是實現過程卻不簡單,搗鼓了兩天,也就算基本可以用了;Demo原始碼在最下面,這裡主要記錄一些自定義Layou
瀑布流(自定義佈局實現)
這篇文章主要分享如何用自定義佈局來實現瀑布流,關於瀑布流的其他實現方式可以參考我的另一篇文章 瀑布流(UIScrollView實現),利用UICollectionView實現瀑布流有個非常大的好處就是我們不用關心重用機制,只把注重點放在如何自定義佈局來排布每一個
javascript自適應寬度的瀑布流實現思路
這裡主要介紹瀑布流的一種實現方法:絕對定位(css)+javascript+ajax+json。簡單一點如果不做滾動載入的話就是絕對定位(css)+javascript了,ajax和json是滾動載入更多內容的時候用到的,感興趣的你可以參考下哦 這樣的佈局並不陌生,從2011年Pinter
android自定義View實現流式佈局
//先來一張效果圖 //自定義的控制元件 import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.
[置頂] RecyclerView實現瀑布流,圖片自適應高度
話不多說,先上效果圖 對於RecyclerView,相信大家都不陌生了,這個集listView,GridView,瀑布流效果與一身強大控制元件,漸漸地滲透在每個App.... 還是回到正題,如何讓RecyclerView裡的圖片自適應高度? 我們知道,要讓RecyclerView有瀑布流效果,R
RecyclerView實現瀑布流,圖片自適應高度
話不多說,先上效果圖 對於RecyclerView,相信大家都不陌生了,這個集listView,GridView,瀑布流效果與一身強大控制元件,漸漸地滲透在每個App.... 還是回到正題,如何讓RecyclerView裡的圖片自適應高度? 我們知道,要讓Recycler
android 自定義view實現流式佈局
今天搞了一個流式佈局:如圖 網上也有部落格講這方面的,只是每個人實現思路不一樣,這是在網上看到一篇文章講這個,我看了下,說下這個怎麼實現原理,網上好多是直接繼承了ViewGroup,那樣的話就有個換行和計運算元view的大小.子view的排放位置,但是這個就省略了那麼多複
ratelimit+aop自定義註解實現應用限流
1、基於springboot專案pom.xml新增如下依賴: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sprin
js實現瀑布流
done title pos webkit for ria side 可能 src 下午查找了瀑布流的相關原理,找了一些css3實現的還有js實現的,最後總結了一些比較簡單的,易懂的整理起來 1.css3實現 只要運用到 column-count分列
【前端】用jQuery實現瀑布流效果
scrollto title n) 個性 避免 ive gets type turn jQuery實現瀑布流效果 何為瀑布流: 瀑布流,又稱瀑布流式布局。是比較流行的一種網站頁面布局,視覺表現為參差不齊的多欄布局,隨著頁面滾動條向下滾動,這種布局還會不斷加載數據塊並附加
Android -- 自定義view實現keep歡迎頁倒計時效果
super onfinish -m use new getc awt ttr alt 1,最近打開keep的app的時候,發現它的歡迎頁面的倒計時效果還不錯,所以打算自己來寫寫,然後就有了這篇文章。 2,還是老規矩,先看一下我們今天實現的效果 相較於我們常見的倒計時
Android自定義View——實現水波紋效果類似剩余流量球
string 三個點 pre ber block span 初始化 move 理解 最近突然手癢就想搞個貝塞爾曲線做個水波紋效果玩玩,終於功夫不負有心人最後實現了想要的效果,一起來看下吧: 效果圖鎮樓 一:先一步一步來分解一下實現的過程 需要繪制一個正弦曲線(sin