本文实例为大家分享了Swift实现3D轮播图效果的具体代码,供大家参考,具体内容如下整天逛淘宝,偶尔有一天看到其中的展示页有个看起来很炫的效果,闲来无事就试着写一个出来,先来看效果:
简单记一下思路,这里我选择使用UICollectionView控件,先根据其复用和滚动的特性做出无限轮播的效果,关键代码://数据源数组let totalCount = 100 var models: [String] = [String]() {didSet {//判断元素个数if models.count < 2 {collectionView.isScrollEnabled = false}//网上的找来的一个办法添加100组数据源对应的索引数组indexArr for _ in 0..func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {//找到滚动停止的点对应的collectionView的indexPath let point = self.convert(collectionView.center, to: collectionView) let index = collectionView.indexPathForItem(at: point) let indexpath = (index?.row ?? 0) % models.count
collectionView.scrollToItem(at: IndexPath(item: totalCount/2 * models.count + indexpath, section: 0), at: .centeredHorizontally, animated: false)}以上是滚动的处理,接下来就是item的渐变效果处理,看到这种情况就想到要写一个UICollectionViewFlowLayout
类供collectionView使用,UICollectionViewFlowLayout是管理item怎么展示用的,首先重写展示视图内的layoutAttributes方法,在此方法中找到attribute对应的item及其属性,和collectionView的偏移量和中心点,进行一系列的计算:
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
//集合视图的宽高(这里默认宽高相等)
let itemHeight = self.collectionView?.frame.height ?? 0//可是视图内的attributes数组let array = super.layoutAttributesForElements(in: rect)//item透明度开始变化时的item的中心点x let centerX = self.collectionView!.contentOffset.x + itemHeight/2 print(self.collectionView?.contentOffset.x ?? 0)
for attributes in array! {//开始变化时的item的中心点x 与 实际中心点相比较let value = attributes.center.x - centerX let delta = abs(value)//设置缩放比例,此处4*itemHeight可根据缩放效果进行修改let scale = 1 - delta/(4*itemHeight)
//设置缩放比例attributes.transform = CGAffineTransform.init(scaleX: scale, y: scale)//层次关系,设置此属性使item依次上下排列attributes.zIndex = Int(1 - abs(delta))
//value<=0表示向左移动,最前面的item停止一段距离if value <= 0{//实际中心点与开始变化时的item的中心点小于等于设定的边界值if delta >= 0 && delta <= itemHeight{//item的中心点固定不变attributes.center.x = centerX//根据推进值,改变item的透明度,此处的delta>10是想让item有一个达到目标区域时有一个停顿效果而不是直接进入改变透明度的阶段attributes.alpha = (delta > 10) ? (1 - delta/(itemHeight/4)) : 1//设置缩放比例,停顿阶段不进行缩放attributes.transform = CGAffineTransform.init(scaleX: 1, y: 1)} else {//移动大于边界值,就是从停顿阶段到透明度改变,此处是下一个item上来,当前item透明度变为0 attributes.alpha = 0}}}return array}解决最后一个小问题,拖动iitem开始滚动,滚动结束时让它自动滚动到网格区域,而不是停在当前或许不适当的地方,重写UICollectionViewFlowLayout另一个方法:override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
let targetRect = CGRect(x: proposedContentOffset.x, y: 0.0, width: self.collectionView!.bounds.size.width, height: self.collectionView!.bounds.size.height)
//目标区域中包含的cell let attrArray = super.layoutAttributesForElements(in: targetRect) as! [UICollectionViewLayoutAttributes]//collectionView落在屏幕重点的x坐标let horizontalCenterX = proposedContentOffset.x + (self.collectionView?.frame.height ?? 0)/2 var offsetAdjustment = CGFloat(MAXFLOAT) for layoutAttributes in attrArray {
let itemHorizontalCenterX = layoutAttributes.center.x//找出离中心店最近的if (abs(itemHorizontalCenterX-horizontalCenterX) < abs(offsetAdjustment)) {offsetAdjustment = itemHorizontalCenterX - horizontalCenterX}}
//返回collectionView最终停留的位置return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y)
}//当collectionView的显示范围发生改变的时候,是否重新布局override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {return true}最后一个方法不写看不到渐变的效果。
源码地址:
点击打开链接以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:Swift调用Objective-C编写的API实例swift5.3 UIColor使用十六进制颜色的方法实例详解Swift 结构体Swift 进阶 —— map 和 flatMap的使用Swift 5.1 之类型转换与模式匹配的教程详解如何使用Swift来实现一个命令行工具的方法Swift4使用GCD实现计时器Swift实现倒计时5秒功能Swift 中如何使用 Option Pattern 改善可选项的 API 设计
