如何在单独的 ViewController 中在 iOS 中制作弹出/对话框视图?

Posted

技术标签:

【中文标题】如何在单独的 ViewController 中在 iOS 中制作弹出/对话框视图?【英文标题】:How to make a popup/dialog view in iOS in a separate ViewController? 【发布时间】:2013-04-26 18:30:37 【问题描述】:

我正在制作一个ios游戏,我想实现这个效果:

我知道如何使用一个视图控制器来做到这一点,但我的视图控制器类已经被代码臃肿,并且该屏幕的情节提要一团糟(实际上我有更多的视图比上图,我只是为了清楚起见隐藏了它们原因)。

所以我的问题是:有没有办法通过使用单独的视图控制器来管理这个暂停弹出框来实现这一点?我需要一个不会关闭先前呈现的屏幕的 segue。我想使用故事板来做到这一点。我尝试了“popover”segue,但它出现了一个我不想要的奇怪边框。

我还需要所有不受暂停视图控制器管理的控件都停止监听事件。我想到了使用覆盖整个屏幕的黑色透明视图作为暂停视图的 BG,并使其忽略事件。有更好的方法吗?

提前致谢。

【问题讨论】:

【参考方案1】:

如果你想用故事板来实现它,这很简单。

我附上example code

1 - 在 Storyboard 中创建您的自定义 PauseViewController。使用全屏视图,黑色,Alpha 0 和包含暂停控件的子视图。创建对应的 .h 和 .m 文件

2 - 添加和链接您的控件(UIButtons)。添加这样的关闭方法。 此方法将从层次结构中删除视图,并使其在关闭时更改 alpha 不可见。

- (IBAction)dismiss:(id)sender 
    [UIView animateWithDuration:0.3f animations:^
        self.view.alpha = 0.0f;
     completion:^(BOOL finished) 
        [self.view removeFromSuperview];
        [self removeFromParentViewController];
    ];

3 - 子类 UIStoryboardSegue 创建你自己的 segue 类。 然后,用类似这样的东西覆盖 perform 方法。这只需使用两个控制器(源和目标)并将目标视图放在源视图上并带有动画。

-(void)perform
    UIViewController *dst = [self destinationViewController];
    UIViewController *src = [self sourceViewController];

    // add the view to the hierarchy and bring to front
    [src addChildViewController:dst];
    [src.view addSubview:dst.view];
    [src.view bringSubviewToFront:dst.view];

    // set the view frame
    CGRect frame;
    frame.size.height = src.view.frame.size.height;
    frame.size.width = src.view.frame.size.width;
    frame.origin.x = src.view.bounds.origin.x;
    frame.origin.y = src.view.bounds.origin.y;
    dst.view.frame = frame;

    [UIView animateWithDuration:0.3f animations:^ 
        dst.view.alpha = 0.5f;
    ];

4 - 链接您的 segue,选择自定义并插入自定义 segue 类名称。

哒哒哒!

如果您需要其他详细信息,请查看示例代码或添加评论。

【讨论】:

这更像是创建一个容器控制器。当 ios 为您提供容器控制器时,您不需要这样做。请参阅下面的答案 他专门要求定制 segue 解决方案。这是干净且可重用的:他可以从任何 viewController 触发 segue(如果需要),或者可以仅重用自定义 segue 来呈现其他 vc。它将动画部分(segue 转换)与控制器代码分开。分离是更干净和可维护的代码的关键。 为了更清楚一点,他要求不要在原始场景中嵌入一些东西,以免更加复杂化。所以他限制了可能的解决方案。否则,更简单的解决方案是只添加一个子视图(而不是整个 vc)并在需要时显示/隐藏。【参考方案2】:

您应该查看 childViewControllers。看起来你想要实现这样的目标。

PauseMenuViewController *pauseMenuVC = [[PauseMenuViewController alloc] init]; 
[self addChildViewController:pauseMenuVC];
if ([self isViewLoaded])
    [self.view addSubview:pauseMenuVC.view];

您应该能够创建自己的菜单进入视图并使背景变暗的动画。

Apple Docs

【讨论】:

【参考方案3】:

假设你没有使用 cocos 2d 的场景。在简单的 iOS 中,最好的解决方案是使用 container Controller

    转到故事板并将容器控制器拖动到主视图控制器(就像拖动 UIlabel 一样) 设置容器的大小。另一个嵌入式视图将从相同大小的容器控制器中弹出。给这个视图控制器一个新的类名。 为容器制作一个出口并根据需要显示/隐藏容器。

如果你不能做到这一点,我会在这个网站上做一个教程。如果你想让我这样做,请在下面评论。

【讨论】:

我正在做一个简单的项目,我想创建一个容器控制器并在其中加载一个 html5 页面,所以你能帮我解决这个问题吗,我有一些关于 html 5 的经验,但没有在 ios dev 中,你能帮我举个简单的例子或教程吗?【参考方案4】:

作为与 UIStoryboardSegue 子类相关的答案的变体,您还可以使用透明的 1x1“blank.png”图像。这样,您只需要关心弹出窗口的视图控制器的子视图的 alpha,这样如果需要,中间的弹出窗口就可以具有完全的可见性。

    -(void)perform
    
        UIViewController *dst = [self destinationViewController];
        UIViewController *src = [self sourceViewController];

        // add the view to the hierarchy and bring to front
        [src addChildViewController:dst];
        [src.view addSubview:dst.view];
        [src.view bringSubviewToFront:dst.view];

        // set the view frame
        CGRect frame;
        frame.size.height = src.view.frame.size.height;
        frame.size.width = src.view.frame.size.width;
        frame.origin.x = src.view.bounds.origin.x;
        frame.origin.y = src.view.bounds.origin.y;
        dst.view.frame = frame;
        dst.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"blank.png"]];

        [UIView animateWithDuration:0.3f animations:^
            dst.view.alpha = 1;
        ];
    

【讨论】:

以上是关于如何在单独的 ViewController 中在 iOS 中制作弹出/对话框视图?的主要内容,如果未能解决你的问题,请参考以下文章

你如何将数据从 ViewController 传递到包含单独 ViewController 的 PageViewController,然后这些 ViewController 将使用这些数据?

如何在使用它的 ViewController 上调整自定义(在单独的文件中创建)UIView 高度?

如何在自定义 UIView 中从 ViewController 传递数据

Swift 2 - 无法在单独的 ViewController 中加载 UIWebView

iPhone:如何使用 UI 图形 PushContext

从标签栏控制器打开带有后退按钮的单独 ViewController