利用swift实现卡片横向滑动动画效果的方法示例

本文主要给大家介绍了关于利用swift实现卡片横向滑动动画效果的相关资料,分享出来供大家参考学习,下面来一起看看详细的介绍吧。

根据惯例,首先上效果图:

那天去面试,面试官突然拿出手机点开了一个app,自个在那点了一会,然后问我 这个效果怎么实现,当时一看可以滑动,肯定用scrollView 或者 collectionView实现,就大概的说了下。今天刚好闲下来,就敲一敲这个效果。

先来分析下这个效果:

卡片是横向滚动,并且每个卡片的位置都是保持在屏幕中间的,而且 左右相邻的卡片都露出来一点边
collectionView 和scrollView都可以实现,在这里,我们用collectionView实现,但是我们平常普通用的collectionView都是正屏滑动的!!而且是平滑,所有我们只能自定义UICollectionViewFlowLayout 流式布局,才可以达到上图效果.

废话不多说,直接上代码:

创建collectionView布局

//创建collectionView布局
func setepUI() {
//CustomLayout是自定义的UICollectionViewFlowLayout
 layout = CustomLayout()
 layout?.itemSize = CGSize(width: SCREEN_WIDTH-80, height: SCREEN_HEIGHT-64-120)

 let rect = CGRect(x: 0, y: 64, width:SCREEN_WIDTH , height: SCREEN_HEIGHT-64)
 collectionView = UICollectionView(frame: rect, collectionViewLayout: layout!)
 collectionView?.delegate = self
 collectionView?.dataSource = self
 view.addSubview(collectionView!)
 collectionView?.register(CustomViewCell.self, forCellWithReuseIdentifier: "identifier")
 collectionView?.backgroundColor = UIColor.red

 }

实现代理方法:

我们在extension中实现:

// MARK: -- delegate and datasource
extension ViewController:
UICollectionViewDelegate,
UICollectionViewDataSource,
UICollectionViewDelegateFlowLayout{

 func numberOfSections(in collectionView: UICollectionView) -> Int {
 return 1
 }

 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
 return 10
 }
 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//CustomViewCell是自定义的cell
 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "identifier", for: indexPath) as! CustomViewCell
 cell.backgroundColor = UIColor.orange
 cell.lable?.text = "\(indexPath.row)/\(10)"
 return cell
 }
}

至此,我们可以得到普通的效果,左右滑动,但中间cell不会居中,两侧cell也不会缩放,如下图:

这个时候就需要在自定义的流式布局 CustomLayout里做点什么了:

初始化方法 prepare , 初始化一些内容:

//重写prepare方法
 //布局之前的准备工作 初始化 这个方法每次layout发生改变就调用一次
override func prepare() {
  scrollDirection = UICollectionViewScrollDirection.horizontal
   minimumLineSpacing = 20.0
  sectionInset = UIEdgeInsets(top: 0, left: 40, bottom: 0, right: 40)
  super.prepare()
 }

(该方法默认返回false) 返回true frame发生改变就允许重新布局 内部会重新调用prepare 和

layoutAttributesForElementsInRect
 override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
  return true
 }

MARK:---用来计算出rect这个范围内所有cell的UICollectionViewLayoutAttributes 对象,循环遍历每个attribute对象,修改frame,再将这数组返回给系统

 override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
  //根据当前滚动进行对每个cell进行缩放
  //首先获取 当前rect范围内的 attributes对象
  let array = super.layoutAttributesForElements(in: rect)
  private let ScaleFactor:CGFloat = 0.001//缩放因子
  //计算缩放比 首先计算出整体中心点的X值 和每个cell的中心点X的值
  //用着两个x值的差值 ,计算出绝对值
  //colleciotnView中心点的值
  let centerX = (collectionView?.contentOffset.x)! + (collectionView?.bounds.size.width)!/2
  //循环遍历每个attributes对象 对每个对象进行缩放
  for attr in array! {
   //计算每个对象cell中心点的X值
   let cell_centerX = attr.center.x

   //计算两个中心点的便宜(距离)
   //距离越大缩放比越小,距离小 缩放比越大,缩放比最大为1,即重合
   let distance = abs(cell_centerX-centerX)
   let scale:CGFloat = 1/(1+distance*ScaleFactor)
   attr.transform3D = CATransform3DMakeScale(1.0, scale, 1.0)

  }

  return array
 }

到目前为止,我们可以得到一个缩放的效果,但是仍然没有达到我们要的效果,可视区域的cell并没有居中显示,而是滑到哪里就到哪里:

如下图:

所以我们还得重写一个方法:

func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint

需要注意的两个参数:

  • proposedContentOffset :手指滑动视图最终停止的便宜量,并不是手指离开时的偏移量(congtentOffset)
  • velocity:手指滑动的速率

