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

首頁 > 學院 > 開發設計 > 正文

iOS開發之窺探UICollectionViewController(五)--一款炫酷的圖片瀏覽組件

2019-11-14 18:09:07
字體:
來源:轉載
供稿:網友

  本篇博客應該算的上CollectionView的高級應用了,從iOS開發之窺探UICollectionViewController(一)到今天的(五),可謂是由淺入深的窺探了一下UICollectionView的用法,這些用法不僅包括SDK中自帶的流式布局(UICollectionViewDelegateFlowLayout)而且介紹了如何根據你的需求去自定義屬于你自己的CollectionView。自定義的CollectionView可謂是非常靈活,其靈活性也決定了其功能的強大。CollectionView的自定義就是其Cell高度可定制的屬性,通過對Cell賦值不同的屬性來達到自定義的目的。

  在上篇博客iOS開發之窺探UICollectionViewController(四) --一款功能強大的自定義瀑布流中,通過自定義的CollectionView創建了一個可定制的自定義瀑布流,效果還是蠻ok的。本篇博客是使用自定義CollectionView的另一個實例,自定義CollectionView的方式和上一篇是一致的,都是重寫UICollectionViewLayout相應的方法,然后再通過委托回調來設置布局的參數。自定義CollectionView的思路是一樣的,只是具體的實現方式不同。學習么,要學會舉一反三,希望大家能通過這兩篇自定義CollectionView的博客來寫出屬于你自己的自定義效果。

  一.效果展示

  廢話少說,進入今天博客的主題,下方就是今天博客中Demo的運行效果。雖然運行效果做成gif丟幀了,看起來有些卡,不過跑起來還是比較流暢的。切換圖片時進行一個360度的旋轉,并且修改Cell的層級,當前顯示的圖片層級最高。并且移動時,如果要顯示的圖片不在屏幕中央就做一個位置矯正。點擊圖片時,使用仿射變換使其放大,再點擊使其縮小。接下來將會詳細的介紹其實現方案。

  二.該自定義布局的使用方式

    我們先看一下該自定義布局是如何使用的,然后再通過使用方式來逐步介紹它是如何實現的。這也是一個由淺入深的過程,因為用起來要比做起了更容易。比如開汽車容易,造汽車可就麻煩多了。所以在本篇博客的第二部分,將要介紹如何去使用該自定義組件。

    其實所有CollectionView的自定義布局的使用方式都是一樣的,分為以下幾步:

    1.為我們的CollectionView指定該布局,本篇博客的CollectionView是通過Storyboard來實現的,所以我們可以通過Storyboard來指定自定義的布局文件,如果你是使用純代碼方式,可以在CollectionView實例化時來指定所需的布局。下方是使用Storyboard來指定的布局文件,需要把Layout選項調到Custom下,然后下方的Class選項就是你要關聯的自定義布局文件,具體如下所示。代碼的就在此不做贅述了,網上一抓一大把。

 

    2.給Storyboard上的CollectionViewController關聯一個類,然后我們就可以使用自定義的布局了。獲取指定的自定義布局對象,然后指定委托代理對象,如下所示:

