gpt4 book ai didi

ios - 是否有可以在 iOS 10 中看到的卡片 View UI 的公共(public) API?

转载 作者:IT王子 更新时间:2023-10-29 05:06:13 25 4
gpt4 key购买 nike

iOS 10 中的音乐应用采用了新的卡片式外观:“正在播放”屏幕向上滑动,而层次结构下方的 View 缩小,在屏幕顶部略微突出。

music app card interface

这是邮件撰写窗口中的示例:

mail compose card interface

这个比喻也可以在流行的播客播放器 Overcast 中看到:

overcast card interface

UIKit 中有实现卡片式外观的函数吗?

最佳答案

您可以在界面生成器中构建转场。选择从 ViewControllerCardViewController 的模式转场。

对于您的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 个类:

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 并将此方法添加到 View Controller :

func dismiss(_ segue: UIStoryboardSegue) {
self.dismiss(animated: true, completion: nil)
}

关于ios - 是否有可以在 iOS 10 中看到的卡片 View UI 的公共(public) API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43530231/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com