iOS Segue - 从左到右 -

时间:2015-06-10 17:38:34

标签: ios swift xcode6 segue uiviewanimation

我已经阅读了有关segues的其他帖子但没有解决我的问题。

简单地说,我的ViewController被订购,就像一本书。我希望向后过渡(例如:从第9页到第8页)始终从左到右呈现(滑过)。我希望从右到左呈现前向过渡(从第9页到第10页)。

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

我的目标是,如果用户从索引跳转到第9页(例如),然后向右滑动,它将向右滑动页面并显示第8页。一旦在第8页,如果他们向左滑动该页面将向左滑动,它们将再次位于第9页。

默认情况下,我的所有ViewController都是从右到左滑动显示的。

实施例: 把它想象成一本书,如果我使用索引跳到第4章,然后向右滑动并从堆栈中弹出一个视图,我将回到索引。但是,如果您使用第394章第4章并向右滑动,则不希望返回索引!您想要转到第393页第3章的最后一页!因此导航堆栈对我没有帮助。

结束示例

详细说明: 1.我在按钮上使用新的Xcode“Show”在ViewControllers之间切换。

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

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

  3. 快速编码。

  4. 使用Xcode 6.3

  5. 我读过有动画代码。我已经阅读了可以使用的深度程序转换。只是选择我想从左边呈现的segue并轻松地反转动画,这似乎很疯狂。

    谢谢!

    尝试记录:

    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进行反刷时,会返回此错误

    This error is returned when I insert DCDC's code into an IBAction for my back-swipe

12 个答案:

答案 0 :(得分:82)

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

斯威夫特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)
                                    }
                        )
    }
}

斯威夫特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)
            }
        )
    }
}

然后在故事板中,点击您想要更改的segue。在属性检查器中,将类型更改为' Custom'并将课程更改为' SegueFromLeft'

答案 1 :(得分:41)

这是一个自定义segue类,可用于在Swift中执行从左到右的segue。它需要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)
    }
}

“后退”按钮仍会出现在转换视图控制器的导航栏中,但您可以轻松地为该视图控制器禁用/配置导航控制器。

答案 2 :(得分:11)

更新了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)
            }
        )
    }
}

答案 3 :(得分:4)

您可以在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/

答案 4 :(得分:4)

Accepted answer针对 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)
        }
    }
}

答案 5 :(得分:2)

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

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

{{1}}

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

答案 6 :(得分:1)

从右边开始。你可以像下面一样覆盖segue中的执行功能。将此函数放在自定义segue类中,并将此类分配给segue。 它适用于带导航控制器和无导航控制器的控制器

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)
                                }            }
    )
}

如果您想要左边的segue,请使用此

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

答案 7 :(得分:1)

在我的情况下,我曾经制作侧边栏菜单......

我创建了一个新的视图控制器和两个海关区域

打开菜单:

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)
    }
    )
}
}

我希望它对你有所帮助......

答案 8 :(得分:1)

更新了Swift 4的接受答案:

df
Out[12]:


    Conflict    Entries
0   Yes     manaaa
1   Yes     guyaaa
2   Yes     boyaaa
3   No  girlbbb

随意将其复制到已接受的答案中并删除此评论。 (这是一个直接的更新,没什么新的。)

答案 9 :(得分:1)

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

答案 10 :(得分:0)

嘿伙计我有完整的解决方案只需复制并通过这段代码写成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)
}

注意:使用" MyAccountViewController"更改ViewController的名称。文本。

答案 11 :(得分:0)

创建"后退按钮"像动画一样,使用它。

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)
    }
}