Is there a public API for card view UI that can be seen across iOS 10?

后端 未结 4 915
盖世英雄少女心
盖世英雄少女心 2020-12-07 09:06

The Music app in iOS 10 adopts a new card-like appearance: Now Playing screen slides up, while the view below in the hierarchy zooms out, protruding slightly at the top of t

4条回答
  •  南方客
    南方客 (楼主)
    2020-12-07 09:31

    Apple show how to do this using UIViewPropertyAnimator in WWDC 2017 Session 230: Advanced Animations with UIKit

    The basic idea is that you add a child view controller, and position it mostly off-screen. When tapped/panned you animate the child view controller's frame.

    import UIKit
    
    class CardViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
    
            view.backgroundColor = .red
        }
    }
    
    class ViewController: UIViewController {
        private let cardViewController = CardViewController()
        private var cardHiddenConstraint: NSLayoutConstraint!
        private var cardVisibleConstraint: NSLayoutConstraint!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            addChild(cardViewController)
            let cardViewControllerView = cardViewController.view!
            cardViewControllerView.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(cardViewControllerView)
    
            cardHiddenConstraint = cardViewControllerView.topAnchor.constraint(equalTo: view.bottomAnchor, constant: -50)
            cardVisibleConstraint = cardViewControllerView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50)
    
            let cardViewControllerViewConstraints = [
                cardViewControllerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                cardViewControllerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                cardHiddenConstraint!,
                cardViewControllerView.heightAnchor.constraint(equalTo: view.heightAnchor)
            ]
            NSLayoutConstraint.activate(cardViewControllerViewConstraints)
    
            cardViewController.didMove(toParent: self)
    
            let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:)))
            cardViewController.view.addGestureRecognizer(tapGestureRecognizer)
        }
    
        @objc private func handleTapGesture(_ gestureRecognizer: UITapGestureRecognizer) {
            let frameAnimator = UIViewPropertyAnimator(duration: 0.3, dampingRatio: 1) {
                if self.cardHiddenConstraint.isActive {
                    self.cardHiddenConstraint.isActive = false
                    self.cardVisibleConstraint.isActive = true
                } else {
                    self.cardVisibleConstraint.isActive = false
                    self.cardHiddenConstraint.isActive = true
                }
                self.view.layoutIfNeeded()
            }
            frameAnimator.startAnimation()
        }
    }
    

提交回复
热议问题