当前位置: 首页 > 面试题库 >

Swift中的自定义翻转Segue

昝晗昱
2023-03-14
问题内容

这是我的自定义Segue的代码

class FlipFromRightSegue: UIStoryboardSegue {
override func perform() {
    let source:UIViewController = self.sourceViewController as UIViewController
    let destination:UIViewController = self.destinationViewController as UIViewController

    UIView.transitionWithView(source.view, duration: 1.0, options: .CurveEaseInOut | .TransitionFlipFromRight, animations: { () -> Void in
        source.view.addSubview(destination.view)
    }) { (finished) -> Void in
        destination.view.removeFromSuperview()
        source.presentViewController(destination, animated: false, completion: nil)
    }
}
}

我以为这可行,但实际上只有在执行segue后,视图才会改变。我应该怎么做才能使视图在中间出现“翻转”时发生变化?

提前致谢。


问题答案:

从iOS
7开始,我们通常不使用自定义序列为过渡设置动画。我们要么使用标准的模态演示,指定一个modalTransitionStyle(即,可以为模态过渡选择的一些动画的固定列表),要么实现自定义动画过渡。这两个描述如下:

  1. 如果仅显示另一个视图控制器的视图,则将动画更改为翻转的简单解决方案是modalTransitionStyle在目标视图控制器中设置。您可以完全在segue属性下的Interface Builder中完成此操作。

如果要以编程方式执行此操作,则可以在目标控制器中的Swift 3中执行以下操作:

    override func viewDidLoad() {
    super.viewDidLoad()

    modalTransitionStyle = .flipHorizontal   // use `.FlipHorizontal` in Swift 2
}

然后,当您调用show/
showViewControllerpresent/时presentViewController,演示将通过水平翻转进行。而且,当您关闭视图控制器时,动画会自动为您反转。

  1. 如果需要更多控制,请在iOS 7及更高版本中使用自定义动画过渡,在其中指定modalPresentationStyle.custom。例如,在Swift 3中:
    class SecondViewController: UIViewController {
    
    let customTransitionDelegate = TransitioningDelegate()
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    
        modalPresentationStyle = .custom   // use `.Custom` in Swift 2
        transitioningDelegate = customTransitionDelegate
    }
    
    ...
    

    }

这指定了UIViewControllerTransitioningDelegatehtml" target="_blank">实例化动画控制器的。例如,在Swift 3中:

    class TransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return AnimationController(transitionType: .presenting)
    }

    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return AnimationController(transitionType: .dismissing)
    }
}

动画控制器只是做.transitionFlipFromRight一个演示,或者.transitionFlipFromLeft在Swift 3中关闭:

    class AnimationController: NSObject, UIViewControllerAnimatedTransitioning {

    enum TransitionType {
        case presenting
        case dismissing
    }

    var animationTransitionOptions: UIViewAnimationOptions

    init(transitionType: TransitionType) {
        switch transitionType {
        case .presenting:
            animationTransitionOptions = .transitionFlipFromRight
        case .dismissing:
            animationTransitionOptions = .transitionFlipFromLeft
        }

        super.init()
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        //let inView   = transitionContext.containerView
        let toView   = transitionContext.viewController(forKey: .to)?.view
        let fromView = transitionContext.viewController(forKey: .from)?.view

        UIView.transition(from: fromView!, to: toView!, duration: transitionDuration(using: transitionContext), options: animationTransitionOptions.union(.curveEaseInOut)) { finished in
            transitionContext.completeTransition(true)
        }
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 1.0
    }
}

有关iOS 7中引入的自定义过渡的更多信息,请参阅WWDC
2013视频使用视图控制器的自定义过渡。

  1. 如果应该承认上述AnimationController内容实际上是过分简化,因为我们正在使用transform(from:to:...)。这样会导致动画无法取消(以防您使用交互式过渡)。它还删除了“ from”视图本身,从iOS 8开始,这实际上就是表示控制器的工作。

因此,您真的想使用UIView.animateAPI
进行翻转动画。我很抱歉,因为以下内容涉及CATransform3D在关键帧动画中使用一些不直观的内容,但是会导致翻转动画,然后可以对其进行可取消的交互式过渡。

