Jab*_*Jab 213 animation uinavigationcontroller ios
我有一个基于导航的应用程序,我想改变推动和弹出动画的动画.我该怎么办?
编辑2018
这个问题有很多答案,现在已经有一段时间了,我已经重新选择了我认为现在最相关的答案.如果有人不这么认为,请在评论中告诉我
小智 264
我做了以下,它工作正常..而且简单易懂.
CATransition* transition = [CATransition animation];
transition.duration = 0.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
//transition.subtype = kCATransitionFromTop; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[[self navigationController] popViewControllerAnimated:NO];
Run Code Online (Sandbox Code Playgroud)
推送同样的事情..
Swift 3.0版本:
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionFade
self.navigationController?.view.layer.add(transition, forKey: nil)
_ = self.navigationController?.popToRootViewController(animated: false)
Run Code Online (Sandbox Code Playgroud)
jor*_*rry 256
这就是我一直设法完成这项任务的方式.
推送:
MainView *nextView=[[MainView alloc] init];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[self.navigationController pushViewController:nextView animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
[UIView commitAnimations];
[nextView release];
Run Code Online (Sandbox Code Playgroud)
对于Pop:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
[UIView commitAnimations];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelay:0.375];
[self.navigationController popViewControllerAnimated:NO];
[UIView commitAnimations];
Run Code Online (Sandbox Code Playgroud)
我还是从这个,所以我要继续前进,并更新它使用动画块这是苹果推荐的方法做动画反正得到很多反馈.
推送:
MainView *nextView = [[MainView alloc] init];
[UIView animateWithDuration:0.75
animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[self.navigationController pushViewController:nextView animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
}];
Run Code Online (Sandbox Code Playgroud)
对于Pop:
[UIView animateWithDuration:0.75
animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
}];
[self.navigationController popViewControllerAnimated:NO];
Run Code Online (Sandbox Code Playgroud)
Ted*_*Ted 29
推动
CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionFade;
//transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController pushViewController:ViewControllerYouWantToPush animated:NO];
Run Code Online (Sandbox Code Playgroud)
对于流行音乐
CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionFade;
//transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController popViewControllerAnimated:NO];
Run Code Online (Sandbox Code Playgroud)
Fat*_*tie 26
如何在基于导航的应用程序中更改Push和Pop动画...
序言 假设您是iOS开发的新手,可能来自Android.令人困惑的是,Apple提供了两个(也就是两个)转换,可以轻松使用.这些是:"交叉淡化"和"翻转".现在,两个最无用的过渡是"交叉淡入淡出"和"翻转"!没有人知道为什么Apple提供这两个无用的转换作为内置转换!所以:令人惊讶的是,如果你想做最普通的过渡,比如"滑落",你必须做大量的工作.这项工作,在这篇文章中解释.
注1:要使用Apple提供的两个中的一个(交叉淡入淡出,翻转),请在此页面上查看@PeterDeWeese的答案.
注2:几年前有一个快速而又肮脏的CATransition准转换.这是行不通的.
重复一遍:
令人惊讶的是:对于iOS,如果您只想进行最简单的转换,例如普通的滑动/滑动转换,则必须实现完整的自定义转换.
这是怎么做的......
UIViewControllerAnimatedTransitioning你需要一个属于你自己的布尔popStyle.(是弹出,还是弹出?)
你必须包括transitionDuration(琐碎)和主要的电话,animateTransition
实际上你必须为内部编写两个不同的例程animateTransition.一个用于推送,一个用于流行音乐.可能会命名他们animatePush和animatePop.在里面animateTransition,只是分支popStyle到两个例程
下面的例子做了一个简单的移动/移动
在你animatePush和animatePop日常生活中.你必须得到"从视图"和"查看".(如何做到这一点,在代码示例中显示.)
你必须 addSubview为新的"到"视图.
你必须completeTransition在你的动漫结束时打电话
那么......
class SimpleOver: NSObject, UIViewControllerAnimatedTransitioning {
var popStyle: Bool = false
func transitionDuration(
using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.20
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
if popStyle {
animatePop(using: transitionContext)
return
}
let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
let f = transitionContext.finalFrame(for: tz)
let fOff = f.offsetBy(dx: f.width, dy: 55)
tz.view.frame = fOff
transitionContext.containerView.insertSubview(tz.view, aboveSubview: fz.view)
UIView.animate(
withDuration: transitionDuration(using: transitionContext),
animations: {
tz.view.frame = f
}, completion: {_ in
transitionContext.completeTransition(true)
})
}
func animatePop(using transitionContext: UIViewControllerContextTransitioning) {
let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
let f = transitionContext.initialFrame(for: fz)
let fOffPop = f.offsetBy(dx: f.width, dy: 55)
transitionContext.containerView.insertSubview(tz.view, belowSubview: fz.view)
UIView.animate(
withDuration: transitionDuration(using: transitionContext),
animations: {
fz.view.frame = fOffPop
}, completion: {_ in
transitionContext.completeTransition(true)
})
}
}
Run Code Online (Sandbox Code Playgroud)
然后 ...
注意:奇怪的是,您只需要在"第一个"视图控制器中执行此操作.(那个"在下面".)
这样,您就弹出一个顶部,做什么.简单.
所以你的班级......
class SomeScreen: UIViewController {
}
Run Code Online (Sandbox Code Playgroud)
成为...
class FrontScreen: UIViewController,
UIViewControllerTransitioningDelegate, UINavigationControllerDelegate {
let simpleOver = SimpleOver()
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.delegate = self
}
func navigationController(
_ navigationController: UINavigationController,
animationControllerFor operation: UINavigationControllerOperation,
from fromVC: UIViewController,
to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
simpleOver.popStyle = (operation == .pop)
return simpleOver
}
}
Run Code Online (Sandbox Code Playgroud)
而已.
完全正常推送和弹出,没有变化.要推......
let n = UIStoryboard(name: "nextScreenStoryboardName", bundle: nil)
.instantiateViewController(withIdentifier: "nextScreenStoryboardID")
as! NextScreen
navigationController?.pushViewController(n, animated: true)
Run Code Online (Sandbox Code Playgroud)
如果您愿意,可以在下一个屏幕上执行此操作:
class NextScreen: TotallyOrdinaryUIViewController {
@IBAction func userClickedBackOrDismissOrSomethingLikeThat() {
navigationController?.popViewController(animated: true)
}
}
Run Code Online (Sandbox Code Playgroud)
"就这么简单."
Cul*_*tes 19
@Magnus回答,只有Swift(2.0)
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromTop
self.navigationController!.view.layer.addAnimation(transition, forKey: nil)
let writeView : WriteViewController = self.storyboard?.instantiateViewControllerWithIdentifier("WriteView") as! WriteViewController
self.navigationController?.pushViewController(writeView, animated: false)
Run Code Online (Sandbox Code Playgroud)
一些旁注:
您也可以使用Segue执行此操作,只需在prepareForSegue或中执行此操作即可shouldPerformSegueWithIdentifier.但是,这也将保留默认动画.要解决此问题,您必须转到故事板,单击Segue,然后取消选中"Animates"框.但这会限制你的IOS 9.0及以上版本的应用程序(至少我在Xcode 7中做过).
在segue中进行操作时,最后两行应替换为:
self.navigationController?.popViewControllerAnimated(false)
Run Code Online (Sandbox Code Playgroud)
即使我设置了假,它也忽略了它.
Luc*_*nzo 16
请记住,在Swift中, 扩展绝对是你的朋友!
public extension UINavigationController {
/**
Pop current view controller to previous view controller.
- parameter type: transition animation type.
- parameter duration: transition animation duration.
*/
func pop(transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
self.addTransition(transitionType: type, duration: duration)
self.popViewControllerAnimated(false)
}
/**
Push a new view controller on the view controllers's stack.
- parameter vc: view controller to push.
- parameter type: transition animation type.
- parameter duration: transition animation duration.
*/
func push(viewController vc: UIViewController, transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
self.addTransition(transitionType: type, duration: duration)
self.pushViewController(vc, animated: false)
}
private func addTransition(transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
let transition = CATransition()
transition.duration = duration
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = type
self.view.layer.addAnimation(transition, forKey: nil)
}
}
Run Code Online (Sandbox Code Playgroud)
nic*_*mro 10
使用私人电话是一个坏主意,因为Apple不再批准那样做的应用程序.也许你可以试试这个:
//Init Animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.50];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:YES];
//Create ViewController
MyViewController *myVC = [[MyViewController alloc] initWith...];
[self.navigationController pushViewController:myVC animated:NO];
[myVC release];
//Start Animation
[UIView commitAnimations];
Run Code Online (Sandbox Code Playgroud)
由于这是谷歌的最高成绩,我认为我会分享我认为最理智的方式; 这是使用iOS 7+转换API.我使用Swift 3为iOS 10实现了这个功能.
UINavigationController如果您创建子类UINavigationController并返回符合UIViewControllerAnimatedTransitioning协议的类的实例,则将它与两个视图控制器之间的动画组合起来非常简单.
例如,这是我的UINavigationController子类:
class NavigationController: UINavigationController {
init() {
super.init(nibName: nil, bundle: nil)
delegate = self
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension NavigationController: UINavigationControllerDelegate {
public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return NavigationControllerAnimation(operation: operation)
}
}
Run Code Online (Sandbox Code Playgroud)
你可以看到我设置了UINavigationControllerDelegate自己,并在我的子类的扩展中,我实现了方法UINavigationControllerDelegate,允许你返回一个自定义动画控制器(即NavigationControllerAnimation).此自定义动画控制器将替换您的股票动画.
您可能想知道为什么我NavigationControllerAnimation通过其初始化程序将操作传递给实例.我这样做是为了在协议NavigationControllerAnimation的实现中UIViewControllerAnimatedTransitioning我知道操作是什么(即'push'或'pop').这有助于了解我应该做什么样的动画.大多数情况下,您希望根据操作执行不同的动画.
其余的很标准.在UIViewControllerAnimatedTransitioning协议中实现两个必需的功能,然后按照您喜欢的方式设置动画:
class NavigationControllerAnimation: NSObject, UIViewControllerAnimatedTransitioning {
let operation: UINavigationControllerOperation
init(operation: UINavigationControllerOperation) {
self.operation = operation
super.init()
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else { return }
let containerView = transitionContext.containerView
if operation == .push {
// do your animation for push
} else if operation == .pop {
// do your animation for pop
}
}
}
Run Code Online (Sandbox Code Playgroud)
重要的是要记住,对于每种不同类型的操作(即"推"或"弹出"),来往视图控制器将是不同的.当您处于推送操作时,视图控制器将被推送.当您处于弹出操作时,视图控制器将是正在转换到的控制器,并且视图控制器将是正在弹出的控制器.
此外,to必须将视图控制器添加为containerView转换上下文中的子视图.
动画完成后,您必须致电transitionContext.completeTransition(true).如果你正在做一个互动的转变,你必须动态地返回Bool来completeTransition(didComplete: Bool),这取决于如果过渡是在动画的最后完成.
最后(可选阅读),您可能想看看我是如何完成我正在进行的转换.这段代码有点哈哈,我写的很快,所以我不会说它是伟大的动画代码,但它仍然显示如何做动画部分.
我的过渡非常简单; 我想模仿UINavigationController通常所做的相同动画,但是我想要在新视图的同时实现旧视图控制器的1:1动画,而不是它的"顶部下一页"动画.控制器出现.这具有使两个视图控制器看起来好像彼此固定的效果.
对于推动操作,需要首先toViewController在x轴关闭屏幕上设置视图原点,将其添加为子视图,containerView通过将其设置origin.x为零来将其设置为屏幕上的动画.与此同时,我fromViewController通过将其设置origin.x在屏幕上来激活视图:
toViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.size.width, dy: 0.0)
containerView.addSubview(toViewController.view)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: [ UIViewAnimationOptions.curveEaseOut ],
animations: {
toViewController.view.frame = containerView.bounds
fromViewController.view.frame = containerView.bounds.offsetBy(dx: -containerView.frame.size.width, dy: 0)
},
completion: { (finished) in
transitionContext.completeTransition(true)
})
Run Code Online (Sandbox Code Playgroud)
流行操作基本上是相反的.添加toViewController作为子视图containerView,并在左侧fromViewController动画时向右动画toViewController:
containerView.addSubview(toViewController.view)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: [ UIViewAnimationOptions.curveEaseOut ],
animations: {
fromViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.width, dy: 0)
toViewController.view.frame = containerView.bounds
},
completion: { (finished) in
transitionContext.completeTransition(true)
})
Run Code Online (Sandbox Code Playgroud)
这是整个swift文件的要点:
https://gist.github.com/alanzeino/603293f9da5cd0b7f6b60dc20bc766be
小智 8
这很简单
self.navigationController?.view.semanticContentAttribute = .forceRightToLeft
Run Code Online (Sandbox Code Playgroud)
有UINavigationControllerDelegate和UIViewControllerAnimatedTransitioning,您可以根据需要更改动画.
例如,这是VC的垂直弹出动画:
@objc class PopAnimator: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.5
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
let containerView = transitionContext.containerView()
let bounds = UIScreen.mainScreen().bounds
containerView!.insertSubview(toViewController.view, belowSubview: fromViewController.view)
toViewController.view.alpha = 0.5
let finalFrameForVC = fromViewController.view.frame
UIView.animateWithDuration(transitionDuration(transitionContext), animations: {
fromViewController.view.frame = CGRectOffset(finalFrameForVC, 0, bounds.height)
toViewController.view.alpha = 1.0
}, completion: {
finished in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
})
}
Run Code Online (Sandbox Code Playgroud)
}
然后
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
if operation == .Pop {
return PopAnimator()
}
return nil;
}
Run Code Online (Sandbox Code Playgroud)
有用的教程 https://www.objc.io/issues/5-ios7/view-controller-transitions/
根据 swift 4更新的答案jordanperry
推动 UIViewController
let yourVC = self.storyboard?.instantiateViewController(withIdentifier: "yourViewController") as! yourViewController
UIView.animate(withDuration: 0.75, animations: {() -> Void in
UIView.setAnimationCurve(.easeInOut)
self.navigationController?.pushViewController(terms, animated: true)
UIView.setAnimationTransition(.flipFromRight, for: (self.navigationController?.view)!, cache: false)
})
Run Code Online (Sandbox Code Playgroud)
对于流行音乐
UIView.animate(withDuration: 0.75, animations: {() -> Void in
UIView.setAnimationCurve(.easeInOut)
UIView.setAnimationTransition(.flipFromLeft, for: (self.navigationController?.view)!, cache: false)
})
navigationController?.popViewController(animated: false)
Run Code Online (Sandbox Code Playgroud)
这是我在Swift中做同样的事情:
推送:
UIView.animateWithDuration(0.75, animations: { () -> Void in
UIView.setAnimationCurve(UIViewAnimationCurve.EaseInOut)
self.navigationController!.pushViewController(nextView, animated: false)
UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromRight, forView: self.navigationController!.view!, cache: false)
})
Run Code Online (Sandbox Code Playgroud)
对于Pop:
实际上,我对上面的一些响应做了一点点不同 - 但由于我是Swift开发的新手,它可能不对.我已经覆盖了viewWillDisappear:animated:并在那里添加了pop代码:
UIView.animateWithDuration(0.75, animations: { () -> Void in
UIView.setAnimationCurve(UIViewAnimationCurve.EaseInOut)
UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromLeft, forView: self.navigationController!.view, cache: false)
})
super.viewWillDisappear(animated)
Run Code Online (Sandbox Code Playgroud)
您现在可以使用UIView.transition. 请注意animated:false。这适用于任何转换选项、弹出、推送或堆栈替换。
if let nav = self.navigationController
{
UIView.transition(with:nav.view, duration:0.3, options:.transitionCrossDissolve, animations: {
_ = nav.popViewController(animated:false)
}, completion:nil)
}
Run Code Online (Sandbox Code Playgroud)
@Luca Davanzo在Swift 4.2中的回答
public extension UINavigationController {
/**
Pop current view controller to previous view controller.
- parameter type: transition animation type.
- parameter duration: transition animation duration.
*/
func pop(transitionType type: CATransitionType = .fade, duration: CFTimeInterval = 0.3) {
self.addTransition(transitionType: type, duration: duration)
self.popViewController(animated: false)
}
/**
Push a new view controller on the view controllers's stack.
- parameter vc: view controller to push.
- parameter type: transition animation type.
- parameter duration: transition animation duration.
*/
func push(viewController vc: UIViewController, transitionType type: CATransitionType = .fade, duration: CFTimeInterval = 0.3) {
self.addTransition(transitionType: type, duration: duration)
self.pushViewController(vc, animated: false)
}
private func addTransition(transitionType type: CATransitionType = .fade, duration: CFTimeInterval = 0.3) {
let transition = CATransition()
transition.duration = duration
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.type = type
self.view.layer.add(transition, forKey: nil)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
183179 次 |
| 最近记录: |