日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

UICollectionView——整体总结

發(fā)布時(shí)間:2023/12/10 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UICollectionView——整体总结 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

這幾天有時(shí)間看了下UICollectionView的東西,才發(fā)覺(jué)它真的非常強(qiáng)大,很有必要好好學(xué)習(xí)學(xué)習(xí)。以前雖然用過(guò)幾次,但沒(méi)有系統(tǒng)的整理總結(jié)過(guò)。這兩天我為UICollectionView做一個(gè)比較全面的整理。包括基本使用自定義布局自定義插入刪除動(dòng)畫(huà)自定義轉(zhuǎn)場(chǎng)動(dòng)畫(huà)等幾部分。好了,開(kāi)始。

UICollectionView相對(duì)于UITableView可以說(shuō)是青出于藍(lán)而勝于藍(lán),它和UITableView很相似,但它要更加強(qiáng)大。
UITableView的布局形式比較單一,局限于行列表,而UICollectionView的強(qiáng)大之處在于把視圖布局分離出來(lái)成為一個(gè)獨(dú)立的類,你想實(shí)現(xiàn)怎樣的視圖布局,就子類化這個(gè)類并在其中實(shí)現(xiàn)。

UICollectionView基礎(chǔ)

  • UICollectionViewFlowLayout:視圖布局對(duì)象(流視圖:一行排滿,自動(dòng)排到下行),繼承自UICollectionViewLayout。
    UICollectionViewLayout有個(gè)collectionView屬性,
    所有的視圖布局對(duì)象都繼承自UICollectionViewLayout。若我們要自定義布局對(duì)象,我們一般繼承UICollectionViewFlowLayout就可以了。
  • 需要實(shí)現(xiàn)三個(gè)協(xié)議;UICollectionViewDataSource(數(shù)據(jù)源)、UICollectionViewDelegateFlowLayout(視圖布局)、UICollectionViewDelegate。
    可以看得出,除了視圖布局,UICollectionView幾乎和UITableView一樣,但這也正是它的強(qiáng)大之處。
