标签栏点击前ViewDisappear动画
ViewDisappear animation before tabbar click
我有一个 TabBarController,它有 3 个 navigationController,每个都有对应的 viewController:AViewController、BViewController 和 CViewController。第一个有一个 UIView 元素,我想在 viewDisappears 使用时针对它 运行 动画:
UIView.animateWithDuration(duration, delay: 0.0, options: .CurveEaseOut, animations: {
期间...
override func viewWillDisappear(animated: Bool) {
如果用户点击标签栏中的第 2 项或第 3 项,我希望该动画首先发生,然后将用户带到第 2 项或第 3 项。
问题是,当用户单击不同的项目时,TabBarController 中的这段代码在我的 ViewController A
中的 viewwillDisappears 之前首先被触发
override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
然后我的动画没有 运行。
我应该将动画放在哪里,以便在 运行 秒之前将用户带到标签栏中的其他项目?
您可以从 UITabBarControllerDelegate
、return false 实现 tabBarController:shouldSelectViewController:
,播放您的动画,然后以编程方式更改选项卡。
您需要编写自己的 UIViewControllerAnimatedTransitioning (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewControllerAnimatedTransitioning_Protocol/)
试试这个代码:
TabBarController.swift
import UIKit
class TabBarController: UITabBarController, UITabBarControllerDelegate {
var buttons = [UIButton]()
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
var newViewControllers = [UIViewController]()
for index in 0..<2 {
let viewController = ViewController()
var tabBarItem = UITabBarItem()
switch index {
case 0:
viewController.view.backgroundColor = UIColor.blueColor()
viewController.label.textColor = UIColor.whiteColor()
tabBarItem = UITabBarItem(tabBarSystemItem: .More, tag: index)
case 1:
viewController.view.backgroundColor = UIColor.greenColor()
viewController.label.textColor = UIColor.blackColor()
tabBarItem = UITabBarItem(tabBarSystemItem: .Favorites, tag: index)
default:
break
}
viewController.label.text = "Text \(index)"
viewController.tabBarItem = tabBarItem
newViewControllers.append(viewController)
//tabBar.items![index] = tabBarItem
}
selectedIndex = 0
// = newViewControllers
setViewControllers(newViewControllers, animated: false)
// Do any additional setup after loading the view, typically from a nib.
}
func tabBarController(tabBarController: UITabBarController, animationControllerForTransitionFromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let fromIndex = tabBarController.viewControllers!.indexOf(fromVC)!
let toIndex = tabBarController.viewControllers!.indexOf(toVC)!
let tabChangeDirection: TabOperationDirection = toIndex < fromIndex ? .Left : .Right
let transitionType = SDETransitionType.TabTransition(tabChangeDirection)
let slideAnimationController = SlideAnimationController(type: transitionType)
return slideAnimationController
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
let label = UILabel(frame: CGRect(x: 40, y: 60, width: 80, height: 40))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(label)
}
var labelHidden = false {
willSet(value) {
if value {
self.label.frame.origin.y = -40
} else {
self.label.frame.origin.y = 60
}
}
}
}
SlideAnimationController.swift (resource: https://github.com/seedante/iOS-ViewController-Transition-Demo)
import UIKit
enum SDETransitionType{
case NavigationTransition(UINavigationControllerOperation)
case TabTransition(TabOperationDirection)
case ModalTransition(ModalOperation)
}
enum TabOperationDirection{
case Left, Right
}
enum ModalOperation{
case Presentation, Dismissal
}
class SlideAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
private var transitionType: SDETransitionType
init(type: SDETransitionType) {
transitionType = type
super.init()
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.3
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
guard let containerView = transitionContext.containerView(), fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey), toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else{
return
}
let fromView = fromVC.view
let toView = toVC.view
var translation = containerView.frame.width
var toViewTransform = CGAffineTransformIdentity
var fromViewTransform = CGAffineTransformIdentity
switch transitionType{
case .NavigationTransition(let operation):
translation = operation == .Push ? translation : -translation
toViewTransform = CGAffineTransformMakeTranslation(translation, 0)
fromViewTransform = CGAffineTransformMakeTranslation(-translation, 0)
case .TabTransition(let direction):
translation = direction == .Left ? translation : -translation
fromViewTransform = CGAffineTransformMakeTranslation(translation, 0)
toViewTransform = CGAffineTransformMakeTranslation(-translation, 0)
case .ModalTransition(let operation):
translation = containerView.frame.height
toViewTransform = CGAffineTransformMakeTranslation(0, (operation == .Presentation ? translation : 0))
fromViewTransform = CGAffineTransformMakeTranslation(0, (operation == .Presentation ? 0 : translation))
}
switch transitionType{
case .ModalTransition(let operation):
switch operation{
case .Presentation: containerView.addSubview(toView)
case .Dismissal: break
}
default: containerView.addSubview(toView)
}
toView.transform = toViewTransform
if let fromVC = fromVC as? ViewController {
UIView.animateWithDuration(0.3, delay: 0.0, options: .CurveEaseOut, animations: {
fromVC.labelHidden = true
}, completion: {
bool in
UIView.animateWithDuration(self.transitionDuration(transitionContext), animations: {
fromView.transform = fromViewTransform
toView.transform = CGAffineTransformIdentity
}, completion: { finished in
fromView.transform = CGAffineTransformIdentity
toView.transform = CGAffineTransformIdentity
let isCancelled = transitionContext.transitionWasCancelled()
transitionContext.completeTransition(!isCancelled)
fromVC.labelHidden = false
})
})
}
}
}
我有一个 TabBarController,它有 3 个 navigationController,每个都有对应的 viewController:AViewController、BViewController 和 CViewController。第一个有一个 UIView 元素,我想在 viewDisappears 使用时针对它 运行 动画:
UIView.animateWithDuration(duration, delay: 0.0, options: .CurveEaseOut, animations: {
期间...
override func viewWillDisappear(animated: Bool) {
如果用户点击标签栏中的第 2 项或第 3 项,我希望该动画首先发生,然后将用户带到第 2 项或第 3 项。
问题是,当用户单击不同的项目时,TabBarController 中的这段代码在我的 ViewController A
中的 viewwillDisappears 之前首先被触发override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
然后我的动画没有 运行。
我应该将动画放在哪里,以便在 运行 秒之前将用户带到标签栏中的其他项目?
您可以从 UITabBarControllerDelegate
、return false 实现 tabBarController:shouldSelectViewController:
,播放您的动画,然后以编程方式更改选项卡。
您需要编写自己的 UIViewControllerAnimatedTransitioning (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewControllerAnimatedTransitioning_Protocol/)
试试这个代码:
TabBarController.swift
import UIKit
class TabBarController: UITabBarController, UITabBarControllerDelegate {
var buttons = [UIButton]()
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
var newViewControllers = [UIViewController]()
for index in 0..<2 {
let viewController = ViewController()
var tabBarItem = UITabBarItem()
switch index {
case 0:
viewController.view.backgroundColor = UIColor.blueColor()
viewController.label.textColor = UIColor.whiteColor()
tabBarItem = UITabBarItem(tabBarSystemItem: .More, tag: index)
case 1:
viewController.view.backgroundColor = UIColor.greenColor()
viewController.label.textColor = UIColor.blackColor()
tabBarItem = UITabBarItem(tabBarSystemItem: .Favorites, tag: index)
default:
break
}
viewController.label.text = "Text \(index)"
viewController.tabBarItem = tabBarItem
newViewControllers.append(viewController)
//tabBar.items![index] = tabBarItem
}
selectedIndex = 0
// = newViewControllers
setViewControllers(newViewControllers, animated: false)
// Do any additional setup after loading the view, typically from a nib.
}
func tabBarController(tabBarController: UITabBarController, animationControllerForTransitionFromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let fromIndex = tabBarController.viewControllers!.indexOf(fromVC)!
let toIndex = tabBarController.viewControllers!.indexOf(toVC)!
let tabChangeDirection: TabOperationDirection = toIndex < fromIndex ? .Left : .Right
let transitionType = SDETransitionType.TabTransition(tabChangeDirection)
let slideAnimationController = SlideAnimationController(type: transitionType)
return slideAnimationController
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
let label = UILabel(frame: CGRect(x: 40, y: 60, width: 80, height: 40))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(label)
}
var labelHidden = false {
willSet(value) {
if value {
self.label.frame.origin.y = -40
} else {
self.label.frame.origin.y = 60
}
}
}
}
SlideAnimationController.swift (resource: https://github.com/seedante/iOS-ViewController-Transition-Demo)
import UIKit
enum SDETransitionType{
case NavigationTransition(UINavigationControllerOperation)
case TabTransition(TabOperationDirection)
case ModalTransition(ModalOperation)
}
enum TabOperationDirection{
case Left, Right
}
enum ModalOperation{
case Presentation, Dismissal
}
class SlideAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
private var transitionType: SDETransitionType
init(type: SDETransitionType) {
transitionType = type
super.init()
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.3
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
guard let containerView = transitionContext.containerView(), fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey), toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else{
return
}
let fromView = fromVC.view
let toView = toVC.view
var translation = containerView.frame.width
var toViewTransform = CGAffineTransformIdentity
var fromViewTransform = CGAffineTransformIdentity
switch transitionType{
case .NavigationTransition(let operation):
translation = operation == .Push ? translation : -translation
toViewTransform = CGAffineTransformMakeTranslation(translation, 0)
fromViewTransform = CGAffineTransformMakeTranslation(-translation, 0)
case .TabTransition(let direction):
translation = direction == .Left ? translation : -translation
fromViewTransform = CGAffineTransformMakeTranslation(translation, 0)
toViewTransform = CGAffineTransformMakeTranslation(-translation, 0)
case .ModalTransition(let operation):
translation = containerView.frame.height
toViewTransform = CGAffineTransformMakeTranslation(0, (operation == .Presentation ? translation : 0))
fromViewTransform = CGAffineTransformMakeTranslation(0, (operation == .Presentation ? 0 : translation))
}
switch transitionType{
case .ModalTransition(let operation):
switch operation{
case .Presentation: containerView.addSubview(toView)
case .Dismissal: break
}
default: containerView.addSubview(toView)
}
toView.transform = toViewTransform
if let fromVC = fromVC as? ViewController {
UIView.animateWithDuration(0.3, delay: 0.0, options: .CurveEaseOut, animations: {
fromVC.labelHidden = true
}, completion: {
bool in
UIView.animateWithDuration(self.transitionDuration(transitionContext), animations: {
fromView.transform = fromViewTransform
toView.transform = CGAffineTransformIdentity
}, completion: { finished in
fromView.transform = CGAffineTransformIdentity
toView.transform = CGAffineTransformIdentity
let isCancelled = transitionContext.transitionWasCancelled()
transitionContext.completeTransition(!isCancelled)
fromVC.labelHidden = false
})
})
}
}
}