iOS6新特征:UICollectionView高级使用示例之CircleLayout

由于UICollectionView功能比较强大,上一篇中对UICollectionView进行了讲解,并给出了一个简单的例子,但是还不足以体现出UICollectionView的强大,在此,继续深入学习了一下UICollectionView的高级功能,顺与大家分享一下心得。 

本示例参考了苹果的WWDC2012,小弟在此模仿了一下,仅起抛砖引玉的作用,UICollectionView更强悍的Layout还等待你的探索

【苹果把PSCollectionView剽窃了一回。那我也抄袭苹果的Demo一回】 

先上代码附件,下载

下面再看看Demo运行的效果图,通过这样的一个Demo,我们可以看出,使用UICollectionView可以很方便的制作出照片浏览等应用。并且需要开发者写的代码也不多。 

程序刚刚启动时,已经默认加载了20cell

[转载](转)iOS6新特征:UICollectionView高级使用示例之Cir 

当点击程序的非cell位置,程序会自动的添加图片到UICollectionView

 [转载](转)iOS6新特征:UICollectionView高级使用示例之Cir

当点击UICollectionView中的某个cell,则该cellUICollectionView中移除

 [转载](转)iOS6新特征:UICollectionView高级使用示例之Cir

下面我也把相关的代码贴出来,代码文件的目录如下图所示

 [转载](转)iOS6新特征:UICollectionView高级使用示例之Cir

从上图,可以看到这个Demo8个关键文件,下面分别对其进行介绍。

1AppDelegate介绍

2ViewController介绍

3Cell介绍

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

一、AppDelegate介绍

AppDelegate的方法didFinishLaunchingWithOptions中,创建一个ViewController,注意:此处的ViewController是继承自UICollectionViewController,在此需要给ViewController传递一个Layout,此处传递了CircleLayout的一个对象实例。这是layout对象是与collection view相关的,layout控制了collection view如何显示它里面的cellssupplementary views。如下面这行关键的代码

 

self.viewController = [[ViewController alloc] initWithCollectionViewLayout:[[CircleLayout alloc] init]];

//

//  AppDelegate.h

//  DevDiv_CollectionView_CircleLayout_Demo

//

//  Created by BeyondVincent on 12-7-3.

//  Copyright (c) 2012 DevDiv. All rights reserved.

//

 

#import

 

@class ViewController;

 

@interface AppDelegate : UIResponder <</SPAN>UIApplicationDelegate>

 

@property (strong, nonatomic) UIWindow *window;

 

@property (strong, nonatomic) ViewController *viewController;

 

@end

//

//  AppDelegate.m

//  DevDiv_CollectionView_CircleLayout_Demo

//

//  Created by BeyondVincent on 12-7-3.

//  Copyright (c) 2012 DevDiv. All rights reserved.

//

 

#import "AppDelegate.h"

 

#import "ViewController.h"

#import "CircleLayout.h"

 

@implementation AppDelegate

 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions

{

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

   

    self.viewController = [[ViewController alloc] initWithCollectionViewLayout:[[CircleLayoutalloc] init]];

   

    self.window.rootViewController = self.viewController;

    [self.window makeKeyAndVisible];

    return YES;

}

 

@end

 

二、ViewController介绍

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

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

//

//  AppDelegate.h

//  DevDiv_CollectionView_CircleLayout_Demo

//

//  Created by BeyondVincent on 12-7-3.

//  Copyright (c) 2012 DevDiv. All rights reserved.

//

 

#import

 

@interface ViewController : UICollectionViewController

 

@property (nonatomic, assign) NSInteger cellCount;

 

@end

//

//  AppDelegate.m

//  DevDiv_CollectionView_CircleLayout_Demo

//

//  Created by BeyondVincent on 12-7-3.

//  Copyright (c) 2012 DevDiv. All rights reserved.

//

 

#import "ViewController.h"

#import "Cell.h"

 

@implementation ViewController

 

-(void)viewDidLoad

{

    self.cellCount = 20;

    UITapGestureRecognizer* tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:selfaction:@selector(handleTapGesture:)];

    [self.collectionView addGestureRecognizer:tapRecognizer];

    [self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:@"MY_CELL"];

    [self.collectionView reloadData];

    self.collectionView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];

 

    UIImageView* imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"icon.png"]];

    imageView.center = self.collectionView.center;

    [self.collectionView addSubview:imageView];

}

 

- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section;

{

    return self.cellCount;

}

 

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath;

{

    Cell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"MY_CELL" forIndexPath:indexPath];

    return cell;

}

 

- (void)handleTapGesture:(UITapGestureRecognizer *)sender {

   

    if (sender.state == UIGestureRecognizerStateEnded)

    {

        CGPoint initialPinchPoint = [sender locationInView:self.collectionView];

        NSIndexPath* tappedCellPath = [self.collectionViewindexPathForItemAtPoint:initialPinchPoint];

        if (tappedCellPath!=nil)

        {

            self.cellCount = self.cellCount - 1;

            [self.collectionView performBatchUpdates:^{

                [self.collectionView deleteItemsAtIndexPaths:[NSArrayarrayWithObject:tappedCellPath]];

               

            } completion:nil];

        }

        else

        {

            self.cellCount = self.cellCount + 1;

            [self.collectionView performBatchUpdates:^{

                [self.collectionView insertItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPathindexPathForItem:0 inSection:0]]];

            } completion:nil];

        }

    }

}

 