1.創(chuàng)建UICollectionView視圖
- (void)loadCollectionView {_customLayout = [[CustomCollectionViewLayout alloc] init]; // 自定義的布局對(duì)象_collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:_customLayout];_collectionView.backgroundColor = [UIColor whiteColor]; _collectionView.dataSource = self; _collectionView.delegate = self; [self.view addSubview:_collectionView]; // 注冊(cè)cell、sectionHeader、sectionFooter [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:cellId]; [_collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerId]; [_collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:footerId]; }

需要注意的是這幾行代碼的位置,及const的位置。(我經(jīng)常搞亂)

@implementation YWViewController// 注意const的位置 static NSString *const cellId = @"cellId"; static NSString *const headerId = @"headerId"; static NSString *const footerId = @"footerId"; - (void)viewDidLoad {
2.實(shí)現(xiàn)UICollectionViewDataSource的幾個(gè)代理方法
#pragma mark ---- UICollectionViewDataSource- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {return 1; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return _section0Array.count; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [_collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath]; cell.backgroundColor = [UIColor purpleColor]; return cell; } // 和UITableView類似,UICollectionView也可設(shè)置段頭段尾 - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { if([kind isEqualToString:UICollectionElementKindSectionHeader]) { UICollectionReusableView *headerView = [_collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:headerId forIndexPath:indexPath]; if(headerView == nil) { headerView = [[UICollectionReusableView alloc] init]; } headerView.backgroundColor = [UIColor grayColor]; return headerView; } else if([kind isEqualToString:UICollectionElementKindSectionFooter]) { UICollectionReusableView *footerView = [_collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:footerId forIndexPath:indexPath]; if(footerView == nil) { footerView = [[UICollectionReusableView alloc] init]; } footerView.backgroundColor = [UIColor lightGrayColor]; return footerView; } return nil; } - (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath { return YES; } - (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath { } #pragma mark ---- UICollectionViewDelegateFlowLayout - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return (CGSize){cellWidth,cellWidth}; } - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { return UIEdgeInsetsMake(5, 5, 5, 5); } - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { return 5.f; } - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { return 5.f; } - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { return (CGSize){ScreenWidth,44}; } - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section { return (CGSize){ScreenWidth,22}; } #pragma mark ---- UICollectionViewDelegate - (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath { return YES; } // 點(diǎn)擊高亮 - (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath]; cell.backgroundColor = [UIColor greenColor]; } // 選中某item - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { } // 長(zhǎng)按某item,彈出copy和paste的菜單 - (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath { return YES; } // 使copy和paste有效 - (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender { if ([NSStringFromSelector(action) isEqualToString:@"copy:"] || [NSStringFromSelector(action) isEqualToString:@"paste:"]) { return YES; } return NO; } // - (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender { if([NSStringFromSelector(action) isEqualToString:@"copy:"]) { // NSLog(@"-------------執(zhí)行拷貝-------------"); [_collectionView performBatchUpdates:^{ [_section0Array removeObjectAtIndex:indexPath.row]; [_collectionView deleteItemsAtIndexPaths:@[indexPath]]; } completion:nil]; } else if([NSStringFromSelector(action) isEqualToString:@"paste:"]) { NSLog(@"-------------執(zhí)行粘貼-------------"); } }

UICollectionView自定義布局

要自定義UICollectionView布局,就要子類化UICollectionViewLayout,然后重寫(xiě)它的一些方法以達(dá)到我們自定義布局的需求。下來(lái)我們來(lái)看看UICollectionViewLayout類里一些比較重要的方法:

  • - (void)prepareLayout;為layout顯示做準(zhǔn)備工作,你可以在該方法里設(shè)置一些屬性。
  • - (CGSize)collectionViewContentSize;返回layout的size。
  • - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;返回在collectionView的可見(jiàn)范圍內(nèi)(bounds)所有item對(duì)應(yīng)的layoutAttrure對(duì)象裝成的數(shù)組。collectionView的每個(gè)item都對(duì)應(yīng)一個(gè)專門的UICollectionViewLayoutAttributes類型的對(duì)象來(lái)表示該item的一些屬性,比如bounds,size,transform,alpha等。
  • - (UICollectionViewLayoutAttributes )layoutAttributesForItemAtIndexPath:(NSIndexPath )indexPath;傳入indexPath,返回該indexPath對(duì)應(yīng)的layoutAtture對(duì)象。
  • - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds; 當(dāng)當(dāng)前l(fā)ayout的布局發(fā)生變動(dòng)時(shí),是否重寫(xiě)加載該layout。默認(rèn)返回NO,若返回YES,則重新執(zhí)行這倆方法:
    • - (void)prepareLayout;
    • - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;
  • - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity;返回layout“最終”的偏移量,何謂“最終”,手指離開(kāi)屏幕時(shí)layout的偏移量不是最終的,因?yàn)樗袘T性,當(dāng)它停止時(shí)才是“最終”偏移量。

下面這兩個(gè)方法一般用于自定義插入刪除時(shí)的動(dòng)畫(huà),后面再說(shuō)。

  • - (UICollectionViewLayoutAttributes )initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath )itemIndexPath;

  • - (nullable UICollectionViewLayoutAttributes )finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath )itemIndexPath;

本Demo的代碼雖然子類化了UICollectionViewLayout,但是主要是用于自定義插入刪除動(dòng)畫(huà),所以本段沒(méi)什么代碼展示。


UICollectionView插入刪除的操作及動(dòng)畫(huà)

插入刪除的操作

添加在哪觸發(fā):

UIBarButtonItem *btnItem = [[UIBarButtonItem alloc] initWithTitle:@"添加"style:UIBarButtonItemStylePlaintarget:self action:@selector(addItemBtnClick:)]; self.navigationItem.rightBarButtonItem = btnItem;

添加的實(shí)現(xiàn):

// 添加(插入item) - (void)addItemBtnClick:(UIBarButtonItem *)btnItem {[_collectionView performBatchUpdates:^{// 構(gòu)造一個(gè)indexPath NSIndexPath *indePath = [NSIndexPath indexPathForItem:_section0Array.count inSection:0]; [_collectionView insertItemsAtIndexPaths:@[indePath]]; // 然后在此indexPath處插入給collectionView插入一個(gè)item [_section0Array addObject:@"x"]; // 保持collectionView的item和數(shù)據(jù)源一致 } completion:nil]; }

