UICollectionView和UIDynamicanimation结合使用
2015-09-20 17:22
585 查看
又是星期天了,今天说一个如何在UICollectionView中,使用UIDynamicanimation,做一个可以左右摆动的动画效果
首先,新建一个DynamicView的类,继承自UIView,在这个类中,我们封装了一个带有左右摆动的动画效果
然后,新建一个cell,继承自UICollectionViewCell;
随后,新建一个布局,继承自UICollectionViewFlowLayout,对cell进行布局,可以左右滑动的cell
最后,新建一个View,继承自UICollectionView,实现数据源代理
demo下载地址:
http://download.csdn.net/download/et295394330/9122053
首先,新建一个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
相关文章推荐
- iOS开发笔记--UISlider的相关属性设置
- 转载:Understanding How PostgreSQL Executes a Query
- Android运用Handler和Message实现异步更新UI界面
- poj 2524 Ubiquitous Religions
- iOS开发之UILabel
- easyUI之Combo
- UVa1584——Circular Sequence
- 23设计模式之建造者模式(Builder)
- Android Gradle 构建工具(Android Gradle Build Tools)是什么?
- 如何把一个UITableView滚动到tableFooterView?
- ios9兼容系列之解决iPad提交报错“iPad Multitasking support requires launch story board in bundle '”
- Mycat全局Sequence详解
- Maven打包web项目报错Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if
- Android UI高级控件之SimpleAdapter
- 徒手用Java来写个Web服务器和框架吧<第二章:Request和Response>
- 在UIButton中如何将imageView和titleView居中且上下分布
- android 事件处理机制之requestDisallowInterceptTouchEvent
- 使用Libcef+Duilib创建自己的Chrome内核浏览器
- Minor issue about class define and the valid scope of scope operator
- iOS:搜索栏控件UISearchBar and SearchDisplayController的使用