iOS 继续 - 从左到右 -

iOS Segue - Left to Right -

我已经阅读了关于 segues 的其他帖子,但 none 解决了我的问题。

简单地说,我的ViewController是有序的,就像一本书。我想要向后过渡(例如:从第 9 页到第 8 页)始终从左到右呈现(滑过)。我想要向前过渡(从第 9 页到第 10 页)从右到左呈现。

是的,如果您逐页翻阅,我的导航控制器后退按钮(左上角)会像这样显示。但是,如果您从索引处跳转,则导航控制器上的后退功能会将您带回到索引处。

我的 objective 是,如果用户从索引跳转到第 9 页(例如),然后向右滑动,它会向右轻弹页面并显示第 8 页。一旦进入页面8,如果他们向左轻拂,页面将向左轻拂,他们将再次出现在第 9 页。

默认情况下,我所有的 ViewController 都是通过从右向左滑入来呈现的。

示例: 把它想象成一本书,如果我使用索引跳到第 4 章,然后向右滑动并从堆栈中弹出一个视图,我就会回到索引处。但是,如果您在第 4 章第 394 页上向右滑动,您就不想返回索引!您想转到第 3 章的最后一页,第 393 页!所以导航堆栈对我没有帮助。

示例结束

详情: 1. 我在点击按钮时使用新的 Xcode "Show" 在 ViewController 之间切换。

  1. 我正在使用导航控制器,用于左上角的 "Back" 按钮功能。这使用导航堆栈并且工作正常。

  2. 但是我在底部有自己的自定义导航栏(后退按钮、主页按钮、索引按钮、前进按钮)和手势。这些是我想要的类似书籍的功能。

  3. 编码 swift。

  4. 使用 Xcode6.3

我看到有动画代码。我读过可以使用的深度编程转换。似乎没有简单的方法来 select 我想从左侧呈现的 segues 并轻松反转动画,这似乎很疯狂。

谢谢!

尝试记录:

I tried DCDC's code:
    UIView.transitionWithView(self.window!, duration: 0.5, options:.TransitionFlipFromLeft, animations: { () -> Void in
            self.window!.rootViewController = mainVC
            }, completion:nil)

当我将 DCDC 的代码插入 IBAction 以进行向后滑动时返回此错误

您可以在 transitionWithView 方法中使用预先声明的过渡类型

UIView.transitionWithView(self.window!, duration: 0.5, options:.TransitionFlipFromLeft, animations: { () -> Void in
            self.window!.rootViewController = mainVC
            }, completion:nil)

我想 .TransitionFlipFromLeft 是我想要的

要完成任务,请将一个新的视图控制器拖到您的情节提要中并使用一些 id 命名它。这将是过渡的目的地。

然后从代码

实例化这个视图控制器
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let mainVC = storyboard.instantiateViewControllerWithIdentifier("someViewController") as! UIViewController

您可以在 IBAction 中或例如在 ViewDidLoad 中执行此操作,但 IBAction 可能是更好的选择。注意为故事板和视图控制器键入正确的标识符。此外,您必须声明您的 appDelegate 实例。这是实现的 IBAction

@IBAction func push(sender: UIButton) {

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let mainVC = storyboard.instantiateViewControllerWithIdentifier("secondVC") as! UIViewController
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

    UIView.transitionWithView(appDelegate.window!, duration: 0.5, options: .TransitionFlipFromLeft , animations: { () -> Void in
        appDelegate.window!.rootViewController = mainVC
        }, completion:nil)
}

如果这不是您所期望的,您可能想要制作自定义动画。这篇文章真的很有帮助:http://mathewsanders.com/animated-transitions-in-swift/

听起来您只是想从 UINavigationController 的堆栈中弹出一个视图控制器,就像默认的后退按钮一样。

您可以做以下两件事之一。最简单的方法是将自定义后退按钮连接到调用 popViewControllerAnimated():

的 IBAction
@IBAction func tappedCustomBackButton(sender: AnyObject) {
    self.navigationController?.popViewControllerAnimated(true)
}

或者您可以创建一个 unwind segue 从您的第二个视图控制器回到您的第一个。

这是一个自定义转场 class,您可以使用它在 Swift 中执行从左到右的转场。它需要 QuartzCore 框架和最少的动画。

Swift 2.2

import UIKit
import QuartzCore

class SegueFromLeft: UIStoryboardSegue {

    override func perform() {
        let src: UIViewController = self.sourceViewController
        let dst: UIViewController = self.destinationViewController
        let transition: CATransition = CATransition()
        let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.duration = 0.25
        transition.timingFunction = timeFunc
        transition.type = kCATransitionPush
        transition.subtype = kCATransitionFromLeft
        src.navigationController!.view.layer.addAnimation(transition, forKey: kCATransition)
        src.navigationController!.pushViewController(dst, animated: false)
    }

}

Swift 3.0

import UIKit
import QuartzCore

class SegueFromLeft: UIStoryboardSegue {

    override func perform() {
        let src: UIViewController = self.source
        let dst: UIViewController = self.destination
        let transition: CATransition = CATransition()
        let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.duration = 0.25
        transition.timingFunction = timeFunc
        transition.type = kCATransitionPush
        transition.subtype = kCATransitionFromLeft
        src.navigationController!.view.layer.add(transition, forKey: kCATransition)
        src.navigationController!.pushViewController(dst, animated: false)
    }
}

"Back" 按钮仍会出现在过渡视图控制器的导航栏中,但您可以轻松地 disable/configure 该视图控制器的导航控制器。

这就是我在不需要导航控制器的情况下实现效果的方法。试试这个:

