您的位置:首页 > 产品设计 > UI/UE

UICollectionView和UIDynamicanimation结合使用

2015-09-20 17:22 585 查看
又是星期天了,今天说一个如何在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 CollectionVIew

static 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: