【问题标题】:How to make Segue animation Horizontal without UINavigationController?如何在没有 UINavigationController 的情况下使 Segue 动画水平?
【发布时间】:2016-02-23 00:05:33
【问题描述】:

我使用的是UISplitViewController,带有MasterViewControllerDetailViewController,没有UINavigationControllers。

目前master->detail的segue动画,由

触发
performSegueWithIdentifier("showDetail", sender: self)

包含从底部向上显示的DetailViewController

如何使动画向左显示?

【问题讨论】:

  • 你能添加你的故事板的截图和你用来调用performSegueWithIdentifier("showDetail", sender: self)的代码sn-p吗?

标签: ios swift uinavigationcontroller segue uisplitviewcontroller


【解决方案1】:

我最近需要更好地控制转场的执行方式,因此我创建了自定义转场类,它们都在不同方向上执行过渡。这是其中一种实现:

Swift 2.x

override func perform() {

    //credits to http://www.appcoda.com/custom-segue-animations/

    let firstClassView = self.sourceViewController.view
    let secondClassView = self.destinationViewController.view

    let screenWidth = UIScreen.mainScreen().bounds.size.width
    let screenHeight = UIScreen.mainScreen().bounds.size.height

    secondClassView.frame = CGRectMake(screenWidth, 0, screenWidth, screenHeight)

    if let window = UIApplication.sharedApplication().keyWindow {

        window.insertSubview(secondClassView, aboveSubview: firstClassView)

        UIView.animateWithDuration(0.4, animations: { () -> Void in

            firstClassView.frame = CGRectOffset(firstClassView.frame, -screenWidth, 0)
            secondClassView.frame = CGRectOffset(secondClassView.frame, -screenWidth, 0)

            }) {(Finished) -> Void in

                self.sourceViewController.navigationController?.pushViewController(self.destinationViewController, animated: false)

        }

    }

}

这个将有一个“从右到左”的过渡。您可以根据需要修改此函数,只需更改源视图控制器和目标视图控制器的初始位置和结束位置。

另外不要忘记,您需要将您的 segue 标记为“自定义 segue”,并将新类分配给它。

更新:添加了 Swift 3 版本

斯威夫特 3

override func perform() {

    //credits to http://www.appcoda.com/custom-segue-animations/

    let firstClassView = self.source.view
    let secondClassView = self.destination.view

    let screenWidth = UIScreen.main.bounds.size.width
    let screenHeight = UIScreen.main.bounds.size.height

    secondClassView?.frame = CGRect(x: screenWidth, y: 0, width: screenWidth, height: screenHeight)

    if let window = UIApplication.shared.keyWindow {

        window.insertSubview(secondClassView!, aboveSubview: firstClassView!)

        UIView.animate(withDuration: 0.4, animations: { () -> Void in

            firstClassView?.frame = (firstClassView?.frame.offsetBy(dx: -screenWidth, dy: 0))!
            secondClassView?.frame = (secondClassView?.frame.offsetBy(dx: -screenWidth, dy: 0))!

        }, completion: {(Finished) -> Void in

            self.source.navigationController?.pushViewController(self.destination, animated: false)

        }) 

    }

}

【讨论】:

  • 在 Swift 3 中为我工作,只需要从编译器中进行很多建议的更正。
  • 谢谢。我现在也添加了 Swift 3 版本。干杯
  • 在此更改之后。转到预览控制器不起作用。 self.dismiss(animated: true, completion: nil) 以前为我工作
  • dismiss 删除模态呈现的控制器
  • @Armin 你应该如何关闭视图控制器self.dismiss(animated: true, completion: nil) 似乎不起作用?
【解决方案2】:

在 UINavigationControllers 中嵌入您的视图控制器。

根据 SplitViewController 模板:

在较小的设备上,它必须使用 Master 的 navigationController。

此外,这个问题已经回答了hereherehere

更多来自View Controller Programming Guide

有两种方法可以在屏幕上显示视图控制器:将其嵌入 容器视图控制器或呈现它。容器视图控制器 提供应用的主要导航......

在故事板中,在导航控制器中嵌入东西并不难。点击你要嵌入的视图控制器,然后编辑器->嵌入->导航控制器。

【讨论】:

  • 没有 UINavigationController 就不可能吗?
  • 不情愿是什么?如果你不想要navBar,只需在DetailViewController的viewDidLoad中说self.navigationController.navBarHidden = true
  • 我刚刚在MasterViewController和DetailViewController之间插入了一个UINavigationController,但它仍然从底部显示
  • 您是否在界面构建器中将过渡类型从“呈现模式”更改为“显示”?
  • @MichaëlAzevedo 模态是没有导航控制器的 splitViewController 中 showDetail 的默认转换。他很困扰,因为主视图控制器没有嵌入到导航控制器中,所以它不能推送细节视图控制器,我们忘了告诉他这样做。
