zoukankan      html  css  js  c++  java
  • iOS6新特征:UICollectionView高级使用示例之CircleLayout

     
    下面再看看Demo运行的效果图,通过这样的一个Demo,我们可以看出,使用UICollectionView可以很方便的制作出照片浏览等应用。并且需要开发者写的代码也不多。
     
    程序刚刚启动时,已经默认加载了20个cell
     
    当点击程序的非cell位置,程序会自动的添加图片到UICollectionView中
     
     
    当点击UICollectionView中的某个cell,则该cell从UICollectionView中移除
     
     
    下面我也把相关的代码贴出来,代码文件的目录如下图所示
     
     
     
    AppDelegate介绍
    在AppDelegate的方法didFinishLaunchingWithOptions中,创建一个ViewController,注意:此处的ViewController是继承自UICollectionViewController,在此需要给ViewController传递一个Layout,此处传递了CircleLayout的一个对象实例。这是layout对象是与collection view相关的,layout控制了collection view如何显示它里面的cells和supplementary views。如下面这行关键的代码
    [csharp] view plaincopy
     
    1. 1       self.viewController = [[ViewController alloc] initWithCollectionViewLayout:[[CircleLayout alloc] init]];  




    [csharp] view plaincopy
     
    1. 01  //  
    2. 02  //  AppDelegate.h  
    3. 03  //  DevDiv_CollectionView_CircleLayout_Demo  
    4. 04  //  
    5. 05  //  Created by BeyondVincent on 12-7-3.  
    6. 06  //  Copyright (c) 2012年 DevDiv. All rights reserved.  
    7. 07  //  
    8. 08    
    9. 09  #import <UIKit/UIKit.h>  
    10. 10    
    11. 11  @class ViewController;  
    12. 12    
    13. 13  @interface AppDelegate : UIResponder <UIApplicationDelegate>  
    14. 14    
    15. 15  @property (strong, nonatomic) UIWindow *window;  
    16. 16    
    17. 17  @property (strong, nonatomic) ViewController *viewController;  
    18. 18    
    19. 19  @end  




    [csharp] view plaincopy
     
    1. 01  //  
    2. 02  //  AppDelegate.m  
    3. 03  //  DevDiv_CollectionView_CircleLayout_Demo  
    4. 04  //  
    5. 05  //  Created by BeyondVincent on 12-7-3.  
    6. 06  //  Copyright (c) 2012年 DevDiv. All rights reserved.  
    7. 07  //  
    8. 08    
    9. 09  #import "AppDelegate.h"  
    10. 10    
    11. 11  #import "ViewController.h"  
    12. 12  #import "CircleLayout.h"  
    13. 13    
    14. 14  @implementation AppDelegate  
    15. 15    
    16. 16  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
    17. 17  {  
    18. 18      self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  
    19. 19         
    20. 20      self.viewController = [[ViewController alloc] initWithCollectionViewLayout:[[CircleLayout alloc] init]];  
    21. 21         
    22. 22      self.window.rootViewController = self.viewController;  
    23. 23      [self.window makeKeyAndVisible];  
    24. 24      return YES;  
    25. 25  }  
    26. 26    
    27. 27  @end  

    ViewController介绍

    ViewController是继承自UICollectionViewController,它负责显示Collection View的所有内容。通常在这里实现Collection View的dataSource和delegate。下面的代码实现了如下两个方法:
    - (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section;
    - (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath;


    并且给collectionView添加了Tap手势识别功能,以便用户在Tap的时候,对item进行相应的添加和删除功能。

    [csharp] view plaincopy
     
    1. 01  //  
    2. 02  //  AppDelegate.m  
    3. 03  //  DevDiv_CollectionView_CircleLayout_Demo  
    4. 04  //  
    5. 05  //  Created by BeyondVincent on 12-7-3.  
    6. 06  //  Copyright (c) 2012年 DevDiv. All rights reserved.  
    7. 07  //  
    8. 08    
    9. 09  #import <UIKit/UIKit.h>  
    10. 10    
    11. 11  @interface ViewController : UICollectionViewController  
    12. 12    
    13. 13  @property (nonatomic, assign) NSInteger cellCount;  
    14. 14    
    15. 15  @end  



    [csharp] view plaincopy
     
    1. 01  //  
    2. 02  //  AppDelegate.m  
    3. 03  //  DevDiv_CollectionView_CircleLayout_Demo  
    4. 04  //  
    5. 05  //  Created by BeyondVincent on 12-7-3.  
    6. 06  //  Copyright (c) 2012年 DevDiv. All rights reserved.  
    7. 07  //  
    8. 08    
    9. 09  #import "ViewController.h"  
    10. 10  #import "Cell.h"  
    11. 11    
    12. 12  @implementation ViewController  
    13. 13    
    14. 14  -(void)viewDidLoad  
    15. 15  {  
    16. 16      self.cellCount = 20;  
    17. 17      UITapGestureRecognizer* tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];  
    18. 18      [self.collectionView addGestureRecognizer:tapRecognizer];  
    19. 19      [self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:@"MY_CELL"];  
    20. 20      [self.collectionView reloadData];  
    21. 21      self.collectionView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];  
    22. 22    
    23. 23      UIImageView* imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"icon.png"]];  
    24. 24      imageView.center = self.collectionView.center;  
    25. 25      [self.collectionView addSubview:imageView];  
    26. 26  }  
    27. 27    
    28. 28  - (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section;  
    29. 29  {  
    30. 30      return self.cellCount;  
    31. 31  }  
    32. 32    
    33. 33  - (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath;  
    34. 34  {  
    35. 35      Cell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"MY_CELL" forIndexPath:indexPath];  
    36. 36      return cell;  
    37. 37  }  
    38. 38    
    39. 39  - (void)handleTapGesture:(UITapGestureRecognizer *)sender {  
    40. 40         
    41. 41      if (sender.state == UIGestureRecognizerStateEnded)  
    42. 42      {  
    43. 43          CGPoint initialPinchPoint = [sender locationInView:self.collectionView];  
    44. 44          NSIndexPath* tappedCellPath = [self.collectionView indexPathForItemAtPoint:initialPinchPoint];  
    45. 45          if (tappedCellPath!=nil)  
    46. 46          {  
    47. 47              self.cellCount = self.cellCount - 1;  
    48. 48              [self.collectionView performBatchUpdates:^{  
    49. 49                  [self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:tappedCellPath]];  
    50. 50                     
    51. 51              } completion:nil];  
    52. 52          }  
    53. 53          else  
    54. 54          {  
    55. 55              self.cellCount = self.cellCount + 1;  
    56. 56              [self.collectionView performBatchUpdates:^{  
    57. 57                  [self.collectionView insertItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForItem:0 inSection:0]]];  
    58. 58              } completion:nil];  
    59. 59          }  
    60. 60      }  
    61. 61  }  
    62. 62    
    63. 63  @end  



    Cell介绍

    在此自定义了一个简单的cell:继承自UICollectionViewCell。

    当item在collection view的可视范围内时,UICollectionViewCell负责显示单个item数据的内容,你可以通过as-is关系来使用它,当然,也可以继承(subclass)自它,以添加一些额外的属性和方法。cell的layout和显示是有collection view管理的,并且cell与layout对象相互对应。

    在这里,我使用继承(subclass)机制,来给cell添加了一个UIImageView,用来显示一副图片。代码很简单,看下面的具体时间即可。在.m文件里面对UIImageView进行了圆角处理。

    [csharp] view plaincopy
     
    1. 01  //  
    2. 02  //  AppDelegate.m  
    3. 03  //  DevDiv_CollectionView_CircleLayout_Demo  
    4. 04  //  
    5. 05  //  Created by BeyondVincent on 12-7-3.  
    6. 06  //  Copyright (c) 2012年 DevDiv. All rights reserved.  
    7. 07  //  
    8. 08    
    9. 09  #import <UIKit/UIKit.h>  
    10. 10    
    11. 11  @interface Cell : UICollectionViewCell  
    12. 12    
    13. 13  @property (strong, nonatomic) UIImageView* imageView;  
    14. 14    
    15. 15  @end  




    [csharp] view plaincopy
     
    1. 01  //  
    2. 02  //  AppDelegate.m  
    3. 03  //  DevDiv_CollectionView_CircleLayout_Demo  
    4. 04  //  
    5. 05  //  Created by BeyondVincent on 12-7-3.  
    6. 06  //  Copyright (c) 2012年 DevDiv. All rights reserved.  
    7. 07  //  
    8. 08    
    9. 09  #import "Cell.h"  
    10. 10    
    11. 11  @implementation Cell  
    12. 12    
    13. 13  - (id)initWithFrame:(CGRect)frame  
    14. 14  {  
    15. 15      self = [super initWithFrame:frame];  
    16. 16      if (self) {  
    17. 17          self.contentView.layer.cornerRadius = 10.0;  
    18. 18          [self.contentView setFrame:CGRectMake(0, 0, 75, 75)];  
    19. 19          self.contentView.layer.borderWidth = 1.0f;  
    20. 20          self.contentView.layer.borderColor = [UIColor whiteColor].CGColor;  
    21. 21          self.contentView.backgroundColor = [UIColor underPageBackgroundColor];  
    22. 22             
    23. 23          self.imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"98_avatar_big.jpg"]];  
    24. 24             
    25. 25          self.imageView.layer.masksToBounds = YES;    
    26. 26          self.imageView.layer.cornerRadius = 10.0;  
    27. 27          [self.imageView setFrame:self.contentView.frame];  
    28. 28          [self.contentView addSubview:self.imageView];  
    29. 29      }  
    30. 30      return self;  
    31. 31  }  
    32. 32    
    33. 33  @end  

    CircleLayout介绍【在UICollectionView中,Layout非常重要】

    CircleLayout继承自UICollectionViewLayout,在这里先简单介绍一下UICollectionViewLayout
    UICollectionViewLayout类是一个抽象基类,通过继承它以生成collection view的layout信息。layout对象的职责就是决定collection view中cells,supplementary views和decoration views的位置,当collection view请求这些信息时,layout对象会提供给collection view。collection view就使用laout对象提供的信息把相关的view显示在屏幕上。
    注意:要使用UICollectionViewLayout必须先子类化它

    子类化时需要注意的事项:
    layout对象不负责创建views,它只提供layout(布局),view的创建是在collection view的data source中。layout对象定义了view的位置和size等布局属性。

    collection view有三种可视元素需要layout:
    Cells:cells是layout管理的主要元素。每一个cell代表了collection view中的单个数据item。一个collection view可以把cell放到一个section中,也可以把cell分为多个section。layout的主要职责就是组织collection view的cells。

    Supplementary views:supplementary view也显示数据,但是与cells不同。并不像cell,supplementary view不可以被用户选择。相反,可以使用supplementary view来给一个section实现类似页眉和页脚,当然不仅仅是section,也可以是整个collection view。supplementary view是可选的,并且他们的使用和位置是由layout对象定义的。

    Decoration views:decoration view是用于装饰的,不可以被用户选择,并且它的相关数据没有与collection view绑定。decoration view是另外一种supplementary view。类似supplementary view,decoration view也是可选的,,并且他们的使用和位置是由layout对象定义的。

    collection view会在许多不同时间里面,请求这些元素的layout对象以获得相关 layout信息。每一个出现在屏幕中的cell和view的位置是有layout对象提供的。类似的,每次从collection view中插入或者删除item,相应的layout也会被添加或者移除。当然,collection view总是会限制layout对象数目:即只针对屏幕的可视范围。

    需要重载的方法
    每个layout对象都需要实现下面的方法:
    • collectionViewContentSize
    • shouldInvalidateLayoutForBoundsChange:
    • layoutAttributesForElementsInRect:
    • layoutAttributesForItemAtIndexPath:
    • layoutAttributesForSupplementaryViewOfKind:atIndexPath: (如果layout 支持 supplementary views)
    • layoutAttributesForDecorationViewWithReuseIdentifier:atIndexPath: (如果layout 支持 decoration views)

    这些方法具体作用,可以查阅相关的sdk即可知晓。
    当collection view中的数据发生了改变,如插入或删除item,那么collection view会请求这些item的layout对象,以更新layout信息。特别是,任意的item被移动,添加或者删除了,必须要有它相关的layout信息来更新相关的新位置。对于移动一个items,collection view会使用标准的方法来检索item的layout属性。对于item的插入和删除,collection view会调用一些不同的方法,你应该重载这些方法,以提供相关的layout信息:
    • initialLayoutAttributesForInsertedItemAtIndexPath:
    • initialLayoutAttributesForInsertedSupplementaryElementOfKind:atIndexPath:
    • finalLayoutAttributesForDeletedItemAtIndexPath:
    • finalLayoutAttributesForDeletedSupplementaryElementOfKind:atIndexPath:

    下面的代码中就是使用到了item的插入和删除。所以重载了下面两个方法:
    • initialLayoutAttributesForInsertedItemAtIndexPath:
    • finalLayoutAttributesForDeletedItemAtIndexPath:


    对于layout在collection view中的作用非常重大,你的画面显示什么效果就看你如何定义layout了。更多相关信息还请阅读相关sdk中的内容。在此不再进行详细的讲解。


    [csharp] view plaincopy
     
    1. 01  //  
    2. 02  //  AppDelegate.m  
    3. 03  //  DevDiv_CollectionView_CircleLayout_Demo  
    4. 04  //  
    5. 05  //  Created by BeyondVincent on 12-7-3.  
    6. 06  //  Copyright (c) 2012年 DevDiv. All rights reserved.  
    7. 07  //  
    8. 08    
    9. 09  #import <UIKit/UIKit.h>  
    10. 10    
    11. 11  @interface CircleLayout : UICollectionViewLayout  
    12. 12    
    13. 13  @property (nonatomic, assign) CGPoint center;  
    14. 14  @property (nonatomic, assign) CGFloat radius;  
    15. 15  @property (nonatomic, assign) NSInteger cellCount;  
    16. 16    
    17. 17  @end  


     


    [csharp] view plaincopy
     
    1. 01  //  
    2. 02  //  AppDelegate.m  
    3. 03  //  DevDiv_CollectionView_CircleLayout_Demo  
    4. 04  //  
    5. 05  //  Created by BeyondVincent on 12-7-3.  
    6. 06  //  Copyright (c) 2012年 DevDiv. All rights reserved.  
    7. 07  //  
    8. 08    
    9. 09  #import "CircleLayout.h"  
    10. 10    
    11. 11  #define ITEM_SIZE 70  
    12. 12    
    13. 13  @implementation CircleLayout  
    14. 14    
    15. 15  -(void)prepareLayout  
    16. 16  {  
    17. 17      [super prepareLayout];  
    18. 18         
    19. 19      CGSize size = self.collectionView.frame.size;  
    20. 20      _cellCount = [[self collectionView] numberOfItemsInSection:0];  
    21. 21      _center = CGPointMake(size.width / 2.0, size.height / 2.0);  
    22. 22      _radius = MIN(size.width, size.height) / 2.5;  
    23. 23  }  
    24. 24    
    25. 25  -(CGSize)collectionViewContentSize  
    26. 26  {  
    27. 27      return [self collectionView].frame.size;  
    28. 28  }  
    29. 29    
    30. 30  - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path  
    31. 31  {  
    32. 32      UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path];  
    33. 33      attributes.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE);  
    34. 34      attributes.center = CGPointMake(_center.x + _radius * cosf(2 * path.item * M_PI / _cellCount),  
    35. 35                                      _center.y + _radius * sinf(2 * path.item * M_PI / _cellCount));  
    36. 36      return attributes;  
    37. 37  }  
    38. 38    
    39. 39  -(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect  
    40. 40  {  
    41. 41      NSMutableArray* attributes = [NSMutableArray array];  
    42. 42      for (NSInteger i=0 ; i < self.cellCount; i++) {  
    43. 43          NSIndexPath* indexPath = [NSIndexPath indexPathForItem:i inSection:0];  
    44. 44          [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];  
    45. 45      }     
    46. 46      return attributes;  
    47. 47  }  
    48. 48    
    49. 49  - (UICollectionViewLayoutAttributes *)initialLayoutAttributesForInsertedItemAtIndexPath:(NSIndexPath *)itemIndexPath  
    50. 50  {  
    51. 51      UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];  
    52. 52      attributes.alpha = 0.0;  
    53. 53      attributes.center = CGPointMake(_center.x, _center.y);  
    54. 54      return attributes;  
    55. 55  }  
    56. 56    
    57. 57  - (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDeletedItemAtIndexPath:(NSIndexPath *)itemIndexPath  
    58. 58  {  
    59. 59      UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];  
    60. 60      attributes.alpha = 0.0;  
    61. 61      attributes.center = CGPointMake(_center.x, _center.y);  
    62. 62      attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0);  
    63. 63      return attributes;  
    64. 64  }  
    65. 65    
    66. 66  @end  
      1. 原文:http://blog.csdn.net/eqera/article/details/8134994
  • 相关阅读:
    winform,WPF 释放内存垃圾,减少资源占用方法
    Winform中使用WPF控件并动态读取Xaml
    Winform程序双向绑定
    STM32L15XXX 入门笔记
    STM32固件库下载地址
    C#实现虚拟控件列表显示100w个控件方法
    DotNetBar滚动条的疑似BUG
    VS Sln图标空白修复办法
    Swift下使用Xib设计界面
    关于Mac OS虚拟机下共享文件夹的方法
  • 原文地址:https://www.cnblogs.com/langtianya/p/4102755.html
Copyright © 2011-2022 走看看