亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

詳解IOS中如何實現瀑布流效果

2020-07-26 03:16:57
字體:
來源:轉載
供稿:網友

首先是效果演示

特點:可以自由設置瀑布流的總列數(效果演示為2列)

雖然iphone手機的系統相冊沒有使用這種布局效果,瀑布流依然是一種很常見的布局方式!!!下面來詳細介紹如何實現這種布局.

首先使用的類是UICollectionView

我們要做的是自定義UICollectionViewCell和UICollectionViewLayout

     1、自定義UICollectionViewCell類,只需要一個UIImageView即可,frame占滿整個cell.

     2、重點是自定義UICollectionViewLayout,注意一定要繼承于UICollectionViewLayout,千萬別繼承于UIColletionViewFlowLayout.

     3、另外還需要計算圖片高度.

為什么要自定義UICollectionViewLayout ?

因為我們需要設置每個item的高度以及位置, 注意這里是位置, 我們真的會設置每個item的位置的相信我!!!自定義UICollectionViewLayout必須要重寫三個協議方法,后面會講到.

為什么要計算圖片高度 ?

因為圖片寬度固定,所以需要按照圖片的比例來計算高度,使圖片等比例顯示.這樣的好處是,媽媽再也不用擔心我的照片被拉伸的奇形怪狀了...而且還需要用圖片的高度來計算整個CollectionView的contentSize...打完收工!!!

主菜來了!!!

以下內容均在自定義的CustomCollectionViewLayout類里邊

//自定義UICollectionViewLayout必須要重寫的三個協議方法//1.計算每個item的大小和位置- (void)prepareLayout;//2.返回每個item的布局屬性- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;//3.返回collectionView的總高度- (CGSize)collectionViewContentSize;

可以看到第三個方法使用了Nullability和泛型,系統的方法都添加了iOS 9新特性。

通過上邊的三個方法名我們可以大致了解需要去做什么.說一下第二個方法,需要返回一個數組,數組存放布局屬性(UICollectionViewLayoutAttributes)對象.那么我們需要寫一個屬性數組(attributesArray),將布局屬性放入這個屬性數組并返回.

還需要什么呢 ?看了文章開頭的朋友應該注意到了,設置瀑布流的列數當然得有個屬性(numberOfColumns)來表示列數.

請注意,因為要在外部設置列數,所以這個屬性需要寫在自定義類的.h文件中

另外為了方便,定義一個屬性(itemWidth)來表示item的寬度

再定義一個屬性(contentHeight)來表示整個collectionView的contenView的高度

首先是初始化,并沒有什么問題