【解决方案3】:

--Swift 3.0--

Armin 的解决方案适用于 swift 3。 新建 -> 文件 -> Cocoa Touch 类 -> 类:...(子类:UIStoryboardSegue)。

import UIKit

class SlideHorSegue: UIStoryboardSegue {
    override func perform() {

        //credits to http://www.appcoda.com/custom-segue-animations/

        let firstClassView = self.source.view
        let secondClassView = self.destination.view

        let screenWidth = UIScreen.main.bounds.size.width
        let screenHeight = UIScreen.main.bounds.size.height

        secondClassView?.frame = CGRect(x: screenWidth, y: 0, width: screenWidth, height: screenHeight)

        if let window = UIApplication.shared.keyWindow {

            window.insertSubview(secondClassView!, aboveSubview: firstClassView!)

            UIView.animate(withDuration: 0.4, animations: { () -> Void in

                firstClassView?.frame = (firstClassView?.frame)!.offsetBy(dx: -screenWidth, dy: 0)
                secondClassView?.frame = (secondClassView?.frame)!.offsetBy(dx: -screenWidth, dy: 0)

            }) {(Finished) -> Void in

                self.source.navigationController?.pushViewController(self.destination, animated: false)

            }

        }

    }

}

在故事板中:将您的转场标记为“自定义转场”,并将新类分配给它。

注意:如果您的 detailesVC 中有 UIScrollView,这将不起作用。

【讨论】:

  • 在此更改之后。转到预览控制器不起作用。 self.dismiss(animated: true, completion: nil) 以前为我工作
  • 如何去上一个视图控制器?
【解决方案4】:

听起来好像新的视图控制器正在模态显示。如果您将 detailViewController 嵌入到 UINavigationController 中并按下新控制器,它将从右到左进行动画处理,并且默认情况下也应该显示一个后退按钮。

【讨论】:

  • 我刚刚在MasterViewController和DetailViewController之间插入了一个UINavigationController,但它仍然从底部显示
【解决方案5】:

当你有一个紧凑宽度的屏幕时,“显示细节” segue 会自动退回到 modal segue。所以你的 DetailViewController 会出现垂直作为默认的模态segue。

您可以使用 UIViewControllerTransitioningDelegate 自定义模态转场的动画。

下面是一个实现横向动画的例子:
1.设置transitioningDelegate及其委托方法

class MasterViewController: UITableViewController,UIViewControllerTransitioningDelegate {

//prepare for segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "showDetail" {
        let detailVC = segue.destinationViewController as! DetailViewController
        detailVC.transitioningDelegate = self
 //     detailVC.detailItem = object//Configure detailVC
    } 
}

//UIViewControllerTransitioningDelegate
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return LeftTransition()
}

func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    let leftTransiton = LeftTransition()
    leftTransiton.dismiss = true
    return leftTransiton
}

}    

2:自定义 UIViewControllerAnimatedTransitioning : LeftTransition

import UIKit

class LeftTransition: NSObject ,UIViewControllerAnimatedTransitioning {
var dismiss = false

func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
    return 2.0
}

    func animateTransition(transitionContext: UIViewControllerContextTransitioning){
    // Get the two view controllers
    let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
    let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
    let containerView = transitionContext.containerView()!

    var originRect = containerView.bounds
    originRect.origin = CGPointMake(CGRectGetWidth(originRect), 0)

    containerView.addSubview(fromVC.view)
    containerView.addSubview(toVC.view)

    if dismiss{
        containerView.bringSubviewToFront(fromVC.view)
        UIView.animateWithDuration(transitionDuration(transitionContext), animations: { () -> Void in
                fromVC.view.frame = originRect
            }, completion: { (_ ) -> Void in
                fromVC.view.removeFromSuperview()
                transitionContext.completeTransition(true )
        })
    }else{
        toVC.view.frame = originRect
        UIView.animateWithDuration(transitionDuration(transitionContext),
            animations: { () -> Void in
                toVC.view.center = containerView.center
            }) { (_) -> Void in
                fromVC.view.removeFromSuperview()
                transitionContext.completeTransition(true )
        }
    }
}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    • 2022-12-17
    • 1970-01-01
    • 2020-10-21
    相关资源
    最近更新 更多