因此,在Swift 3中:

    class AnimationController: NSObject, UIViewControllerAnimatedTransitioning {

    enum TransitionType {
        case presenting
        case dismissing
    }

    let transitionType: TransitionType

    init(transitionType: TransitionType) {
        self.transitionType = transitionType

        super.init()
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let inView   = transitionContext.containerView
        let toView   = transitionContext.view(forKey: .to)!
        let fromView = transitionContext.view(forKey: .from)!

        var frame = inView.bounds

        func flipTransform(angle: CGFloat, offset: CGFloat = 0) -> CATransform3D {
            var transform = CATransform3DMakeTranslation(offset, 0, 0)
            transform.m34 = -1.0 / 1600
            transform = CATransform3DRotate(transform, angle, 0, 1, 0)
            return transform
        }

        toView.frame = inView.bounds
        toView.alpha = 0

        let transformFromStart:  CATransform3D
        let transformFromEnd:    CATransform3D
        let transformFromMiddle: CATransform3D
        let transformToStart:    CATransform3D
        let transformToMiddle:   CATransform3D
        let transformToEnd:      CATransform3D

        switch transitionType {
        case .presenting:
            transformFromStart  = flipTransform(angle: 0,        offset: inView.bounds.size.width / 2)
            transformFromEnd    = flipTransform(angle: -.pi,     offset: inView.bounds.size.width / 2)
            transformFromMiddle = flipTransform(angle: -.pi / 2)
            transformToStart    = flipTransform(angle: .pi,      offset: -inView.bounds.size.width / 2)
            transformToMiddle   = flipTransform(angle: .pi / 2)
            transformToEnd      = flipTransform(angle: 0,        offset: -inView.bounds.size.width / 2)

            toView.layer.anchorPoint = CGPoint(x: 0, y: 0.5)
            fromView.layer.anchorPoint = CGPoint(x: 1, y: 0.5)

        case .dismissing:
            transformFromStart  = flipTransform(angle: 0,        offset: -inView.bounds.size.width / 2)
            transformFromEnd    = flipTransform(angle: .pi,      offset: -inView.bounds.size.width / 2)
            transformFromMiddle = flipTransform(angle: .pi / 2)
            transformToStart    = flipTransform(angle: -.pi,     offset: inView.bounds.size.width / 2)
            transformToMiddle   = flipTransform(angle: -.pi / 2)
            transformToEnd      = flipTransform(angle: 0,        offset: inView.bounds.size.width / 2)

            toView.layer.anchorPoint = CGPoint(x: 1, y: 0.5)
            fromView.layer.anchorPoint = CGPoint(x: 0, y: 0.5)
        }

        toView.layer.transform = transformToStart
        fromView.layer.transform = transformFromStart
        inView.addSubview(toView)

        UIView.animateKeyframes(withDuration: self.transitionDuration(using: transitionContext), delay: 0, options: [], animations: {
            UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.0) {
                toView.alpha = 0
                fromView.alpha = 1
            }
            UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5) {
                toView.layer.transform = transformToMiddle
                fromView.layer.transform = transformFromMiddle
            }
            UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.0) {
                toView.alpha = 1
                fromView.alpha = 0
            }
            UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5) {
                toView.layer.transform = transformToEnd
                fromView.layer.transform = transformFromEnd
            }
        }, completion: { finished in
            toView.layer.transform = CATransform3DIdentity
            fromView.layer.transform = CATransform3DIdentity
            toView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
            fromView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)

            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        })
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 1.0
    }
}
  1. 仅供参考,iOS 8通过演示控制器扩展了自定义过渡模型。有关更多信息,请参阅WWDC 2014视频A Look Inside Presentation Controllers。

无论如何,如果在过渡结束时不再可见“ from”视图,则应指示演示控制器将其从视图层次结构中删除,例如:

    class PresentationController: UIPresentationController {
    override var shouldRemovePresentersView: Bool { return true }
}

而且,显然,您必须TransitioningDelegate将此演示控制器通知您:

    class TransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {

    ...

    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        return PresentationController(presentedViewController: presented, presenting: presenting)
    }            
}

此答案已针对Swift 3进行了更新。



 类似资料:
  • 问题内容: 在上面的代码中,我有2个问题:1)。它具有编译错误:’UINavigationController!’ 没有名为“ pushViewController”的成员 但是在该类中,确实有一个pushViewController方法。 2)。我必须添加注释:@objc(SEPushNoAnimationSegue),否则,在情节提要中,它只能识别随机生成的名称,例如_tcxxxxSEPush

  • 问题内容: 它允许您从调用中返回子类。 我正在尝试找出使用Swift实现相同功能的最佳方法。 我确实知道,很可能有一种更好的方法可以用Swift实现相同的目的。但是,我的类将由我无法控制的现有Obj- C库初始化。因此,它确实需要以这种方式工作并且可以从Obj-C调用。 任何指针将不胜感激。 问题答案: 我不相信Swift可以直接支持这种模式,因为初始化程序不会像在Objective C中那样返回

  • 问题内容: 我正在使用Swift在Xcode(7.0版)中创建游戏,并且我想在游戏结束时以字体“ gameOver.ttf”显示标签“ Game Over”。我已将字体添加到资源文件夹中。我不知道如何在我的代码中引用它。我可以帮忙吗?我的代码: 问题答案: 这些是向您的应用程序添加自定义字体的步骤: 在您的应用程序中添加“ gameOver.ttf”字体(确保它已包含在目标中) 修改applica

  • 问题内容: 我正在使用JSON.NET序列化一些对象,并且我想知道是否有一种简单的方法可以仅针对特定对象覆盖默认json.net转换器? 目前我有以下课程: JSON.NET当前将上述序列化为: 是否可以仅通过特定方式将其格式化为: 我对JSON.NET有点陌生。我想知道上面是否与编写自定义转换器有关。我找不到任何有关如何编写示例的具体示例。如果有人可以指出我的具体信息,我将不胜感激。 我需要找到

  • 在自定义arrayAdapter中实现自定义getFilter时遇到问题。实际上,我不知道如何实现它。尝试了各种代码,但仍然没有成功。这是我的自定义阵列适配器。 这是ListTO课程。 这是布局图。 这里的搜索关键字来自“inputSearch”编辑文本。 这是文本更改的侦听器。 谢谢

  • 本文向大家介绍C# winform自定义翻页控件详解,包括了C# winform自定义翻页控件详解的使用技巧和注意事项,需要的朋友参考一下 C#  winform中自定义的翻页控件,自己设计,供大家参考,具体内容如下 1.主要是使用控件绑定点击事件   用到的控件分别为picturebox   lable  上一页pbPage_Prev    下一页 pbPage_Next  首页 pbPage_