- (instancetype)init {  self = [super init];  if (self) {    _attributesArray = [NSMutableArray array];    // 默認值設置為2列    _numberOfColumns = 2;    _contentHeight = 0.0f;    _cellMargin = 5.0f;/**< 用來表示間距的屬性 */  }  return self;}

然后是getter方法,只需要使用點語法即可得到itemWidth的值(因為它就是固定的)

- (CGFloat)itemWidth {  //所有邊距的和.兩列時有三個邊距, 三列時有四個邊距,邏輯強大就是好...  CGFloat allMargin = (_numberOfColumns + 1) * _cellMargin;  //除去邊界之后的總寬度  CGFloat noMarginWidth = CGRectGetWidth(self.collectionView.bounds) - allMargin;  //出去邊距的總寬度除以列數得到每一列的寬度(也就是itemWidth)  return noMarginWidth / _numberOfColumns;}

---接下來是難點---

必須重寫的第一個方法

- (void)prepareLayout {  // 定義變量記錄高度最小的列,初始為第0列高度最小.#pragma mark - 注意這個是從0開始算的啊!!!  NSInteger shortestColumn = 0;#pragma mark - 注意這個是從0開始算的啊!!!  // 存儲每一列的總高度.因為添加圖片的列高度會變,所以需要定義一個數組來記錄列的總高度.  NSMutableArray *columnHeightArray = [NSMutableArray array];  // 設置列的初始高度為邊距的高度,沒毛病!!!  for (int i = 0; i < _numberOfColumns; i++) {    // 所有列初始高度均設置為cell的間距    [columnHeightArray addObject:@(_cellMargin)];  }  // 遍歷collectionView中第 0 區中的所有item  for (int i = 0; i < [self.collectionView numberOfItemsInSection:0]; i++) {    //需要用到這個玩意,提前拿到.    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];    // 創建系統需要的布局屬性對象,看后邊的參數就知道這就是每個item的布局屬性了    UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath: indexPath];    // 將布局屬性放入數組中,這個數組當然是一開始定義的布局屬性數組了    [_attributesArray addObject:layoutAttributes];    // 設置每個item的位置(x, y, width, height)    // 橫坐標的起始位置#pragma mark - 比如一共兩列,現在要放一張圖片上去,需要放到高度最小的那一列.#pragma mark - 假設第0列最短,那么item的x坐標就是從一個邊距寬度那里開始.#pragma mark - (itemWidth + cellMargin)為一個整體    CGFloat x = (self.itemWidth + _cellMargin) * shortestColumn + _cellMargin;    // 縱坐標就是 總高度數組 中最小列對應的高度#pragma mark - 圖片始終是添加在高度最小的那一列    CGFloat y = [columnHeightArray[column] floatValue];/**<注意類型轉換 */    // 寬度沒什么好說的    CGFloat width = self.itemWidth;#pragma mark - 這里給自定義的類聲明了一個協議,通過協議得到圖片的高度,調用時機就是需要item高度的時候#pragma mark - 將Item的寬度傳給代理人(ViewController),VC計算好高度后將高度返回給自定義類#pragma mark - 也就是↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓    CGFloat height = [self.delegate collectionView:self.collectionView                        layout:self                         width:self.itemWidth               heightForItemAtIndexPath:indexPath];    // 大功告成,設置item的位置信息,沒什么好說    layoutAttributes.frame = CGRectMake(x, y, width, height);    // 上邊廢了半天勁放了一個item上去了,總高度數組是不是該更新一下數據了    columnHeightArray[shortestColumn] = @([columnHeightArray[shortestColumn] floatValue] + height + _cellMargin);    // 整個內容的高度,通過比較得到較大值作為整個內容的高度    self.contentHeight = MAX(self.contentHeight, [columnHeightArray[shortestColumn] floatValue]);    // 剛才放了一個item上去,那么此時此刻哪一列的高度比較低呢    for (int i = 0; i < _numberOfColumns; i++) {      //當前列的高度(剛才添加item的那一列)      CGFloat currentHeight = [columnHeightArray[shortestColumn] floatValue];      // 取出第i列中存放列高度      CGFloat height = [columnHeightArray[i] floatValue];      if (currentHeight > height) {        //第i列高度(height)最低時,高度最低的列(shortestColumn)當然就是第i列了        shortestColumn = i;      }    }  }// 思考下只使用上邊的代碼會出現什么問題// 并不能影響心情,請不要恐慌...// 提示:這個方法會被多次調用,數組}

---難點已經結束---

沒有理解的朋友請重點看上邊的難點方法.

必須重寫的第二個方法

// 2.返回的是, 每個item對應的布局屬性- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {  return _attributesArray;}

必須重寫的第三個方法

// 3.返回CollectionView的滾動范圍- (CGSize)collectionViewContentSize {  return CGSizeMake(0, _contentHeight);}

ViewController里邊關于CollectionView的創建和協議方法就沒什么好說的了.

看下自定義類CustomCollectionViewLayout的創建以及屬性的賦值情況:

CustomCollectionViewLayout *layout = [[CustomCollectionViewLayout alloc] init];layout.numberOfColumns = 2;/**< 在ViewController里設置瀑布流的列數,2列或3列為最佳 */layout.delegate = self;/**< 指定VC為計算高度協議方法的代理人 */

再看下協議方法的實現部分(在ViewController.m中實現)

- (CGFloat)collectionView:(UICollectionView *)collectionView          layout:(UICollectionViewLayout *)collectionViewLayout          width:(CGFloat)width heightForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {  UIImage *image = _imagesArray[indexPath.row];  // 根據傳過來的寬度來設置一個合適的矩形, 高度設為CGFLOAT_MAX表示以寬度來計算高度  CGRect boundingRect = CGRectMake(0, 0, width, CGFLOAT_MAX);  // 通過系統函數來得到最終的矩形,需要引入頭文件  // #import <AVFoundation/AVFoundation.h>  CGRect imageCurrentRect = AVMakeRectWithAspectRatioInsideRect(image.size, boundingRect);  return imageCurrentRect.size.height;}

總結

到這里呢,在IOS實現瀑布流就算是結束了,有興趣的朋友可以自己動手試一下,希望本文對大家開發IOS有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91久久精品日日躁夜夜躁国产| 国语对白做受69| 欧美日韩国产在线播放| 亚洲一区二区三区四区在线播放| 国产精品吴梦梦| 亚洲成人动漫在线播放| 日韩**中文字幕毛片| 亚洲视频日韩精品| 日韩经典中文字幕| 亚洲激情小视频| www.久久撸.com| 丝袜亚洲欧美日韩综合| 亚洲精品日产aⅴ| 国产成人精品在线播放| 国产视频精品久久久| 久久亚洲春色中文字幕| 欧美精品在线看| 精品久久久久久久久久| 日韩中文在线观看| 亚洲情综合五月天| 亚洲有声小说3d| 91影院在线免费观看视频| 91精品国产免费久久久久久| 欧美极品少妇xxxxⅹ喷水| 国内精品视频久久| 亚洲qvod图片区电影| 日韩成人在线视频网站| 亚洲国产精品va| 亚洲欧美中文在线视频| 午夜精品一区二区三区在线| 伊人一区二区三区久久精品| 久久不射热爱视频精品| 精品国产自在精品国产浪潮| 国产一区二区三区久久精品| 人九九综合九九宗合| 综合av色偷偷网| 欧美性黄网官网| 狠狠躁18三区二区一区| 欧美在线观看网站| 久久精品久久久久电影| 亚洲国产女人aaa毛片在线| 亚洲第一精品自拍| 国内精品小视频在线观看| 午夜精品一区二区三区在线视频| 久久国产精品免费视频| 国产综合久久久久久| 成人免费视频网址| 一本色道久久综合狠狠躁篇的优点| 色妞欧美日韩在线| 久久国产精品视频| 色偷偷亚洲男人天堂| 欧美夫妻性生活xx| 欧美激情手机在线视频| 日本精品久久久久影院| 亚洲午夜精品视频| 日韩电视剧免费观看网站| 久久精品国产96久久久香蕉| 亚洲电影成人av99爱色| 国产精品久久久久久久久影视| 欧美与欧洲交xxxx免费观看| 国产亚洲福利一区| 国产成人97精品免费看片| 日韩精品视频在线| 菠萝蜜影院一区二区免费| 亚洲国产精久久久久久久| 久久久免费在线观看| 久久夜精品va视频免费观看| 国产精品伦子伦免费视频| 97在线视频免费观看| 亚洲欧美国产一本综合首页| 亚洲毛片在线免费观看| 亚洲深夜福利网站| 日韩av中文字幕在线免费观看| 国产精品永久在线| 亚洲大胆人体视频| 91精品在线国产| 日韩精品在线观看一区| 亚洲最大中文字幕| 欧美亚洲视频在线看网址| 欧美综合国产精品久久丁香| 亚洲午夜精品久久久久久久久久久久| 日韩成人激情影院| 俺去了亚洲欧美日韩| 久久影院在线观看| 日本午夜人人精品| 精品亚洲一区二区三区| 国产成+人+综合+亚洲欧洲| 国产区精品在线观看| 奇门遁甲1982国语版免费观看高清| 久久久电影免费观看完整版| 不卡av在线播放| 久久久久久久久久av| 日韩在线播放一区| 日韩av免费在线播放| 日韩av在线最新| 欧美性xxxxhd| 97色伦亚洲国产| 国产精品老女人视频| 欧美另类老肥妇| 国产日韩欧美在线| 日韩精品在线影院| 亚洲精品国产成人| 欧美日韩国产中文精品字幕自在自线| 日韩精品中文字幕有码专区| 日韩在线视频二区| 伊人久久免费视频| 国产精品第一第二| 欧美在线一级视频| 91日本视频在线| 日韩欧美国产高清91| 日韩精品日韩在线观看| 欧美大片va欧美在线播放| 日韩免费在线看| 欧美在线免费看| 51色欧美片视频在线观看| 欧美电影第一页| 亚洲精品欧美日韩专区| 中文字幕国产亚洲| 亚洲最大av网| 尤物99国产成人精品视频| 91超碰caoporn97人人| 精品伊人久久97| 色综合久久久888| 亚洲欧美国产精品va在线观看| 久久偷看各类女兵18女厕嘘嘘| 国产亚洲精品成人av久久ww| 国产日韩中文字幕在线| 国产精品永久免费在线| 欧美日韩在线另类| 欧洲精品久久久| 亚洲午夜精品久久久久久久久久久久| 成人中心免费视频| 色伦专区97中文字幕| 国产一区欧美二区三区| 8x拔播拔播x8国产精品| 欧美黄色片在线观看| 国产精品精品视频一区二区三区| 中文字幕日本欧美| 欧美日韩人人澡狠狠躁视频| 久久国产视频网站| 日韩成人av一区| 亚洲护士老师的毛茸茸最新章节| 国产欧美日韩中文字幕在线| 中文字幕视频在线免费欧美日韩综合在线看| 国模私拍一区二区三区| 欧美电影院免费观看| 国产视频一区在线| 亚洲欧洲自拍偷拍| 亚洲精品国产精品国自产观看浪潮| 91精品国产一区| 亚洲精品一二区| 国产精品一区二区三区久久| 亚洲一二三在线| 亚洲综合精品一区二区| 亚洲国产精品一区二区三区| 国产精品91免费在线| 成人h猎奇视频网站| 久久久久久久999| 韩国19禁主播vip福利视频| 久久精品99久久久久久久久| 成人黄色免费片| 亚洲欧美一区二区三区情侣bbw| 96精品久久久久中文字幕| 亚洲深夜福利视频|