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

 更新时间:2017年07月21日 09:28:19   作者:醉春风  
卡片横向滑动动画效果相信对大家来说都不陌生,下面这篇文章主要给大家介绍了关于利用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

总结

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

相关文章

  • Swift中定义单例的方法实例

    Swift中定义单例的方法实例

    Swift中单例的写法有很多种,下面这篇文章主要给大家介绍了关于Swift中定义单例的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-03-03
  • 详解Swift中enum枚举类型的用法

    详解Swift中enum枚举类型的用法

    Swift中通过enum关键字可以直接创建出枚举对象,而且可以使用switch和case语句来进行流程控制,十分强大和灵活,这里我们就来详解Swift中enum枚举类型的用法
    2016-06-06
  • Swift编程中的一些类型转换方法详解

    Swift编程中的一些类型转换方法详解

    这篇文章主要介绍了Swift编程中的一些类型转换方法详解,是Swift入门学习中的基础知识,需要的朋友可以参考下
    2015-11-11
  • 详解Swift面向对象编程中的方法(method)

    详解Swift面向对象编程中的方法(method)

    既然面向对象那就一定会有method,方法和面向过程语言中的function函数并没什么区别,只不过方法在面向对象语言中可以被类来约束作用域,这里我们就来详解Swift面向对象编程中的方法(method)
    2016-07-07
  • swift中自定义正则表达式运算符=~详解

    swift中自定义正则表达式运算符=~详解

    这篇文章主要给大家介绍了关于swift中自定义正则表达式运算符=~的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-12-12
  • Swift实现文件压缩和解压示例代码

    Swift实现文件压缩和解压示例代码

    本篇文章主要介绍了Swift实现文件压缩和解压示例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • Swift实现表格视图单元格单选(1)

    Swift实现表格视图单元格单选(1)

    这篇文章主要为大家详细介绍了Swift实现表格视图单元格单选,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • swift内存管理指针类型使用实例详解

    swift内存管理指针类型使用实例详解

    这篇文章主要为大家介绍了swift内存管理指针类型使用实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • 在Swift中如何使用正则表达式详解

    在Swift中如何使用正则表达式详解

    正则表达式是对字符串操作的一种逻辑公式,相信大家应该都不陌生,下面这篇文章主要给大家介绍了关于在Swift中如何使用正则表达式的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-09-09
  • Swift3.0 GCD定时器的使用DEMO

    Swift3.0 GCD定时器的使用DEMO

    这篇文章主要介绍了Swift3.0 GCD定时器的使用,实现倒计时,UIDatePicker的使用, 仿写一个活动倒计时的DEMO,需要的朋友可以参考下
    2017-02-02

最新评论