Swift 4:

import UIKit
class SegueFromLeft: 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: .curveEaseInOut,
                         animations: {
                                dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
                                },
                        completion: { finished in
                                src.present(dst, animated: false, completion: nil)
                                    }
                        )
    }
}

Swift 3:

import UIKit

class SegueFromLeft: UIStoryboardSegue
{
    override func perform()
    {
        let src = self.sourceViewController
        let dst = self.destinationViewController

        src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
        dst.view.transform = CGAffineTransformMakeTranslation(-src.view.frame.size.width, 0)

        UIView.animateWithDuration(0.25,
            delay: 0.0,
            options: UIViewAnimationOptions.CurveEaseInOut,
            animations: {
                dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
            },
            completion: { finished in
                src.presentViewController(dst, animated: false, completion: nil)
            }
        )
    }
}

然后在故事板中,单击您要更改的转场。在属性检查器中将类型更改为 'Custom' 并将 class 更改为 'SegueFromLeft'

来自 right.You 的 Segue 可以覆盖 segue 中的 perform 函数,如下所示。将此函数放入自定义转场 class 并将此 class 分配给转场。 它适用于带导航控制器和不带导航控制器的控制器

override func perform()
{
    let src = self.sourceViewController
    print(src)
    let dst = self.destinationViewController
    print(dst)

    src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
    dst.view.transform = CGAffineTransformMakeTranslation(src.view.frame.size.height, 0)

    UIView.animateWithDuration(0.35,
                               delay: 0.0,
                               options: UIViewAnimationOptions.CurveEaseInOut,
                               animations: {
                                dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
        },
                               completion: { finished in
                                if let navController = src.navigationController {
                                    navController.pushViewController(dst, animated: false)

                                } else {
                                    src.presentViewController(dst, animated: false, completion: nil)
                                }            }
    )
}

如果你想从左边开始转场,那么使用这个

CGAffineTransformMakeTranslation(-src.view.frame.size.height, 0)

就我而言,我曾经制作侧边栏菜单...

我创建了一个新的视图控制器和两个自定义 segues

打开菜单:

import Foundation
import UIKit

class SegueFromLeft: UIStoryboardSegue {

  override func perform() {

    let src = self.source as UIViewController
    let dst = self.destination as UIViewController

    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: UIViewAnimationOptions.curveEaseInOut,
                               animations: {
                                dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
    },
                               completion: { finished in
                                src.present(dst, animated: false, completion: nil)
    }
    )

}

}

关闭菜单:

import Foundation
import UIKit

class SegueFromRight: UIStoryboardSegue {

override func perform() {

    let src = self.source as UIViewController
    let dst = self.destination as UIViewController

    src.view.superview?.insertSubview(dst.view, belowSubview: src.view)
    src.view.transform = CGAffineTransform(translationX: 0, y: 0)

    UIView.animate(withDuration: 0.25,
                               delay: 0.0,
                               options: UIViewAnimationOptions.curveEaseInOut,
                               animations: {
                                src.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0)
    },
                               completion: { finished in
                                src.dismiss(animated: false, completion: nil)
    }
    )
}
}

希望对你有所帮助...

更新了 Swift 3 中接受的答案:

import UIKit

class SegueFromLeft: 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: UIViewAnimationOptions.curveEaseInOut,
            animations: {
                dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
            },
            completion: { finished in
                src.present(dst, animated: false, completion: nil)
            }
        )
    }
}

嘿伙计,我有完整的解决方案,只需复制并粘贴这段代码 swift 3.

func menu(){
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "MyAccountViewController") as! MyAccountViewController

    let transition: CATransition = CATransition()
    let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    transition.duration = 0.5
    transition.timingFunction = timeFunc
    transition.type = kCATransitionPush
    transition.subtype = kCATransitionFromLeft
    self.navigationController?.view.layer.add(transition, forKey: kCATransition)
    self.navigationController?.pushViewController(vc, animated: false)
}

注意:将 ViewController 的名称更改为 "MyAccountViewController" 文本。

更新为 Swift 3(截至 2017 年 6 月)

左到右

继续
import UIKit

class SegueFromLeft: UIStoryboardSegue {
    override func perform() {
        let src = self.source       //new enum
        let dst = self.destination  //new enum

        src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
        dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0) //Method call changed
        UIView.animate(withDuration: 0.25, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: { 
            dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
        }) { (finished) in
            src.present(dst, animated: false, completion: nil) //Method call changed
        }
    }
}

从右到左

继续
import UIKit

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*2, y: 0) //Double the X-Axis
        UIView.animate(withDuration: 0.25, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: { 
            dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
        }) { (finished) in
            src.present(dst, animated: false, completion: nil)
        }
    }
}

要创建类似 "back button" 的动画,请使用它。

class SegueRightToLeft: UIStoryboardSegue {

override func perform() {
    let src = self.source       //new enum
    let dst = self.destination  //new enum

    src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
    dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width/2, y: 0) 
    //slice the x axis translation in half

    UIView.animate(withDuration: 0.25, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
        dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
    }) { (finished) in
        src.present(dst, animated: false, completion: nil)
    }
}

已将已接受的答案更新为 Swift 4:

class SegueFromLeft: 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: UIViewAnimationOptions.curveEaseInOut,
                               animations: {
                                dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
    },
                               completion: { finished in
                                src.present(dst, animated: false, completion: nil)
    })
     }
}

随时将此复制到已接受的答案中并删除此评论。 (这是直接更新,没有什么新东西。)

聚会有点晚了我知道...它 self.view.window 不是 self.window