不使用 Storyboard segues 的自定义视图转换 (Swift)
Posted
技术标签:
【中文标题】不使用 Storyboard segues 的自定义视图转换 (Swift)【英文标题】:Custom View Transition without use of Storyboard segues (Swift) 【发布时间】:2015-07-27 00:02:36 【问题描述】:我有两个视图,我想做一个滑动样式的过渡,当有一个 segue 可以操作时我已经这样做了,但是我这里没有一个,所以我不确定如何应用我的动画类。我在课堂上只有:
let stb = UIStoryboard(name: "Walkthrough", bundle: nil)
let walkthrough = stb.instantiateViewControllerWithIdentifier("walk") as! BWWalkthroughViewController
self.presentViewController(walkthrough, animated: true, completion: nil)
我想申请应用以下自定义segue:
class CustomSegue: UIStoryboardSegue
override func perform()
// Assign the source and destination views to local variables.
var firstVCView = self.sourceViewController.view as UIView!
var secondVCView = self.destinationViewController.view as UIView!
// Get the screen width and height.
let screenWidth = UIScreen.mainScreen().bounds.size.width
let screenHeight = UIScreen.mainScreen().bounds.size.height
// Specify the initial position of the destination view.
secondVCView.frame = CGRectMake(0.0, screenHeight, screenWidth, screenHeight)
// Access the app's key window and insert the destination view above the current (source) one.
let window = UIApplication.sharedApplication().keyWindow
window?.insertSubview(secondVCView, aboveSubview: firstVCView)
// Animate the transition.
UIView.animateWithDuration(0.2, animations: () -> Void in
firstVCView.frame = CGRectOffset(firstVCView.frame, -screenWidth, 0.0)
secondVCView.frame = CGRectOffset(secondVCView.frame, -screenWidth, 0.0)
) (Finished) -> Void in
self.sourceViewController.presentViewController(self.destinationViewController as! UIViewController,
animated: false,
completion:nil)
我不能让它工作请任何指针?
【问题讨论】:
请注意,您不需要使用UIScreen.mainScreen()
,它实际上可能会造成一些混乱。另请注意,如果您将动画减慢到 4 秒,它似乎会显示不受欢迎的伪影。
【参考方案1】:
虽然第一个答案应该是“使用 Storyboard Segues”,但您可以通过这种方式解决自定义转换:
通用方法
-
修改您的
CustomSegue
以采用 both UIStoryboardSegue
和 UIViewControllerAnimatedTransitioning
协议。
重构 CustomSegue
以便两个协议都可以使用动画。
为导航控制器设置一个delegate
,它可以是它自己,以提供自定义转换到push
和pop
让animationControllerForOperation
创建并返回CustomSegue
的实例,并带有您选择的标识符。
概述
// Adopt both protocols
class CustomSegue: UIStoryboardSegue, UIViewControllerAnimatedTransitioning
func animate(firstVCView:UIView,
secondVCView:UIView,
containerView:UIView,
transitionContext: UIViewControllerContextTransitioning?)
// factored transition code goes here
) (Finished) -> Void in
if let context = transitionContext
// UIViewControllerAnimatedTransitioning
else
// UIStoryboardSegue
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval
// return timing
func animateTransition(transitionContext: UIViewControllerContextTransitioning)
// Perform animate using transitionContext information
// (UIViewControllerAnimatedTransitioning)
override func perform()
// Perform animate using segue (self) variables
// (UIStoryboardSegue)
以下是完整代码示例。它已经过测试。请注意,我还修复了原始问题中的一些动画错误,并添加了淡入效果来强调动画。
CustomSegue 类
// Animation for both a Segue and a Transition
class CustomSegue: UIStoryboardSegue, UIViewControllerAnimatedTransitioning
func animate(firstVCView:UIView,
secondVCView:UIView,
containerView:UIView,
transitionContext: UIViewControllerContextTransitioning?)
// Get the screen width and height.
let offset = secondVCView.bounds.width
// Specify the initial position of the destination view.
secondVCView.frame = CGRectOffset(secondVCView.frame, offset, 0.0)
firstVCView.superview!.addSubview(secondVCView)
secondVCView.alpha = 0;
// Animate the transition.
UIView.animateWithDuration(self.transitionDuration(transitionContext!),
animations: () -> Void in
firstVCView.frame = CGRectOffset(firstVCView.frame, -offset, 0.0)
secondVCView.frame = CGRectOffset(secondVCView.frame, -offset, 0.0)
secondVCView.alpha = 1; // emphasis
) (Finished) -> Void in
if let context = transitionContext
context.completeTransition(!context.transitionWasCancelled())
else
self.sourceViewController.presentViewController(
self.destinationViewController as! UIViewController,
animated: false,
completion:nil)
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval
return 4 // four seconds
// Perform Transition (UIViewControllerAnimatedTransitioning)
func animateTransition(transitionContext: UIViewControllerContextTransitioning)
self.animate(transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!.view,
secondVCView: transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!.view,
containerView: transitionContext.containerView(),
transitionContext: transitionContext)
// Perform Segue (UIStoryboardSegue)
override func perform()
self.animate(self.sourceViewController.view!!,
secondVCView: self.destinationViewController.view!!,
containerView: self.sourceViewController.view!!.superview!,
transitionContext:nil)
宿主 ViewController 类
class ViewController: UIViewController, UINavigationControllerDelegate
override func viewDidLoad()
super.viewDidLoad()
self.navigationController?.delegate = self
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?
switch operation
case .Push:
return CustomSegue(identifier: "Abc", source: fromVC, destination: toVC)
default:
return nil
【讨论】:
谢谢,我看不到如何将它应用到我的代码中? 太棒了,我想在家里应用它。今晚下班后我会去,太棒了! 我应用了您的代码,但无法为宽度和高度属性设置动画。你知道这是为什么吗? 试过了,transitionContext不能为nil。作为transitionDuration(使用:transitionContext!)隐含不是零“transitionContext!”。以上是关于不使用 Storyboard segues 的自定义视图转换 (Swift)的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS 5 上使用 Segues/Storyboard 弹出当前视图
无法使用自定义 segue 和 Storyboard 调整 UIViewController 的大小
IOS/Objective-C:在没有 Storyboard Segue 的情况下可以在模态转换中使用自定义 Segue?
XCode/iOS:将 UIGestureRecognizerDelegate 添加到 UIViewController 后,Storyboard Segue 事件不起作用
使用没有 Storyboard Segues 的 UIViewControllerAnimatedTransitioning