在Swift中滑动Segue

时间:2015-11-10 06:27:11

标签: ios swift swift2

我正在尝试创建一个水平滑动的segue,它将从一个视图平移到下一个视图。我已经向下平移了,但它显示了一个区域中的黑色空间,它应该显示下一个视图控制器。这就是我实现我的segue

的方式
class SlideSegue: UIStoryboardSegue {

    enum Direction {
        case Left
        case Right
    }

    // MARK: - Properties
    var direction = Direction.Left

    // MARK: -
    override func perform() {
        let srcVc = self.sourceViewController
        let destVc = self.destinationViewController


        let destView = destVc.view.snapshotViewAfterScreenUpdates(true)
        var frame = destView.frame
        frame.origin.x = CGFloat(valForDirection()) * srcVc.view.frame.width
        destView.frame = frame
        srcVc.view.addSubview(destView)

        UIView.animateWithDuration(0.3, animations: { () -> Void in
            let x = CGFloat(self.valForDirection()) * srcVc.view.bounds.width
            let slide = CGAffineTransformMakeTranslation(x, 0)
            srcVc.view.transform = slide
            }) { (finished: Bool) -> Void in
                srcVc.presentViewController(destVc, animated: false, completion: nil)

                destView.removeFromSuperview()
        }

    }

    func valForDirection() -> Int {
        return direction == Direction.Left ? -1 : 1
    }

}

class SlideLeftSegue: SlideSegue {
    override func perform() {
        self.direction = Direction.Left
        super.perform()
    }
}

class SlideRightSegue: SlideSegue {
    override func perform() {
        self.direction = Direction.Right
        super.perform()
    }
}

修改

编辑(已解决) 这是最终的工作解决方案,感谢下面的两个答案

class SlideSegue: UIStoryboardSegue {

    enum Direction: Int {
        case Left = 1
        case Right = -1
    }

    // MARK: - Properties
    var direction = Direction.Left

    // MARK: -
    override func perform() {
        let srcVc = self.sourceViewController
        let destVc = self.destinationViewController


        let destView = destVc.view.snapshotViewAfterScreenUpdates(true)
        var frame = destView.frame
        frame.origin.x = CGFloat(direction.rawValue) * srcVc.view.frame.width
        destView.frame = frame
        srcVc.view.addSubview(destView)

        UIView.animateWithDuration(0.3, animations: { () -> Void in
            let x = -CGFloat(self.direction.rawValue) * srcVc.view.bounds.width
            let slide = CGAffineTransformMakeTranslation(x, 0)
            srcVc.view.transform = slide
            }) { (finished: Bool) -> Void in
                srcVc.presentViewController(destVc, animated: false, completion: nil)

                destView.removeFromSuperview()
        }

    }

}

class SlideLeftSegue: SlideSegue {
    override func perform() {
        self.direction = Direction.Left
        super.perform()
    }
}

class SlideRightSegue: SlideSegue {
    override func perform() {
        self.direction = Direction.Right
        super.perform()
    }
}

3 个答案:

答案 0 :(得分:2)

尝试将您的SlideSegue课改为此课程,删除valForDirection功能(如果您不介意的话,我可以自由地重构一下)

class FirstCustomSegue: UIStoryboardSegue {

    enum Direction: Int {
        case Left = 1
        case Right = -1
    }

    // MARK: - Properties
    var direction = Direction.Left

    // MARK: - Perform
    override func perform() {
        let srcVc = self.sourceViewController
        let destVc = self.destinationViewController

        destVc.view.frame = srcVc.view.frame
        destVc.view.frame.origin.x = CGFloat(direction.rawValue) * srcVc.view.frame.width
        let window = UIApplication.sharedApplication().keyWindow
        window?.insertSubview(destVc.view, aboveSubview: srcVc.view)

        UIView.animateWithDuration(0.3, animations: { () -> Void in
            let x = CGFloat(self.direction.rawValue) * srcVc.view.bounds.width
            destVc.view.frame.origin.x = 0
            srcVc.view.frame.origin.x = -x

            }) { (finished: Bool) -> Void in
                srcVc.presentViewController(destVc, animated: false, completion: nil)
        }
    }

}

我还没有测试过这个,所以我不能100%确定语法是否正确。

更新:MatthewLuiHK似乎是正确的。你所要做的就是翻转价值观。

致谢:http://www.appcoda.com/custom-segue-animations/

答案 1 :(得分:2)

我通过以下修改进行测试,效果很好。

func valForDirection() -> Int {
    return direction == Direction.Left ? 1 : -1
}

如果向左滑动,destView的originX应该是它的宽度。 else -width。

答案 2 :(得分:0)

这段代码对我有用,它显示VC下方的新视图控制器被刷掉,但是当segue完成时,视图控制器会短暂地闪烁黑色。

任何想法如何确保每次平稳过渡?

import UIKit

class SlideSegue: UIStoryboardSegue {

enum Direction: Int {
    case Left = 1
    case Right = -1
}

// MARK: - Properties
var direction = Direction.Left

// MARK: -
override func perform() {
    let srcVc = self.sourceViewController
    let destVc = self.destinationViewController


    let destView = destVc.view.snapshotViewAfterScreenUpdates(true)
    var frame = destView.frame
    frame.origin.x = CGFloat(direction.rawValue) * srcVc.view.frame.width
    destView.frame = frame
    srcVc.view.addSubview(destView)

    UIView.animateWithDuration(0.3, animations: { () -> Void in
        let x = -CGFloat(self.direction.rawValue) * srcVc.view.bounds.width
        let slide = CGAffineTransformMakeTranslation(x, 0)
        srcVc.view.transform = slide
        }) { (finished: Bool) -> Void in
            srcVc.presentViewController(destVc, animated: false, completion: nil)

            destView.removeFromSuperview()
    }
}
}

class SlideLeftSegue: SlideSegue {
override func perform() {
    self.direction = Direction.Left
    super.perform()
}
}

class SlideRightSegue: SlideSegue {
override func perform() {
    self.direction = Direction.Right
    super.perform()
}
}

非常感谢