UICollectionView和UIDynamicanimation结合使用

来源:互联网 发布:炒贵金属软件 编辑:程序博客网 时间:2024/06/05 05:20

又是星期天了,今天说一个如何在UICollectionView中,使用UIDynamicanimation,做一个可以左右摆动的动画效果


首先,新建一个DynamicView的类,继承自UIView,在这个类中,我们封装了一个带有左右摆动的动画效果

#import "DynamicView.h"@implementation DynamicView{    UIDynamicAnimator *_animator;    UIPushBehavior *_pushBehavior;    }- (instancetype)initWithFrame:(CGRect)frame {    self = [super initWithFrame:frame];    if (self) {        self.backgroundColor = [UIColor clearColor];                //挂件        self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.bounds.origin.x + 30, self.bounds.origin.y + 20, self.bounds.size.width - 60, self.bounds.size.height - 40)];        self.imageView.userInteractionEnabled = YES;        [self addSubview:self.imageView];                        //花纹        self.topImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0 , self.bounds.size.width - 60, 50)];        [self addSubview:self.topImageView];                //love寄语        self.love = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 60, 40)];        self.love.center = CGPointMake(self.bounds.size.width / 2, self.topImageView.center.y );        self.love.userInteractionEnabled = YES;        self.love.image = [UIImage imageNamed:@"love"];        [self addSubview:self.love];                //添加滑动        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleView:)];        [self.imageView addGestureRecognizer:pan];                        //KVO观察者模式        [self.imageView addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:nil];                //加载动画        [self applyDynamic];    }    return self;}- (void)applyDynamic {        UIDynamicBehavior *behavior = [[UIDynamicBehavior alloc] init];        CGPoint anchor = self.imageView.center;    anchor.y -= 200;        self.topImageView.center = anchor;    UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:self.imageView attachedToAnchor:anchor];    [behavior addChildBehavior:attachment];        //重力    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.imageView]];    gravity.magnitude = 10;    [behavior addChildBehavior:gravity];        //物理引擎公有属性    UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.imageView]];    itemBehavior.elasticity = 1.0;    itemBehavior.allowsRotation = NO;    itemBehavior.resistance = 2.0f;    [behavior addChildBehavior:itemBehavior];            //将动画加入到contentView中    _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self];    [_animator addBehavior:behavior];    }- (void)handleView:(UIPanGestureRecognizer *)pan {    if (pan.state == UIGestureRecognizerStateBegan) {        if (_pushBehavior) {            [_animator removeBehavior:_pushBehavior];        }        //推力        _pushBehavior = [[UIPushBehavior alloc] initWithItems:@[pan.view] mode:UIPushBehaviorModeContinuous];        [_animator addBehavior:_pushBehavior];    }        CGFloat offset = [pan translationInView:self].x / 10.f;    _pushBehavior.pushDirection = CGVectorMake(offset, 0);    if (pan.state == UIGestureRecognizerStateEnded) {        [_animator removeBehavior:_pushBehavior];        _pushBehavior = nil;    }}//画连线- (void)drawRect:(CGRect)rect {    CGContextRef context = UIGraphicsGetCurrentContext();    //起点    CGPoint anchor = self.topImageView.center;    //终点    CGPoint pointLeft = CGPointMake(self.imageView.frame.origin.x + 62, self.imageView.frame.origin.y + 12);    CGPoint pointRight = CGPointMake(self.imageView.frame.origin.x + self.imageView.frame.size.width - 57, self.imageView.frame.origin.y + 10);        CGContextMoveToPoint(context, anchor.x - 120, anchor.y - 15);    CGContextAddLineToPoint(context, pointLeft.x, pointLeft.y);        CGContextMoveToPoint(context, anchor.x + 120, anchor.y - 15);    CGContextAddLineToPoint(context, pointRight.x, pointRight.y);    CGContextSetLineWidth(context, 1.0f);    [[UIColor blackColor] setStroke];        CGContextSetAllowsAntialiasing(context, YES);    CGContextSetShouldAntialias(context, YES);    self.layer.shouldRasterize = YES;        CGContextDrawPath(context, kCGPathFillStroke);        }//刷新画线- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {    [self setNeedsDisplay];}//移除KVO- (void)dealloc {    [self.imageView removeObserver:self forKeyPath:@"center" context:nil];}

然后,新建一个cell,继承自UICollectionViewCell;

#import "BookCoverCell.h"@implementation BookCoverCell{    UIDynamicAnimator *_animator;    UIPushBehavior *_pushBehavior;}//初始化- (instancetype)initWithFrame:(CGRect)frame {    self = [super initWithFrame:frame];    if (self) {                //设置contentView的背景颜色        self.contentView.backgroundColor = [UIColor clearColor];                self.viewDynamic = [[DynamicView alloc] initWithFrame:self.bounds];        [self.contentView addSubview:self.viewDynamic];            }    return self;}@end