1 - (void)viewDidLoad {2     [super viewDidLoad];3     4     _customeLayout = (CustomTransformCollecionLayout *) self.collectionViewLayout;5     _customeLayout.layoutDelegate = self;6 }

 

    3.除了實現CollectionView的DataSource和Delegate, 我們還需實現布局的代理方法,該自定義布局要實現的代理方法如下。第一個是設置Cell的大小,也就是寬高。第二個是設置Cell間的邊距。

 1 #PRagma mark <CustomTransformCollecionLayoutDelegate> 2  3 - (CGSize)itemSizeWithCollectionView:(UICollectionView *)collectionView 4                  collectionViewLayout:(CustomTransformCollecionLayout *)collectionViewLayout { 5     return CGSizeMake(200, 200); 6 } 7  8 - (CGFloat)marginSizeWithCollectionView:(UICollectionView *)collectionView 9                     collectionViewLayout:(CustomTransformCollecionLayout *)collectionViewLayout {10     return 10.0f;11 }

 

  4.點擊Cell放大和縮小是在UICollectionViewDataSource中點擊Cell的代理方法中做的,在此就不做贅述了,詳見GitHub上分享的鏈接。

 

  三. 如何實現

    上面介紹了如何去使用該自定義組件,接下來就是“造車”的過程了。本篇博客的第三部分介紹如何去實現這個自定義布局。

    1. CustomTransformCollecionLayout頭文件中的代碼如下所示,該文件中定義了一個協議,協議中的方法就是在CollectionView中要實現的那兩個代理方法。這些代理方法提供了Cell的大小和邊距。該文件的接口中定義了一個代理對象,當然為了強引用循環,該代理對象是weak類型的。

 1 // 2 //  CustomTransformCollecionLayout.h 3 //  CustomTransformCollecionLayout 4 // 5 //  Created by Mr.LuDashi on 15/9/24. 6 //  Copyright (c) 2015年 ZeluLi. All rights reserved. 7 // 8  9 #import <UIKit/UIKit.h>10 11 #define SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.width12 #define SCREEN_HEIGHT [[UIScreen mainScreen] bounds].size.height13 14 @class CustomTransformCollecionLayout;15 16 @protocol CustomTransformCollecionLayoutDelegate <NSObject>17 /**18  * 確定cell的大小19  */20 - (CGSize) itemSizeWithCollectionView:(UICollectionView *)collectionView21                  collectionViewLayout:(CustomTransformCollecionLayout *)collectionViewLayout;22 23 /**24  * 確定cell的大小25  */26 - (CGFloat) marginSizeWithCollectionView:(UICollectionView *)collectionView27                  collectionViewLayout:(CustomTransformCollecionLayout *)collectionViewLayout;28 29 @end30 31 @interface CustomTransformCollecionLayout : UICollectionViewLayout32 33 @property (nonatomic, weak) id<CustomTransformCollecionLayoutDelegate> layoutDelegate;34 35 @end

 

    2.接下來介紹一下CustomTransformCollecionLayout實現文件也就是.m中的代碼,其中的延展中的屬性如下所示。numberOfSections:該參數代表著CollectionView的Section的個數。numberOfCellsInSection:代表著每個Section中Cell的個數。itemSize則是Cell的尺寸(寬高),該屬性的值是由布局代理方法提供。itemMargin: 該屬性是Cell的邊距,它也是通過布局的代理方法提供。itemsX: 用來存儲計算的每個Cell的X坐標。

 1 // 2 //  CustomTransformCollecionLayout.m 3 //  CustomTransformCollecionLayout 4 // 5 //  Created by Mr.LuDashi on 15/9/24. 6 //  Copyright (c) 2015年 ZeluLi. All rights reserved. 7 // 8  9 #import "CustomTransformCollecionLayout.h"10 11 @interface CustomTransformCollecionLayout()12 13 @property (nonatomic) NSInteger numberOfSections;14 @property (nonatomic) NSInteger numberOfCellsInSection;15 @property (nonatomic) CGSize itemSize;16 @property (nonatomic) CGFloat itemMargin;18 @property (nonatomic, strong) NSMutableArray *itemsX;19 20 @end

 

    3. 在實現中我們需要重寫UICollectionViewLayout中相關的方法,需要重寫的方法如下:

    (1). 預加載布局方法, 該方法會在UICollectionView加載數據時執行一次,在該方法中負責調用一些初始化函數。具體如下所示。

1 #pragma mark -- UICollectionViewLayout 重寫的方法2 - (void)prepareLayout {3     [super prepareLayout];4     5     [self initData];6     7     [self initItemsX];8 }

 

    (2).下面的方法會返回ContentSize, 說白一些,就是CollectionView滾動區域的大小。