实现该方法:

/// <#Description#>
 ///
 /// - Parameter proposedContentOffset: 当手指滑动的时候 最终的停止的偏移量
 /// - Returns: 返回最后停止后的点
 override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
  let visibleX = proposedContentOffset.x
  let visibleY = proposedContentOffset.y
  let visibleW = collectionView?.bounds.size.width
  let visibleH = collectionView?.bounds.size.height
  //获取可视区域
  let targetRect = CGRect(x: visibleX, y: visibleY, width: visibleW!, height: visibleH!)

  //中心点的值
  let centerX = proposedContentOffset.x + (collectionView?.bounds.size.width)!/2

  //获取可视区域内的attributes对象
  let attrArr = super.layoutAttributesForElements(in: targetRect)!
  //如果第0个属性距离最小
  var min_attr = attrArr[0]
  for attributes in attrArr {
   if (abs(attributes.center.x-centerX) < abs(min_attr.center.x-centerX)) {
    min_attr = attributes
   }
  }
  //计算出距离中心点 最小的那个cell 和整体中心点的偏移
  let ofsetX = min_attr.center.x - centerX
  return CGPoint(x: proposedContentOffset.x+ofsetX, y: proposedContentOffset.y)
 }

至此,整个过程结束,其实很简单,主要是对这几个方法理解!

最后代码下载:

github下载地址:点这里

本地下载地址:http://xiazai.jb51.net/201707/yuanma/ScrollCardDemo(jb51.net).rar

总结