随后,新建一个布局,继承自UICollectionViewFlowLayout,对cell进行布局,可以左右滑动的cell

#import "BookCoverLayout.h"@implementation BookCoverLayout//这两个常量用来设置cell的尺寸;static CGFloat PageWidth = 450;static CGFloat PageHeight = 360;//初始化方法- (instancetype)init {    self = [super init];    if (self) {        self.scrollDirection = UICollectionViewScrollDirectionHorizontal; //1 滚动方向        self.itemSize = CGSizeMake(PageWidth, PageHeight); //2 cell的尺寸        self.minimumInteritemSpacing = 10; //3 cell间最小间距    }    return self;}//重写prepareLayout方法;//告诉Layout对象去更新当前的layout;- (void)prepareLayout {    [super prepareLayout];    //滚动视图的比例    //1.设置滚动视图的停止速度    self.collectionView.decelerationRate = UIScrollViewDecelerationRateFast;    //2.设置插入间隔区域;定义一个在scrollview被拽出一个contentOffset 的时候的一个空间    self.collectionView.contentInset = UIEdgeInsetsMake(0,                                                        self.collectionView.bounds.size.width / 2 - PageWidth / 2 ,                                                        0,                                                        self.collectionView.bounds.size.width / 2 - PageWidth / 2);    }//设置每个cell的布局- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {        NSArray *array = [super layoutAttributesForElementsInRect:rect];    for (UICollectionViewLayoutAttributes *attributes in array) {        CGRect frame = attributes.frame;        CGFloat distance = 0;        //计算间距        distance = fabs(self.collectionView.contentOffset.x + self.collectionView.contentInset.left - frame.origin.x);        //根据相互间距离,设置缩放比例        CGFloat scale = 0.7 * MIN(MAX(1 - distance / (self.collectionView.bounds.size.width), 0.75), 1);        attributes.transform = CGAffineTransformMakeScale(scale, scale);    }    return array;}//当collection View 的bounds发生改变时,能够重新计算cell属性,当滚动时,UICollectionView会改变它的bounds;- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {    return YES;}//封面快速到位,当手指抬起时,停止的点- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {    CGPoint newOffset;    //获取当前位置    UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;    //计算总宽度    CGFloat width = layout.itemSize.width + layout.minimumLineSpacing;    //计算偏移量    CGFloat offset = proposedContentOffset.x + self.collectionView.contentInset.left;        if (velocity.x > 0) {        //ceil(x) 返回一个更大的数        offset = width * ceil(offset / width); //如果velocity.x > 0,向右滚动,根据(偏移量 /宽度),决定滚动到哪个封面    } else if (velocity.x == 0) {        //round(x) 返回一个四舍五入的值        offset = width * round(offset / width); //如果velocity.x = 0,滑动不充足,仍旧是当前cell    } else if (velocity.x < 0) {        //floor(x) 取不大于x的最大整数        offset = width *floor(offset / width); //如果velocity.x < 0,向左滚动    }    newOffset.x = offset - self.collectionView.contentInset.left;    newOffset.y = proposedContentOffset.y; //总是相同    return newOffset;}@end

最后,新建一个View,继承自UICollectionView,实现数据源代理

#import "CollectionVIew.h"@implementation CollectionVIewstatic NSString *const reuseIdentifier = @"cell";- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout {    self = [super initWithFrame:frame collectionViewLayout:layout];    if (self) {    self.dataSource = self;    self.delegate = self;    [self registerClass:[BookCoverCell class] forCellWithReuseIdentifier:reuseIdentifier];    self.backgroundColor = [UIColor clearColor];    }    self.showsHorizontalScrollIndicator = NO;    return self;}- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {    return 5;}- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {    BookCoverCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];    cell.viewDynamic.imageView.image = [UIImage imageNamed:@"bg2"];    cell.viewDynamic.topImageView.image = [UIImage originalSizeImageWithPDFNamed:@"mybg4.pdf"];    return cell;}@end
这样,所有的准备工作就做完了,我们在ViewController中,alloc一下,就OK了;

#import "ViewController.h"#import "CollectionVIew.h"#import "BookCoverCell.h"#import "BookCoverLayout.h"#define  kScreenWidth  [UIScreen mainScreen].bounds.size.width#define  kScreenHeight [UIScreen mainScreen].bounds.size.height@interface ViewController ()@property (strong, nonatomic) CollectionVIew *collectionView;@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    self.view.backgroundColor = [UIColor whiteColor];        BookCoverLayout *myLayout = [[BookCoverLayout alloc] init];    self.collectionView = [[CollectionVIew alloc] initWithFrame:CGRectMake(0, kScreenHeight * 0.25, kScreenWidth, kScreenHeight * 0.55) collectionViewLayout:myLayout];    [self.view addSubview:self.collectionView];}@end

demo下载地址:

http://download.csdn.net/download/et295394330/9122053

1 0
原创粉丝点击