1 /**2  * 該方法返回CollectionView的ContentSize的大小3  */4 - (CGSize)collectionViewContentSize {5     CGFloat width = _numberOfCellsInSection * (_itemSize.width + _itemMargin);6     return CGSizeMake(width,  SCREEN_HEIGHT);7 }

 

    (3).下方的方法是為每個Cell綁定一個UICollectionViewLayoutAttributes對象,用來設置每個Cell的屬性。

 1 /** 2  * 該方法為每個Cell綁定一個Layout屬性~ 3  */ 4 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { 5      6     NSMutableArray *array = [NSMutableArray array]; 7      8     //add cells 9     for (int i = 0; i < _numberOfCellsInSection; i++) {10         NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];11         12         UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];13         14         [array addObject:attributes];15     }16     return array;17 }

  

    (4).下方這個方法是比較重要的,重寫這個方法是為了為每個Cell設定不同的屬性值。其中transform的值是根據CollectionView的滾動偏移量來計算的,所以在滾動CollectionView時,Cell也會跟著旋轉。具體的實現方案在代碼中添加了注釋,如下所示:

 1 /** 2  * 為每個Cell設置attribute 3  */ 4 - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{ 5      6     //獲取當前Cell的attributes 7     UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 8      9     //獲取滑動的位移10     CGFloat contentOffsetX = self.collectionView.contentOffset.x;11     //根據滑動的位移計算當前顯示的時第幾個Cell12     NSInteger currentIndex = [self countIndexWithOffsetX: contentOffsetX];13     //獲取Cell的X坐標14     CGFloat centerX = [_itemsX[indexPath.row] floatValue];15     //計算Cell的Y坐標16     CGFloat centerY = SCREEN_HEIGHT/2;17     18     //設置Cell的center和size屬性19     attributes.center = CGPointMake(centerX, centerY);20     attributes.size = CGSizeMake(_itemSize.width, _itemSize.height);21 22     //計算當前偏移量(滑動后的位置 - 滑動前的位置)23     CGFloat animationDistance = _itemSize.width + _itemMargin;24     CGFloat change = contentOffsetX - currentIndex * animationDistance + SCREEN_WIDTH / 2 - _itemSize.width / 2;25     26     //做一個位置修正,因為當滑動過半時,currentIndex就會加一,就不是上次顯示的Cell的索引,所以要減去一做個修正27     if (change < 0) {28         change = contentOffsetX - (currentIndex - 1) * animationDistance + SCREEN_WIDTH/2 - _itemSize.width/2;29     }30     31     if (currentIndex == 0 && contentOffsetX <= 0) {32         change = 0;33     }34     35     //旋轉量36     CGFloat temp = M_PI * 2 * (change / (_itemSize.width + _itemMargin));37     38     //仿射變換 賦值39     attributes.transform = CGAffineTransformMakeRotation(temp);40     41     //把當前顯示的Cell的zIndex設置成較大的值42     if (currentIndex == indexPath.row) {43         attributes.zIndex = 1000;44     } else {45         attributes.zIndex = currentIndex;46     }47     48     return attributes;49 }
View Code

 

    (5).要讓Cell隨著滾動旋轉起來,你需要重寫下面這個方法,并且返回YES。該方法返回YES意味著當滾動時,會再次執行上面(4)的方法,重新為每個Cell的屬性賦值。所以重寫下面的方法,并返回YES(下面的表達式也是一樣的)才可以運動起來呢。

1 //當邊界發生改變時,是否應該刷新布局。如果YES則在邊界變化(一般是scroll到其他地方)時,將重新計算需要的布局信息。2 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {3     return !CGRectEqualToRect(newBounds, self.collectionView.bounds);4 }

 

    (6).重寫下面的方法是為了修正CollectionView滾動的偏移量,使當前顯示的Cell出現在屏幕的中心的位置,方法如下:

 1 //修正Cell的位置,使當前Cell顯示在屏幕的中心 2 - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{ 3      4      5     //計算顯示的是第幾個Cell 6     NSInteger index = [self countIndexWithOffsetX:proposedContentOffset.x]; 7      8     CGFloat centerX = index * (_itemSize.width + _itemMargin) + (_itemSize.width/2); 9     10     proposedContentOffset.x = centerX - SCREEN_WIDTH/2;11     12     return proposedContentOffset;13 }
View Code

 

    4.下方就是我自己實現的方法了,也就在重寫的方法中調用的函數,具體如下。

 1 #pragma mark -- 自定義的方法 2 /** 3  * 根據滾動便宜量來計算當前顯示的時第幾個Cell 4  */ 5 - (NSInteger) countIndexWithOffsetX: (CGFloat) offsetX{ 6     return (offsetX + (SCREEN_WIDTH / 2)) / (_itemSize.width + _itemMargin); 7 } 8  9 /**10  * 初始化私有屬性,通過代理獲取配置參數11  */12 - (void) initData{13     _numberOfSections = self.collectionView.numberOfSections;14     15     _numberOfCellsInSection = [self.collectionView numberOfItemsInSection:0];16 17     _itemSize = [_layoutDelegate itemSizeWithCollectionView:self.collectionView collectionViewLayout:self];18     19     _itemMargin = [_layoutDelegate marginSizeWithCollectionView:self.collectionView collectionViewLayout:self];20     21 }22 23 /**24  * 計算每個Cell的X坐標25  */26 - (void) initItemsX{27     _itemsX = [[NSMutableArray alloc] initWithCapacity:_numberOfCellsInSection];28     29     for (int i = 0; i < _numberOfCellsInSection; i ++) {30         CGFloat tempX = i * (_itemSize.width + _itemMargin) + _itemSize.width/2;31         [_itemsX addObject:@(tempX)];32     }33     34     35 }

 

  至此,Demo的代碼講解完畢,經過上述步驟,你就可以寫出上面動畫中的自定義效果了,具體代碼會在github中進行分享。分享鏈接如下:

  github上Demo的鏈接地址:https://github.com/lizelu/CustomTransformCollecionLayout


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国内精品免费午夜毛片| 久久亚洲精品国产亚洲老地址| 韩国福利视频一区| 欧美日韩一区二区在线播放| 欧美激情一区二区三区成人| 日韩影视在线观看| 91sao在线观看国产| 96精品久久久久中文字幕| 成人午夜激情免费视频| 精品视频久久久久久| 日韩中文字幕视频| 亚洲国产天堂网精品网站| 国产成人91久久精品| 欧美乱妇高清无乱码| 欧美一级大胆视频| 国产亚洲精品高潮| 欧美视频免费在线| 精品视频一区在线视频| 久久久噜噜噜久久久| 国产精品18久久久久久首页狼| 日韩一二三在线视频播| 国产色视频一区| 日本久久久久亚洲中字幕| 中文字幕亚洲图片| 精品国产乱码久久久久久天美| 国产精品久久二区| 97超碰国产精品女人人人爽| 欧美性生交xxxxx久久久| 亚洲片在线资源| 国产99久久精品一区二区| 亚洲欧美国产日韩中文字幕| 久久亚洲精品一区二区| 国产suv精品一区二区| 成人av番号网| 欧美在线视频免费播放| 亚洲剧情一区二区| 国产精品美乳在线观看| 亚洲v日韩v综合v精品v| 国产精品一区二区三区毛片淫片| 88xx成人精品| 国产成人涩涩涩视频在线观看| 欧美丰满少妇xxxx| 最新亚洲国产精品| 亚洲人a成www在线影院| 欧美成人精品一区| 久久视频在线免费观看| 欧美亚洲另类制服自拍| 欧美日韩中文在线观看| 久久久人成影片一区二区三区| 欧美日韩国产精品| 久久久久久av| 成人福利网站在线观看11| 精品国产精品三级精品av网址| 国产精品久久二区| 中文字幕精品www乱入免费视频| 国内揄拍国内精品少妇国语| 成人淫片在线看| 一区二区福利视频| 成人欧美一区二区三区在线| 欧美视频中文在线看| 久久久久九九九九| 亚洲第一二三四五区| 2024亚洲男人天堂| 久久青草福利网站| 亚洲成人a级网| 日韩精品视频免费专区在线播放| 亚洲午夜精品视频| 欧美精品久久久久a| 国产99久久久欧美黑人| 欧美黑人巨大xxx极品| 国产高清视频一区三区| 成人性教育视频在线观看| 福利一区福利二区微拍刺激| 欧美激情视频一区| 日韩精品视频中文在线观看| 在线观看日韩欧美| 久久久久久久一区二区三区| 欧美午夜视频一区二区| 欧美亚洲激情视频| 国产精品日韩电影| 欧美成在线视频| 热久久这里只有精品| 精品女同一区二区三区在线播放| 午夜精品理论片| 欧美激情性做爰免费视频| 日本中文字幕不卡免费| 国产精品www| 国产99久久精品一区二区永久免费| 91精品国产高清自在线看超| 日韩电影网在线| 亚洲精品久久久久中文字幕欢迎你| 午夜精品久久久久久久久久久久久| 91久久国产婷婷一区二区| 美女精品视频一区| 91嫩草在线视频| 日本道色综合久久影院| 欧美最顶级丰满的aⅴ艳星| 日韩av色在线| 久久久久久久久久久免费精品| 亚洲精品一区久久久久久| 国产欧美精品xxxx另类| 日本aⅴ大伊香蕉精品视频| 国产日韩欧美日韩| 国产精品一区专区欧美日韩| 亚洲性69xxxbbb| 久久影视三级福利片| 亚洲精品aⅴ中文字幕乱码| 欧美日韩在线视频首页| 91精品视频大全| 精品在线小视频| 国产精品9999| 国产区亚洲区欧美区| 欧美日韩在线看| 精品国产区一区二区三区在线观看| 亚洲女人被黑人巨大进入al| 国产97在线|亚洲| 一区二区三区无码高清视频| 在线观看日韩视频| 亚洲欧美变态国产另类| 97国产精品视频人人做人人爱| 97精品国产91久久久久久| 在线看片第一页欧美| 精品中文字幕久久久久久| 岛国精品视频在线播放| 亚洲女人被黑人巨大进入al| 亚洲第一视频网| 国产精品美女网站| 亚洲另类激情图| 日本国产一区二区三区| 亚洲欧美日韩国产中文| 亚洲人精品午夜在线观看| 精品福利在线观看| 8x海外华人永久免费日韩内陆视频| 日本欧美黄网站| 久久精品久久久久久| 日本亚洲欧洲色α| 久久久噜噜噜久噜久久| 夜夜嗨av色一区二区不卡| 国产日韩欧美日韩大片| 国产成人精品午夜| 成人激情视频在线观看| 日本高清视频精品| 亚洲国产成人久久综合| 亚洲综合日韩中文字幕v在线| 97超级碰碰碰久久久| 日韩欧美在线免费观看| 国产精品高潮在线| 亚洲老司机av| 午夜精品一区二区三区在线| 91tv亚洲精品香蕉国产一区7ujn| 亚洲理论在线a中文字幕| 色综合天天综合网国产成人网| 一区二区日韩精品| 久久免费少妇高潮久久精品99| 久久伊人精品视频| 日韩欧美国产高清91| 亚洲午夜色婷婷在线| 欧美日本在线视频中文字字幕| 91精品综合久久久久久五月天| 欧美亚洲视频在线观看| 亚洲免费伊人电影在线观看av| 国产精品第七十二页| 日韩av一区在线观看| 91最新国产视频|