Is there a public API for card view UI that can be seen across iOS 10?(是否有可以在 iOS 10 上看到的卡片视图 UI 的公共 API?)
问题描述
iOS 10 中的音乐应用采用了新的卡片式外观:正在播放"屏幕向上滑动,而层次结构中下方的视图缩小,在屏幕顶部略微突出.
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 the screen.
这是邮件撰写窗口中的示例:
Here is the example from Mail compose window:
这个比喻也可以在流行的播客播放器 Overcast 中看到:
This metaphor can also be seen in Overcast, the popular podcast player:
UIKit 中是否有实现这种卡片式外观的功能?
Is there a function in UIKit for achieving this card-like appearance?
推荐答案
你可以在interface builder中构建segue.从 ViewController 选择模态 segue 到 CardViewController.
You can build the segue in interface builder. Selecting modal segue from ViewController to CardViewController.
对于您的 CardViewController :
import UIKit
class CardViewController: UIViewController {
  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.commonInit()
  }
  override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: Bundle!)  {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    self.commonInit()
  }
  func commonInit() {
    self.modalPresentationStyle = .custom
    self.transitioningDelegate = self
  }
  override func viewDidLoad() {
    super.viewDidLoad()
    roundViews()
  }
  func roundViews() {
    view.layer.cornerRadius = 8
    view.clipsToBounds = true
  }
}
然后添加这个扩展:
extension CardViewController: UIViewControllerTransitioningDelegate {
  func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
    if presented == self {
      return CardPresentationController(presentedViewController: presented, presenting: presenting)
    }
    return nil
  }
  func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    if presented == self {
      return CardAnimationController(isPresenting: true)
    } else {
      return nil
    }
  }
  func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    if dismissed == self {
      return CardAnimationController(isPresenting: false)
    } else {
      return nil
    }
  }
}
最后,您还需要 2 个类:
Finally, you will need 2 more classes:
import UIKit
class CardPresentationController: UIPresentationController {
  lazy var dimmingView :UIView = {
    let view = UIView(frame: self.containerView!.bounds)
    view.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.3)
    view.layer.cornerRadius = 8
    view.clipsToBounds = true
    return view
  }()
  override func presentationTransitionWillBegin() {
    guard
      let containerView = containerView,
      let presentedView = presentedView
      else {
        return
    }
    // Add the dimming view and the presented view to the heirarchy
    dimmingView.frame = containerView.bounds
    containerView.addSubview(dimmingView)
    containerView.addSubview(presentedView)
    // Fade in the dimming view alongside the transition
    if let transitionCoordinator = self.presentingViewController.transitionCoordinator {
      transitionCoordinator.animate(alongsideTransition: {(context: UIViewControllerTransitionCoordinatorContext!) -> Void in
        self.dimmingView.alpha = 1.0
      }, completion:nil)
    }
  }
  override func presentationTransitionDidEnd(_ completed: Bool)  {
    // If the presentation didn't complete, remove the dimming view
    if !completed {
      self.dimmingView.removeFromSuperview()
    }
  }
  override func dismissalTransitionWillBegin()  {
    // Fade out the dimming view alongside the transition
    if let transitionCoordinator = self.presentingViewController.transitionCoordinator {
      transitionCoordinator.animate(alongsideTransition: {(context: UIViewControllerTransitionCoordinatorContext!) -> Void in
        self.dimmingView.alpha  = 0.0
      }, completion:nil)
    }
  }
  override func dismissalTransitionDidEnd(_ completed: Bool) {
    // If the dismissal completed, remove the dimming view
    if completed {
      self.dimmingView.removeFromSuperview()
    }
  }
  override var frameOfPresentedViewInContainerView : CGRect {
    // We don't want the presented view to fill the whole container view, so inset it's frame
    let frame = self.containerView!.bounds;
    var presentedViewFrame = CGRect.zero
    presentedViewFrame.size = CGSize(width: frame.size.width, height: frame.size.height - 40)
    presentedViewFrame.origin = CGPoint(x: 0, y: 40)
    return presentedViewFrame
  }
  override func viewWillTransition(to size: CGSize, with transitionCoordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: transitionCoordinator)
    guard
      let containerView = containerView
      else {
        return
    }
    transitionCoordinator.animate(alongsideTransition: {(context: UIViewControllerTransitionCoordinatorContext!) -> Void in
      self.dimmingView.frame = containerView.bounds
    }, completion:nil)
  }
}
和:
import UIKit
class CardAnimationController: NSObject {
  let isPresenting :Bool
  let duration :TimeInterval = 0.5
  init(isPresenting: Bool) {
    self.isPresenting = isPresenting
    super.init()
  }
}
// MARK: - UIViewControllerAnimatedTransitioning
extension CardAnimationController: UIViewControllerAnimatedTransitioning {
  func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
    return self.duration
  }
  func animateTransition(using transitionContext: UIViewControllerContextTransitioning)  {
    let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
    let fromView = fromVC?.view
    let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
    let toView = toVC?.view
    let containerView = transitionContext.containerView
    if isPresenting {
      containerView.addSubview(toView!)
    }
    let bottomVC = isPresenting ? fromVC : toVC
    let bottomPresentingView = bottomVC?.view
    let topVC = isPresenting ? toVC : fromVC
    let topPresentedView = topVC?.view
    var topPresentedFrame = transitionContext.finalFrame(for: topVC!)
    let topDismissedFrame = topPresentedFrame
    topPresentedFrame.origin.y -= topDismissedFrame.size.height
    let topInitialFrame = topDismissedFrame
    let topFinalFrame = isPresenting ? topPresentedFrame : topDismissedFrame
    topPresentedView?.frame = topInitialFrame
    UIView.animate(withDuration: self.transitionDuration(using: transitionContext),
                   delay: 0,
                   usingSpringWithDamping: 300.0,
                   initialSpringVelocity: 5.0,
                   options: [.allowUserInteraction, .beginFromCurrentState], //[.Alert, .Badge]
      animations: {
        topPresentedView?.frame = topFinalFrame
        let scalingFactor : CGFloat = self.isPresenting ? 0.92 : 1.0
        bottomPresentingView?.transform = CGAffineTransform.identity.scaledBy(x: scalingFactor, y: scalingFactor)
    }, completion: {
      (value: Bool) in
      if !self.isPresenting {
        fromView?.removeFromSuperview()
      }
    })
    if isPresenting {
      animatePresentationWithTransitionContext(transitionContext)
    } else {
      animateDismissalWithTransitionContext(transitionContext)
    }
  }
  func animatePresentationWithTransitionContext(_ transitionContext: UIViewControllerContextTransitioning) {
    let containerView = transitionContext.containerView
    guard
      let presentedController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to),
      let presentedControllerView = transitionContext.view(forKey: UITransitionContextViewKey.to)
      else {
        return
    }
    // Position the presented view off the top of the container view
    presentedControllerView.frame = transitionContext.finalFrame(for: presentedController)
    presentedControllerView.center.y += containerView.bounds.size.height
    containerView.addSubview(presentedControllerView)
    // Animate the presented view to it's final position
    UIView.animate(withDuration: self.duration, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.0, options: .allowUserInteraction, animations: {
      presentedControllerView.center.y -= containerView.bounds.size.height
    }, completion: {(completed: Bool) -> Void in
      transitionContext.completeTransition(completed)
    })
  }
  func animateDismissalWithTransitionContext(_ transitionContext: UIViewControllerContextTransitioning) {
    let containerView = transitionContext.containerView
    guard
      let presentedControllerView = transitionContext.view(forKey: UITransitionContextViewKey.from)
      else {
        return
    }
    // Animate the presented view off the bottom of the view
    UIView.animate(withDuration: self.duration, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.0, options: .allowUserInteraction, animations: {
      presentedControllerView.center.y += containerView.bounds.size.height
    }, completion: {(completed: Bool) -> Void in
      transitionContext.completeTransition(completed)
    })
  }
}
最后,为了动画 CardViewController 关闭,将关闭按钮挂钩到 FirstResponder 选择 dismiss 并将此方法添加到 视图控制器:
Finally, in order to animate the CardViewController closing, hook your closing button to FirstResponder selecting dismiss and add this method to ViewController:
func dismiss(_ segue: UIStoryboardSegue) {
    self.dismiss(animated: true, completion: nil)
}
                        这篇关于是否有可以在 iOS 10 上看到的卡片视图 UI 的公共 API?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:是否有可以在 iOS 10 上看到的卡片视图 UI 的公共 API?
				
        
 
            
        - android 4中的android RadioButton问题 2022-01-01
 - 想使用ViewPager,无法识别android.support.*? 2022-01-01
 - 如何检查发送到 Android 应用程序的 Firebase 消息的传递状态? 2022-01-01
 - 使用自定义动画时在 iOS9 上忽略 edgesForExtendedLayout 2022-01-01
 - 在测试浓缩咖啡时,Android设备不会在屏幕上启动活动 2022-01-01
 - Android - 拆分 Drawable 2022-01-01
 - MalformedJsonException:在第1行第1列路径中使用JsonReader.setLenient(True)接受格式错误的JSON 2022-01-01
 - 用 Swift 实现 UITextFieldDelegate 2022-01-01
 - Android viewpager检测滑动超出范围 2022-01-01
 - Android - 我如何找出用户有多少未读电子邮件? 2022-01-01
 
				
				
				
				