以上就是这篇文章的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • iOS swift实现转场动画的方法示例

    转场动画介绍 转场动画在我们日常开发中是经常遇到的,所谓转场动画,就是一个控制器的view切到另一个控制器的view上过程中过的动画效果.本例子是实现了在导航控制器的titleView边上慢慢弹出一个控制器.下面话不多说,来一起看看详细的介绍: 效果图: 专场前 专场后 示例代码 首先自定义一个animator类.在需要转场的控制器内,设置代理 //需要设置转场动画的控制器titleViewVc.transitioningDelegate = aniamator//这里的animator是ani

  • Swift洗牌动画效果的实现方法

    目标效果: 点击动画按钮之后每张牌各自旋转 散开到屏幕上半部分的任意位置之后回到初始位置 比较像LOL男刀的技能动画 : ) 1: 创建卡牌对象 for _ in 0...49 { let cardSet = UIImageView(image: UIImage(named: "cardBackLandscape")) self.view.addSubview(cardSet) cardSet.frame = self.landscapeCardBack.frame self.card

  • 利用Swift实现各类的CATransition动画详解

    前言 最近因为工作的需要,打算用swift重构现有项目,实现过程中发现用到了很多系统的动画实现,因为之前的都是用OC实现的,这里主要是把一些动画效果来通过swift实现一下. 这篇文章主要是实现一下CATransition动画的不同效果. 第一步 创建一个swift文件并声明相应的枚举类型 enum TransitionAnimType : Int { case fade = 0, //淡入淡出 push, //推挤 reveal, //揭开 moveIn, //覆盖 cube, //立方体 s

  • Swift语言实现地图坐标弹跳动画

    下面应用Swift语言做地图坐标实现弹簧跳动的效果,具体实现方法如下所示: iOS动画大概分这几种: CoreAnimation动画(基础)UIView动画(animateWithDuration开头的函数,带弹簧特效)UIDynamic动画(有物理引擎) 上次写弹跳动画,由于刚开始学,就用了最基础的CA动画,但是因为自己不会写KeyFrame,所以还引用了一个开源库来实现下坠的弹跳效果,这样固然是实现了需求,但是一点都不优雅--从iOS7开始,有了2.3两种动画,就不再需要用老的CA动画去一点

  • Swift自定义iOS中的TabBarController并为其添加动画

    自定义TabBarController 有时候默认的TabBarController不能满足我们的开发需求,比如你想用彩色的图标,系统却只调用图标的轮廓,所以我们需要自己定义一下TabBar. 方法一:修改TabBarController中的TabBar 新建 CustomTabBarController 类继承自 UITabBarController,并在Storyboard中设置: 首先自定义 tabBar 的背景,在 viewDidLoad() 方法中添加: 复制代码 代码如下: // 用

  • 利用swift实现卡片横向滑动动画效果的方法示例

    本文主要给大家介绍了关于利用swift实现卡片横向滑动动画效果的相关资料,分享出来供大家参考学习,下面来一起看看详细的介绍吧. 根据惯例,首先上效果图: 那天去面试,面试官突然拿出手机点开了一个app,自个在那点了一会,然后问我 这个效果怎么实现,当时一看可以滑动,肯定用scrollView 或者 collectionView实现,就大概的说了下.今天刚好闲下来,就敲一敲这个效果. 先来分析下这个效果: 卡片是横向滚动,并且每个卡片的位置都是保持在屏幕中间的,而且 左右相邻的卡片都露出来一点边

  • jQuery实现菜单感应鼠标滑动动画效果的方法

    本文实例讲述了jQuery实现菜单感应鼠标滑动动画效果的方法.分享给大家供大家参考.具体分析如下: 此代码测试环境为IE9 以及GG.FF浏览器,IE8及以下浏览器可能不支持,希望理解. 这款JS鼠标滑动效果使用jQuery实现简单动画的方法,而且也惊喜的发现,jquery有更好的书写方法,可以连写,在animate方法前加上stop方法就可实现鼠标移出后,不再执行滑动效果. 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 T

  • vue动画效果实现方法示例

    本文实例讲述了vue动画效果实现方法.分享给大家供大家参考,具体如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>www.jb51.net vue动画</title> <script src="https://cdn.bootcss.com/vue/2.4.4/vue.min.js&

  • jquery实现仿Flash的横向滑动菜单效果代码

    本文实例讲述了jquery实现仿Flash的横向滑动菜单效果代码.分享给大家供大家参考.具体如下: 这是一个仿Flash的jquery滑动菜单,横向,延时效果明显,如果觉得延时太长的话,自己可以修改参数,通过这个菜单主要是想向大家掌握一些jQuery生成动画的技巧,同时这也是jquery强大功能的体现. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/jquery-f-flash-style-move-menu-codes/ 具体代码如下: <!

  • 小程序实现横向滑动日历效果

    本文实例为大家分享了小程序实现横向滑动日历效果的具体代码,供大家参考,具体内容如下 <scroll-view class="scroll-view_H" scroll-x> <view class='list' style='width:{{ width }}rpx'> <view bindtap="select" wx:for="{{ calendar }}" wx:key="" wx:for-

  • 利用Flutter实现“孔雀开屏”的动画效果

    前言 今天分享一个类似"孔雀开屏"的动画效果,打开新的页面时,新的页面从屏幕右上角以圆形逐渐打开到全屏. 先来看下具体的效果 不知道这种效果大家叫什么名字?如果有更合适的名字可以在评论处告诉我,下面来说下如何实现此效果. 在使用Navigator进入一个新的页面时,通常用法如下: Navigator.of(context).push(MaterialPageRoute( builder: (context){ return PageB(); } )); MaterialPageRout

  • iOS 基本动画、关键帧动画、利用缓动函数实现物理动画效果

    iOS基本动画/关键帧动画/利用缓动函数实现物理动画效果 先说下基本动画部分 基本动画部分比较简单, 但能实现的动画效果也很局限 使用方法大致为: #1. 创建原始UI或者画面 #2. 创建CABasicAnimation实例, 并设置keypart/duration/fromValue/toValue #3. 设置动画最终停留的位置 #4. 将配置好的动画添加到layer层中 举个例子, 比如实现一个圆形从上往下移动, 上代码: //设置原始画面 UIView *showView = [[UI

  • Android编程实现ViewPager多页面滑动切换及动画效果的方法

    本文实例讲述了Android编程实现ViewPager多页面滑动切换及动画效果的方法.分享给大家供大家参考,具体如下: 一.首先,我们来看一下效果图,这是新浪微博的Tab滑动效果.我们可以手势滑动,也可以点击上面的头标进行切换.与此同方式, 白色横条会移动到相应的页卡头标下.这是一个动画效果,白条是缓慢滑动过去的.好了,接下来我们就来实现它. 二.在开始前,我们先要认识一个控件,ViewPager.它是google SDk中自带的一个附加包的一个类,可以用来实现屏幕间的切换. 这个附加包是and

  • js实现横向百叶窗效果网页切换动画效果的方法

    本文实例讲述了js实现横向百叶窗效果网页切换动画效果的方法.分享给大家供大家参考.具体分析如下: 这是一款很简洁但是效果却不错的网页切换效果,点击新网页后,网页会出现蓝白相间的百叶窗线条自动切换,直到网页全部显示完全.代码如下: 复制代码 代码如下: <html> <head> <title>js网页百叶窗动态切换效果</title> <style> <!-- .intro{ position:absolute; left:0; top:0

  • 利用JS实现文字的聚合动画效果

    前言 所谓文字聚合效果,原理就是将容器分为若干的小块,然后每个小块设置 background-poisition ,最后添加css3动画就可以了,去掉注释,也就仅仅20行的代码. 先来看看效果图: js代码如下: //c为列数,r为行数,把box划分成多少个小块 var box = document.querySelector('.boxWrap1'),c=4,r=8; //每个小块的宽高 var w = box.offsetWidth/c,h = box.offsetHeight/r; //循

随机推荐