集合视图单元格重叠Bottomsheet中的动画

时间:2018-02-02 14:41:58

标签: ios iphone swift uicollectionview bottom-sheet

我需要应用类似底部工作表的动画,其中“收集视图”单元格在关闭时彼此重叠,而在打开底部工作表时则打开宽度。我已经使用“分页视图”和“分页”实现了底部工作表,但是需要应用动画,当底部工作表关闭时,该动画仅显示当前单元格和其后的单元格。

这是我的底片类,以及一些我想要实现的图像:

class ScrollableBottomSheetViewController: UIViewController {

    @IBOutlet var pageControl: UIPageControl!
    @IBOutlet var collection: UICollectionView!
    @IBOutlet var headerView: UIView!

    let fullView: CGFloat = 0//50

    var partialView: CGFloat {
        return UIScreen.main.bounds.height - 50
    }

    let collectionMargin = CGFloat(32)
    let itemSpacing = CGFloat(10)
    let itemHeight = CGFloat(333)
    var itemWidth = CGFloat(0)
    var currentItem = 5

    override func viewDidLoad() {
        super.viewDidLoad()

        self.definesPresentationContext = true

        self.collection.delegate = self
        self.collection.dataSource = self

        self.collection.register(UINib(nibName:"AdsCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "default")

        let gesture = UIPanGestureRecognizer.init(target: self, action: #selector(ScrollableBottomSheetViewController.panGesture))
        gesture.delegate = self
        view.addGestureRecognizer(gesture)

        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        //CGFloat(219) //
        itemWidth = UIScreen.main.bounds.width - collectionMargin * 2.0

        print(itemWidth)

        layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
        layout.headerReferenceSize = CGSize(width: collectionMargin, height: 0)
        layout.footerReferenceSize = CGSize(width: collectionMargin, height: 0)
        layout.minimumLineSpacing = itemSpacing
        layout.scrollDirection = .horizontal

        collection!.collectionViewLayout = layout
        collection?.decelerationRate = UIScrollViewDecelerationRateFast
    }

    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

        let pageWidth = Float(itemWidth + itemSpacing)
        let targetXContentOffset = Float(targetContentOffset.pointee.x)
        let contentWidth = Float(collection!.contentSize.width  )
        var newPage = Float(self.pageControl.currentPage)

        if velocity.x == 0 {
            newPage = floor( (targetXContentOffset - Float(pageWidth) / 2) / Float(pageWidth)) + 1.0
        } else {
            newPage = Float(velocity.x > 0 ? self.pageControl.currentPage + 1 : self.pageControl.currentPage - 1)

            if newPage < 0 {
                newPage = 0
            }

            if (newPage > contentWidth / pageWidth) {
                newPage = ceil(contentWidth / pageWidth) - 1.0
            }
        }

        self.pageControl.currentPage = Int(newPage)
        let point = CGPoint (x: CGFloat(newPage * pageWidth) + itemSpacing, y: targetContentOffset.pointee.y)
        targetContentOffset.pointee = point
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        prepareBackgroundView()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        UIView.animate(withDuration: 0.6, animations: { [weak self] in
            let frame = self?.view.frame
            let yComponent = self?.partialView
            self?.view.frame = CGRect(x: 0, y: yComponent!, width: frame!.width, height: frame!.height)// - 100)
        })
    }

    @objc func panGesture(_ recognizer: UIPanGestureRecognizer) {

        let translation = recognizer.translation(in: self.view)
        let velocity = recognizer.velocity(in: self.view)

        let y = self.view.frame.minY

        if (y + translation.y >= fullView) && (y + translation.y <= partialView) {
            self.view.frame = CGRect(x: 0, y: y + translation.y, width: view.frame.width, height: view.frame.height)
            recognizer.setTranslation(CGPoint.zero, in: self.view)
        }

        if recognizer.state == .ended {
            var duration = velocity.y < 0 ? Double((y - fullView) / -velocity.y) : Double((partialView - y) / velocity.y)

            duration = duration > 1.3 ? 1 : duration

            UIView.animate(withDuration: duration, delay: 0.0, options: [.allowUserInteraction], animations: {
                if velocity.y >= 0 {
                    self.view.frame = CGRect(x: 0, y: self.partialView, width: self.view.frame.width, height: self.view.frame.height)
                } else {
                    self.view.frame = CGRect(x: 0, y: self.fullView, width: self.view.frame.width, height: self.view.frame.height)
                }

            }, completion: { [weak self] _ in
                if velocity.y < 0 {
                    self?.collection.isScrollEnabled = true
                }
            })
        }
    }


    func prepareBackgroundView() {
        let blurEffect = UIBlurEffect.init(style: .dark)
        let visualEffect = UIVisualEffectView.init(effect: blurEffect)
        let bluredView = UIVisualEffectView.init(effect: blurEffect)

        bluredView.contentView.addSubview(visualEffect)
        visualEffect.frame = UIScreen.main.bounds
        bluredView.frame = UIScreen.main.bounds

        view.insertSubview(bluredView, at: 0)
    }
}

extension ScrollableBottomSheetViewController : UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "default", for: indexPath)

        return cell
    }
}

extension ScrollableBottomSheetViewController: UIGestureRecognizerDelegate {

    // Solution
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {

        let gesture = (gestureRecognizer as! UIPanGestureRecognizer)
        let direction = gesture.velocity(in: view).y

        let y = view.frame.minY

        if (y == fullView && collection.contentOffset.x == 0 && direction > 0) || (y == partialView) {
            collection.isScrollEnabled = false
        } else {
            collection.isScrollEnabled = true
        }

        return false
    }

}

Opened Opening Opened

0 个答案:

没有答案