因?yàn)槭蔷毩?xí)Demo,所以暫時(shí)把刪除的觸發(fā)源寫(xiě)在了長(zhǎng)按某Item彈出菜單的copy按鈕里。實(shí)際中你可以自定義UICollectionViewCell,添加長(zhǎng)按手勢(shì),長(zhǎng)按抖動(dòng)出現(xiàn)叉號(hào),然后刪除等,隨你怎么做。

// copy and paste 的實(shí)現(xiàn) - (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender { if([NSStringFromSelector(action) isEqualToString:@"copy:"]) { // NSLog(@"-------------執(zhí)行拷貝-------------"); [_collectionView performBatchUpdates:^{ [_section0Array removeObjectAtIndex:indexPath.row]; [_collectionView deleteItemsAtIndexPaths:@[indexPath]]; } completion:nil]; } else if([NSStringFromSelector(action) isEqualToString:@"paste:"]) { NSLog(@"-------------執(zhí)行粘貼-------------"); } }

插入刪除的動(dòng)畫(huà)

上面已經(jīng)提到了在UICollectionViewLayout類中有兩個(gè)用于自定義動(dòng)畫(huà)的方法,兩個(gè)方法分別表示動(dòng)畫(huà)的起始狀態(tài)和終止?fàn)顟B(tài),我們可以分別在方法里設(shè)置layoutAttrure來(lái)實(shí)現(xiàn)某種動(dòng)畫(huà)效果。

蘋果選擇了一種安全的途徑去實(shí)現(xiàn)一個(gè)簡(jiǎn)單的淡入淡出動(dòng)畫(huà)作為所有布局的默認(rèn)動(dòng)畫(huà)。如果你想實(shí)現(xiàn)自定義動(dòng)畫(huà),最好的辦法是子類化 UICollectionViewFlowLayout 并且在適當(dāng)?shù)牡胤綄?shí)現(xiàn)你的動(dòng)畫(huà)。

一般來(lái)說(shuō),我們對(duì)布局屬性從初始狀態(tài)到結(jié)束狀態(tài)進(jìn)行線性插值來(lái)計(jì)算 collection view 的動(dòng)畫(huà)參數(shù)。然而,新插入或者刪除的元素并沒(méi)有最初或最終狀態(tài)來(lái)進(jìn)行插值。要計(jì)算這樣的 cells 的動(dòng)畫(huà),collection view 將通過(guò) initialLayoutAttributesForAppearingItemAtIndexPath: 以及 finalLayoutAttributesForDisappearingItemAtIndexPath: 方法來(lái)詢問(wèn)其布局對(duì)象,以獲取最初的和最后的屬性。蘋果默認(rèn)的實(shí)現(xiàn)中,對(duì)于特定的某個(gè) indexPath,返回的是它的通常的位置,但 alpha 值為 0.0,這就產(chǎn)生了一個(gè)淡入或淡出動(dòng)畫(huà)。

簡(jiǎn)而言之,就是蘋果自帶了插入刪除時(shí)Item的淡入淡出的動(dòng)畫(huà),若你想自定義更炫的動(dòng)畫(huà),就子類化UICollectionViewFlowLayout類,并重寫(xiě)以下兩個(gè)方法:

// 初始狀態(tài) - (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {UICollectionViewLayoutAttributes *attr = [self layoutAttributesForItemAtIndexPath:itemIndexPath]; attr.center = CGPointMake(CGRectGetMidX(self.collectionView.bounds), CGRectGetMaxY(self.collectionView.bounds)); attr.transform = CGAffineTransformRotate(CGAffineTransformMakeScale(0.2, 0.2), M_PI); return attr; } // 終結(jié)狀態(tài) - (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath { UICollectionViewLayoutAttributes *attr = [self layoutAttributesForItemAtIndexPath:itemIndexPath]; attr.alpha = 0.0f; return attr; }
insert&delete.gif

UICollectionView的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)

http://objccn.io/issue-12-5/

轉(zhuǎn)載于:https://www.cnblogs.com/Free-Thinker/p/6737701.html

總結(jié)

以上是生活随笔為你收集整理的UICollectionView——整体总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。