@end

 

三、Cell介绍

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

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

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

//

//  Cell.h

//  DevDiv_CollectionView_CircleLayout_Demo

//

//  Created by BeyondVincent on 12-7-3.

//  Copyright (c) 2012 DevDiv. All rights reserved.

//

 

#import

 

@interface Cell : UICollectionViewCell

 

@property (strong, nonatomic) UIImageView* imageView;

 

@end

//

//  Cell.m

//  DevDiv_CollectionView_CircleLayout_Demo

//

//  Created by BeyondVincent on 12-7-3.

//  Copyright (c) 2012 DevDiv. All rights reserved.

//

 

#import "Cell.h"

 

@implementation Cell

   

 

- (id)initWithFrame:(CGRect)frame

{

    self = [super initWithFrame:frame];

    if (self) {

       

//      self.contentView.layer.cornerRadius = 10.0;

        [self.contentView setFrame:CGRectMake(0, 0, 75, 75)];

//      self.contentView.layer.borderWidth = 1.0f;

//      self.contentView.layer.borderColor = [UIColor whiteColor].CGColor;

        self.contentView.backgroundColor = [UIColor underPageBackgroundColor];

       

        self.imageView = [[UIImageView alloc]initWithImage:[UIImageimageNamed:@"98_avatar_big.jpg"]];

       

//      self.imageView.layer.masksToBounds = YES;

//      self.imageView.layer.cornerRadius = 10.0;

        [self.imageView setFrame:self.contentView.frame];

        [self.contentView addSubview:self.imageView];

        }

   

    return self;

}

@end


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

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

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

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

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

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

collection view
会在许多不同时间里面,请求这些元素的layout对象以获得相关 layout信息。每一个出现在屏幕中的cellview的位置是有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会请求这些itemlayout对象,以更新layout信息。特别是,任意的item被移动,添加或者删除了,必须要有它相关的layout信息来更新相关的新位置。对于移动一个itemscollection view会使用标准的方法来检索itemlayout属性。对于item的插入和删除,collection view会调用一些不同的方法,你应该重载这些方法,以提供相关的layout信息:

initialLayoutAttributesForInsertedItemAtIndexPath:

initialLayoutAttributesForInsertedSupplementaryElementOfKind:atIndexPath:

finalLayoutAttributesForDeletedItemAtIndexPath:

finalLayoutAttributesForDeletedSupplementaryElementOfKind:atIndexPath:


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

initialLayoutAttributesForInsertedItemAtIndexPath:

finalLayoutAttributesForDeletedItemAtIndexPath:



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

//

//  CircleLayout.h

//  DevDiv_CollectionView_CircleLayout_Demo

//

//  Created by BeyondVincent on 12-7-3.

//  Copyright (c) 2012 DevDiv. All rights reserved.

//

 

#import

 

@interface CircleLayout : UICollectionViewLayout

 

@property (nonatomic, assign) CGPoint center;

@property (nonatomic, assign) CGFloat radius;

@property (nonatomic, assign) NSInteger cellCount;

 

@end

//

//  CircleLayout.m

//  DevDiv_CollectionView_CircleLayout_Demo

//

//  Created by BeyondVincent on 12-7-3.

//  Copyright (c) 2012 DevDiv. All rights reserved.

//

 

#import "CircleLayout.h"

 

#define ITEM_SIZE 70

 

@implementation CircleLayout

 

-(void)prepareLayout

{

    [super prepareLayout];

   

    CGSize size = self.collectionView.frame.size;

    _cellCount = [[self collectionView] numberOfItemsInSection:0];

    _center = CGPointMake(size.width / 2.0, size.height / 2.0);

    _radius = MIN(size.width, size.height) / 2.5;

}

 

-(CGSize)collectionViewContentSize

{

    return [self collectionView].frame.size;

}

 

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path

{

    UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributeslayoutAttributesForCellWithIndexPath:path];

    attributes.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE);

    attributes.center = CGPointMake(_center.x + _radius * cosf(2 * path.item * M_PI /_cellCount),

                                    _center.y + _radius * sinf(2 * path.item * M_PI /_cellCount));

    return attributes;

}

 

-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect

{

    NSMutableArray* attributes = [NSMutableArray array];

    for (NSInteger i=0 ; i < self.cellCount; i++) {

        NSIndexPath* indexPath = [NSIndexPath indexPathForItem:i inSection:0];

        [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];

    }   

    return attributes;

}

 

- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForInsertedItemAtIndexPath:(NSIndexPath *)itemIndexPath

{

    UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];

    attributes.alpha = 0.0;

    attributes.center = CGPointMake(_center.x, _center.y);

    return attributes;

}

 

- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDeletedItemAtIndexPath:(NSIndexPath *)itemIndexPath

{

    UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];

    attributes.alpha = 0.0;

    attributes.center = CGPointMake(_center.x, _center.y);

    attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0);

    return attributes;

}

 

@end


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值