美文网首页
卡片式效果和转场动画

卡片式效果和转场动画

作者: 晴川历历汉阳树丶 | 来源:发表于2020-04-24 11:06 被阅读0次

1.卡片效果

卡片效果使用的事 collocationView 实现的,主要在于对UICollectionViewFlowLayout 里面方法的重写。

class LNCollectionViewLaout: UICollectionViewFlowLayout {

    public var scaleFactor:CGFloat = 0.4
    public var itemSpacing:CGFloat = 20.0

    //MARK:-  这个方法每次layout发生改变就会调用一次
    override func prepare() {
        scrollDirection = .horizontal
        minimumLineSpacing = itemSpacing
//        sectionInset = UIEdgeInsets.init(top: 150, left: itemSize.width/2, bottom: 150, right: itemSize.width/2)
        super.prepare()
    }
    
    //MARK:-  返回true frame发生变化是就允许重新布局。内部就会z重新调用prepare和layoutAttributesForElementsInRect
    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        return true
    }
    
    //MARK:-  用来计算出rect这个范围内所有的cell的UICollectionViewLayoutAttributes对象循环便利每个attribute对象m,然后修改frame,再返回给系统
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        
        let cellAttributes = super.layoutAttributesForElements(in: rect) ?? []
        let scaleFactor:CGFloat = self.scaleFactor/1000
        
        //找到当前位置的中心点
        let centerX = (collectionView?.contentOffset.x ?? 0) + (collectionView?.bounds.size.width ?? 0)/2
        
        for attribute in cellAttributes {
            let cell_centerX = attribute.center.x
            
            //计算两中心的距离
            let distance = abs(cell_centerX - centerX)
            //距离越大缩放比例就越小,越小就越大,如果cell的中心点与中心重合,那就是最大点1
            let scale:CGFloat = 1/(1+distance*scaleFactor)
            
            attribute.transform3D = CATransform3DMakeScale(1.0, scale, 1.0)
        }
        return cellAttributes
    }
    
    
    override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
        let visibleX = proposedContentOffset.x
        let visibleY = proposedContentOffset.y
        let visibleWidth = collectionView?.width ?? 0
        let visibleHeight = collectionView?.height ?? 0
        
        //可视区域
        let targetRect = CGRect.init(x: visibleX, y: visibleY, width: visibleWidth, height: visibleHeight)
        
        //中心点的值
        let centerX = proposedContentOffset.x + (collectionView?.bounds.size.width ?? 0)/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
        
//        print("ddddddd\(proposedContentOffset)")

        return CGPoint(x: proposedContentOffset.x+ofsetX, y: proposedContentOffset.y)
    }    
}

使用的时候直接用自定义的这个 layout,然后调整一下 itemSize,就可以达到效果。

获得当前屏幕显示的下标:

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let index = ((collectionView?.contentOffset.x ?? 0) - layout.sectionInset.left)/(layout.itemSize.width+layout.minimumLineSpacing)
        //对index四舍五入,当大于0.5的时候,就证明下一个cell的大部分都已经在屏幕中了,小于0.5还是自己。然后记录值,避免多次调用。
        if Int(index.rounded()) != lastIndex {
            lastIndex = Int(index.rounded())
            //下标已改变,可以做处理。
            let cell = collectionView.cellForItem(at: IndexPath.init(row: Int(index.rounded()), section: 0))
            self.collectionView.backgroundColor = cell?.backgroundColor
        }
        print("当前\(lastIndex)")
    }

cell点击居中的问题

    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    
        guard let cell = collectionView.cellForItem(at: indexPath) else {  return }
        let centerX = collectionView.contentOffset.x + collectionView.width/2
        
        //本来是要大于0也就是不在正中心就要判断不是当前选中下标,但是多次试验之后发现有很多次都不是整好等于0,所以就判断1            
        if abs(cell.centerX - centerX) > 1 {
            
            collectionView.scrollToItem(at: indexPath, at: UICollectionView.ScrollPosition.centeredHorizontally, animated: true)
        }
    }

2.转场动画

转场动画直接用的三方 Hero

pod 'Hero'

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    collectionView.deselectItem(at: indexPath, animated: true)
    
    guard let cell = collectionView.cellForItem(at: indexPath) else {  return }
    //id可以一个页面的多个view共用一个,但是会造成预期之外的效果。比如页面返回时,其他设置了这个id的视图也会跟着这个view开始动画。
    let heroId = "LNCardViewController_CardCell_\(indexPath.row)"
    cell.hero.id = heroId
    
    let showVc = ShowViewController()
    //打开效果
    showVc.hero.isEnabled = true
    showVc.contentView.backgroundColor = cell.backgroundColor
    ///需要变化动画的view,于前面的cell设置同样的id
    showVc.contentView.hero.id = heroId
    showVc.modalPresentationStyle = .fullScreen
    present(showVc, animated: true, completion: nil)
    }
}

相关文章

  • 卡片式效果和转场动画

    1.卡片效果 卡片效果使用的事 collocationView 实现的,主要在于对UICollectionView...

  • iOS 自定义转场动画

    本文记录分享下自定义转场动画的实现方法,具体到动画效果:新浪微博图集浏览转场效果、手势过渡动画、网易音乐启动屏转场...

  • iOS动画(四) --自定义转场动画

    本文记录分享下自定义转场动画的实现方法,具体到动画效果:新浪微博图集浏览转场效果、手势过渡动画、网易音乐启动屏转场...

  • Core Animation之转场动画

    1、转场动画简单介绍 CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iO...

  • Flutter - 页面转场动画

    一、页面转场动画效果

  • 动画

    CABasicAnimation基础核心动画 缩放动画 图片抖动 根据圆形的路径做移动的效果. 转场动画 创建转场...

  • iOS自定义转场动画

    关于iOS的转场动画的实现: 转场动画实际上就是对View添加的转场效果,在CATransiton就已经给我们提供...

  • iOS-自定义控制器转场动画(present/dismiss)

    一、转场动画类型 iOS控制器转场动画类型可以分为非交互式转场动画和交互式转场动画。 二、转场动画分析 2.1、转...

  • Android 动画-共享元素动画

    一、简介 首先看下转场共享元素动画的效果: 转场共享动画的代码实现: 代码很简单,startActivity 传了...

  • iOS swift转场动画by TransitioningDel

    转场动画 以我们常用的present、push转场动画为例,这种过渡性视图展示效果被抽象成UIViewContro...

网友评论

      本文标题:卡片式效果和转场动画

      本文链接:https://www.haomeiwen.com/subject/ctbxwhtx.html