在Xcode中使用无动画的Push Segue

90

我在使用Xcode的普通Storyboard和Push Segue,但是我想要一种只显示下一个视图而不是滑动下一个视图的Segue(就像当您使用选项卡栏时下一个视图只是出现的)。

有没有一种简单的方法让普通的push segues只是"出现"而不是"滑动",而无需添加自定义的segues?

一切都正常工作,我只是想在视图之间删除那个滑动动画。


我刚试图将推送segue更改为模态segue,因为这样可以让我去掉动画,但是我有一个带有顶部工具栏的表视图,将segue设置为模态会删除此顶部栏,而且我找不到任何方法将顶部栏添加回来!因此,我需要一个既不会动画过渡,又不会破坏我的表视图的解决方案。 - R2D2
11个回答

143

通过创建自定义segue(基于此链接)我能够做到这一点。

  1. 创建一个新的segue类(见下文)。
  2. 打开你的Storyboard并选择segue。
  3. 将类设置为PushNoAnimationSegue(或者任何你决定称其为的名称)。

Specify segue class in Xcode

Swift 4

import UIKit

/*
 Move to the next screen without an animation.
 */
class PushNoAnimationSegue: UIStoryboardSegue {

    override func perform() {
        self.source.navigationController?.pushViewController(self.destination, animated: false)
    }
}

Objective C

PushNoAnimationSegue.h

#import <UIKit/UIKit.h>

/*
 Move to the next screen without an animation.
 */
@interface PushNoAnimationSegue : UIStoryboardSegue

@end

PushNoAnimationSegue.m

#import "PushNoAnimationSegue.h"

@implementation PushNoAnimationSegue

- (void)perform {

    [self.sourceViewController.navigationController pushViewController:self.destinationViewController animated:NO];
}

@end

11
最佳答案。关于如何实现后向动画,你有什么想法吗? - Thomas
1
运行得非常好。这也是使用故事板segue的“正确”方法。 - Jeff Richley
背景动画的颠簸。谁想要在弹出时有动画却不想在推送时有呢? - Jonny
1
有人停止了上面答案的后退动画吗? - Imran
4
不是“解决方案”,自定义过渡效果会覆盖整个布局,就像模态推送一样,而原始的推送过渡效果会遵循window.frame、navigationController、tabBarController等。如何配置过渡效果以像推送过渡效果一样行事,而不是像模态过渡效果一样行事?或者说……这是一个价值100万美元的问题,如何在使用故事板配置常规过渡效果时指定animations=NO? - Pedro Borges
显示剩余6条评论

50

在 iOS 9 的 Interface Builder 中,您可以取消勾选 "Animates"。

在这里输入图片描述


3
这是原问题的答案!其他答案展示了如何在objc/swift代码中实现,而dtochetto仅使用Xcode(就像原问题中所要求的那样)。 - drpawelo
然而对于取消的转场,它似乎不起作用。 - Nicolas Manzini
2
这是最好和最快的解决方案,不幸的是它在iOS 8上无法工作。 - EricH206
2
@DanielT。也许你可以在Storyboard上拖动2个Segue,一个带有动画效果,另一个没有动画效果。给它们不同的“标识符(Identifier)”名称。 - AechoLiu
1
请注意,XCode只是在.storyboard文件中的segue元素中添加属性。如果您正在使用Visual Studio并且设计师中没有可用的复选标记,则可以手动编辑.storyboard文件并将animates="NO"添加到您关心的segues中。 - Wes

35

Ian的答案很好用!

如果有人需要,这是Segue的Swift版本:

已更新至Swift 5,2020年5月

PushNoAnimationSegue.swift

import UIKit

