我正在使用presentViewController呈现新屏幕
let dashboardWorkout = DashboardWorkoutViewController()
presentViewController(dashboardWorkout, animated: true, completion: nil)
这将显示从下到上的新屏幕,但我希望不使用即可从右到左显示UINavigationController
。
我使用的是Xib而不是情节提要,该怎么办?
我正在使用presentViewController呈现新屏幕
let dashboardWorkout = DashboardWorkoutViewController()
presentViewController(dashboardWorkout, animated: true, completion: nil)
这将显示从下到上的新屏幕,但我希望不使用即可从右到左显示UINavigationController
。
我使用的是Xib而不是情节提要,该怎么办?
Answers:
是否使用xib
或storyboard
正在使用都没关系。通常,当您将视图控制器推入Presentor时,使用从右向左过渡UINavigiationController
。
更新
新增计时功能 kCAMediaTimingFunctionEaseInEaseOut
示例项目与斯威夫特4实现加入GitHub上
迅捷3和4.2
let transition = CATransition()
transition.duration = 0.5
transition.type = CATransitionType.push
transition.subtype = CATransitionSubtype.fromRight
transition.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut)
view.window!.layer.add(transition, forKey: kCATransition)
present(dashboardWorkout, animated: false, completion: nil)
对象
CATransition *transition = [[CATransition alloc] init];
transition.duration = 0.5;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[transition setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[self.view.window.layer addAnimation:transition forKey:kCATransition];
[self presentViewController:dashboardWorkout animated:false completion:nil];
斯威夫特2.x
let transition = CATransition()
transition.duration = 0.5
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromRight
transition.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut)
view.window!.layer.addAnimation(transition, forKey: kCATransition)
presentViewController(dashboardWorkout, animated: false, completion: nil)
在自定义转换的情况下,方法中的animated
参数presentViewController
似乎并不重要。它可以是任何值,true
或者false
。
Swift 3的存在/消失的完整代码
extension UIViewController {
func presentDetail(_ viewControllerToPresent: UIViewController) {
let transition = CATransition()
transition.duration = 0.25
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromRight
self.view.window!.layer.add(transition, forKey: kCATransition)
present(viewControllerToPresent, animated: false)
}
func dismissDetail() {
let transition = CATransition()
transition.duration = 0.25
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
self.view.window!.layer.add(transition, forKey: kCATransition)
dismiss(animated: false)
}
}
阅读所有答案,看不到正确的解决方案。正确的方法是为呈现的VC委托创建自定义UIViewControllerAnimatedTransitioning。
因此,它假定需要执行更多步骤,但是结果却更具可定制性,并且没有副作用,例如从视图移到呈现的视图。
因此,假设您有一些ViewController,并且有一种显示方法
var presentTransition: UIViewControllerAnimatedTransitioning?
var dismissTransition: UIViewControllerAnimatedTransitioning?
func showSettings(animated: Bool) {
let vc = ... create new vc to present
presentTransition = RightToLeftTransition()
dismissTransition = LeftToRightTransition()
vc.modalPresentationStyle = .custom
vc.transitioningDelegate = self
present(vc, animated: true, completion: { [weak self] in
self?.presentTransition = nil
})
}
presentTransition
并dismissTransition
用于为视图控制器设置动画。因此,您将ViewController应用于UIViewControllerTransitioningDelegate
:
extension ViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return presentTransition
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return dismissTransition
}
}
因此,最后一步是创建您的自定义过渡:
class RightToLeftTransition: NSObject, UIViewControllerAnimatedTransitioning {
let duration: TimeInterval = 0.25
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let container = transitionContext.containerView
let toView = transitionContext.view(forKey: .to)!
container.addSubview(toView)
toView.frame.origin = CGPoint(x: toView.frame.width, y: 0)
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: {
toView.frame.origin = CGPoint(x: 0, y: 0)
}, completion: { _ in
transitionContext.completeTransition(true)
})
}
}
class LeftToRightTransition: NSObject, UIViewControllerAnimatedTransitioning {
let duration: TimeInterval = 0.25
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let container = transitionContext.containerView
let fromView = transitionContext.view(forKey: .from)!
container.addSubview(fromView)
fromView.frame.origin = .zero
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseIn, animations: {
fromView.frame.origin = CGPoint(x: fromView.frame.width, y: 0)
}, completion: { _ in
fromView.removeFromSuperview()
transitionContext.completeTransition(true)
})
}
}
在当前上下文中显示该代码视图控制器时,您可以从那时开始进行自定义。另外,您可能还会看到customUIPresentationController
也很有用(使用传递UIViewControllerTransitioningDelegate
)
您还可以使用自定义segue。
迅捷5
class SegueFromRight: UIStoryboardSegue {
override func perform() {
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: src.view.frame.size.width, y: 0)
UIView.animate(withDuration: 0.25,
delay: 0.0,
options: UIView.AnimationOptions.curveEaseInOut,
animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
},
completion: { finished in
src.present(dst, animated: false, completion: nil)
})
}
}
试试这个,
let animation = CATransition()
animation.duration = 0.5
animation.type = kCATransitionPush
animation.subtype = kCATransitionFromRight
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
vc.view.layer.addAnimation(animation, forKey: "SwitchToView")
self.presentViewController(vc, animated: false, completion: nil)
这vc
是dashboardWorkout
您的情况下的viewcontroller 。
class AA: UIViewController
func goToBB {
let bb = .. instantiateViewcontroller, storyboard etc .. as! AlreadyOnboardLogin
let tr = CATransition()
tr.duration = 0.25
tr.type = kCATransitionMoveIn // use "MoveIn" here
tr.subtype = kCATransitionFromRight
view.window!.layer.add(tr, forKey: kCATransition)
present(bb, animated: false)
bb.delegate, etc = set any other needed values
}
然后 ...
func dismissingBB() {
let tr = CATransition()
tr.duration = 0.25
tr.type = kCATransitionReveal // use "Reveal" here
tr.subtype = kCATransitionFromLeft
view.window!.layer.add(tr, forKey: kCATransition)
dismiss(self) .. or dismiss(bb), or whatever
}
CATransition
是不是真的做这项工作。
请注意,您会得到恼人的十字渐变为黑色,不幸的是破坏了效果。
许多开发人员(例如我)真的不喜欢使用NavigationController
。通常,在您进行过程中以即席方式呈现尤其灵活,特别是对于不寻常和复杂的应用程序。但是,“添加”导航控制器并不困难。
只需在情节提要上,转到条目VC,然后单击“嵌入式->在导航控制器中”。真的就是这样。要么,
在 didFinishLaunchingWithOptions
如果您愿意可以很容易地构建导航控制器
您甚至根本不需要将变量保留在任何地方,因为 .navigationController
它始终可以作为属性使用-很简单。
确实,一旦有了navigationController,在屏幕之间进行转换就变得很简单了,
let nextScreen = instantiateViewController etc as! NextScreen
navigationController?
.pushViewController(nextScreen, animated: true)
你可以 pop
。
(旧的滑行速度较低,而新的滑行速度较低。)
通常且令人惊讶的是,您通常必须努力进行完全自定义的过渡。
即使您只想要最简单,最常见的移入/移出过渡,也必须执行完整的自定义过渡。
幸运的是,为此,在此QA上有一些剪切和粘贴的样板代码... https://stackoverflow.com/a/48081504/294884。新年快乐2018!
导入UIKit并为UIViewController创建一个扩展:
extension UIViewController {
func transitionVc(vc: UIViewController, duration: CFTimeInterval, type: CATransitionSubtype) {
let customVcTransition = vc
let transition = CATransition()
transition.duration = duration
transition.type = CATransitionType.push
transition.subtype = type
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
view.window!.layer.add(transition, forKey: kCATransition)
present(customVcTransition, animated: false, completion: nil)
}}
简单调用后:
let vC = YourViewController()
transitionVc(vc: vC, duration: 0.5, type: .fromRight)
从左到右:
let vC = YourViewController()
transitionVc(vc: vC, duration: 0.5, type: .fromleft)
您可以根据自己的喜好更改时长...
试试这个。
let transition: CATransition = CATransition()
transition.duration = 0.3
transition.type = kCATransitionReveal
transition.subtype = kCATransitionFromLeft
self.view.window!.layer.addAnimation(transition, forKey: nil)
self.dismissViewControllerAnimated(false, completion: nil)
let transition = CATransition()
transition.duration = 0.25
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
tabBarController?.view.layer.add(transition, forKey: kCATransition)
self.navigationController?.popToRootViewController(animated: true)
使用Swift在iOS中从右到左显示视图控制器
func FrkTransition()
{
let transition = CATransition()
transition.duration = 2
transition.type = kCATransitionPush
transitioningLayer.add(transition,forKey: "transition")
// Transition to "blue" state
transitioningLayer.backgroundColor = UIColor.blue.cgColor
transitioningLayer.string = "Blue"
}
引用者: [ https://developer.apple.com/documentation/quartzcore/catransition] [1 ]
如果您想保留Apple的经典动画,而又没有看到使用CATransition()看到的“黑色”过渡,则有一个更好的解决方案对我有用。只需使用popToViewController方法。
您可以在其中寻找所需的viewController
self.navigationController.viewControllers // Array of VC that contains all VC of current stack
您可以通过搜索restoreIdentifier查找所需的viewController。
注意:例如,如果要浏览3个视图控制器,并且到达最后一个时,则要弹出第一个。在这种情况下,您将丢失对有效的SECOND视图控制器的引用,因为popToViewController已覆盖它。顺便说一句,有一个解决方案:您可以在popToViewcontroller之前轻松保存以后需要的VC。它对我很好。
这为我工作:
self.navigationController?.pushViewController(controller, animated: true)