/// Move to the next screen without an animation
class PushNoAnimationSegue: UIStoryboardSegue {
override func perform() {
    if let navigation = source.navigationController {
        navigation.pushViewController(destination as UIViewController, animated: false)
    }
}

2
可能是由于Swift版本的原因,在你使用它们的两个地方,我需要使用"as!"而不是"as"。 - Carlos
1
也许在Swift 1.2中可以实现?我已经在Xcode 7 Beta1中使用Swift 2.0进行了检查,编译没有任何警告。 - zavié

6
我现在已经使用以下代码来实现这个功能:
CreditsViewController *creditspage = [self.storyboard instantiateViewControllerWithIdentifier:@"Credits"];
[UIView beginAnimations:@"flipping view" context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:YES];
[self.navigationController pushViewController:creditspage animated:NO];
[UIView commitAnimations];

希望这能帮到其他人!


你可以将这段代码添加到UIButton的操作中或者其他任何需要的地方。如果你想要跳转到一个新的视图控制器,但是不需要动画效果,你可以使用以下代码:
  • void(yourUIButtonAction) { CreditsViewController *creditspage = [self.storyboard instantiateViewControllerWithIdentifier:@"Credits"]; [self.navigationController pushViewController:creditspage animated:NO]; }
- R2D2
这甚至没有回答问题。你在这里没有使用segue! - KIDdAe

4

以下是适用于Swift的版本,用于以模态方式呈现ViewController而不进行动画:

import UIKit

/// Present the next screen without an animation.
class ModalNoAnimationSegue: UIStoryboardSegue {

    override func perform() {
        self.sourceViewController.presentViewController(
            self.destinationViewController as! UIViewController,
            animated: false,
            completion: nil)
    }

}

1
这段代码是从@zavié的答案中复制的,没有添加任何内容,但确实更糟:没有包括可选项检查。 - Diego Freniche
这与@zavié的答案不同,因为它展示了如何以模态方式呈现一个ViewController而没有动画。很高兴在这里作为参考,因为它与问题有些相关。 - n.Drake

2

使用Swift3进行回答 -

对于“push”转场:

class PushNoAnimationSegue: UIStoryboardSegue
{
    override func perform()
    {
       source.navigationController?.pushViewController(destination, animated: false)
    }
}

对于“模态”segue:

class ModalNoAnimationSegue: UIStoryboardSegue
{
    override func perform() {
        self.source.present(destination, animated: false, completion: nil)
    }
}

1

对于使用 Xamarin iOS 的任何人,您的自定义 segue 类需要如下所示:

[Register ("PushNoAnimationSegue")]
public class PushNoAnimationSegue : UIStoryboardSegue
{
    public PushNoAnimationSegue(IntPtr handle) : base (handle)
    {

    }

    public override void Perform ()
    {
        SourceViewController.NavigationController.PushViewController (DestinationViewController, false);
    }
}

不要忘记您仍需要在故事板中设置自定义segue,并将类设置为PushNoAnimationSegue类。

0

在Swift中,只需在UINavigationController.pushViewController上设置animated false即可。

self.navigationController!.pushViewController(viewController, animated: false)

1
不确定为什么这被踩了。对我来说完美地工作了! - Eric

0

对我来说,最简单的方法是:

UIView.performWithoutAnimation { 

        self.performSegueWithIdentifier("yourSegueIdentifier", sender: nil)

    }

iOS 7.0及以上版本可用


如果使用自适应转场,我认为尽管 performWithoutAnimation 可以禁用动画,但在执行转场之前,如果转场已经勾选了“动画”,则动画会再次启用。执行完毕后,如果之前被禁用,则会再次禁用它们。 - malhal
但是您可以通过创建一个UIStoryboardSegue子类并在执行之前再次禁用动画来解决它(例如,使用构造函数检查它们是否被禁用并将其存储在属性中)。 - malhal
我提交了反馈FB11718965,请求添加此功能。 - malhal

0

无动画推送:Swift 这是对我有效的方法。

import ObjectiveC

private var AssociatedObjectHandle: UInt8 = 0
    extension UIViewController {

        var isAnimationRequired:Bool {
            get {
        return (objc_getAssociatedObject(self, &AssociatedObjectHandle) as? Bool) ?? true
            }
            set {
                objc_setAssociatedObject(self, &AssociatedObjectHandle, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }

    -------------------- SilencePushSegue --------------------

class SilencePushSegue: UIStoryboardSegue {

    override func perform() {
        if self.source.isAnimationRequired == false {
            self.source.navigationController?.pushViewController(self.destination, animated: false)
        }else{
            self.source.navigationController?.pushViewController(self.destination, animated: true)
        }
    }
}

使用方法:按照图片所示,在Storyboard中设置segue类。在你想要调用performSegue的地方,将isAnimationRequired从你的viewcontroller设为false,这样就可以不带动画地推出segue,然后在调用self.performSegue后将其设回true。祝你好运....

DispatchQueue.main.async {
                self.isAnimationRequired = false
                self.performSegue(withIdentifier: "showAllOrders", sender: self);
                self.isAnimationRequired = true
            }

set the segue class from storyboard as shown in picture.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接