iOS中如何在弹出窗口中呈现视图控制器

7
所以我有一个主视图控制器。该视图控制器有一个带有故事板segue的条形按钮项,种类设置为“呈现为弹出窗口”。
这一切都按预期工作。但是当你在那个弹出窗口视图控制器内点击另一个按钮时,它会将视图全屏显示。我希望它能在弹出窗口中显示。像推/显示在现有弹出窗口边界的顶部。
我该如何实现这一点?
我只想在iPad上实现此行为。但我认为这是默认的。
编辑
我更喜欢在故事板中完成所有操作,但如果需要,也愿意使用Swift代码完成。

你试过这个吗?https://github.com/lkzhao/Hero - elk_cloner
@elk_cloner 这似乎是一个动画库。不是我要找的东西。 - Charlie Fish
这个第三方库可以帮助你:https://github.com/huynguyencong/EzPopup - huync
3个回答

6
创建一个 UIBarButtonItemIBAction,并在动作中执行以下操作:
- (IBAction)popupAction:(UIBarButtonItem *)sender {
    UIViewController *vc = [[UIViewController alloc] init];  // I don't use segue
    vc.view.backgroundColor = [UIColor grayColor];
    vc.modalPresentationStyle = UIModalPresentationPopover;
    UIPopoverPresentationController *popvc = vc.popoverPresentationController;
    popvc.delegate = self;
    popvc.permittedArrowDirections = UIPopoverArrowDirectionAny;
    popvc.barButtonItem = sender; // if UIBarButtonItem
    // if view
    // popvc.sourceView = sender;
    // popvc.sourceRect = sender.bounds;

    vc.preferredContentSize = CGSizeMake(200, 200);

    [self presentViewController:vc animated:YES completion:nil];
}

还有 UIPopoverPresentationControllerDelegate

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection{
    return UIModalPresentationNone;
}

- (BOOL)popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController{
    return YES;
}

Swift:

@IBAction func popupAction(_ sender: UIBarButtonItem) {
    let vc = UIViewController.init()
    vc.view.backgroundColor = UIColor.gray
    vc.modalPresentationStyle = UIModalPresentationStyle.popover
    let popvc = vc.popoverPresentationController
    popvc?.delegate = self
    popvc?.permittedArrowDirections = UIPopoverArrowDirection.any
    popvc?.barButtonItem = sender
    vc.preferredContentSize = CGSize.init(width: 200, height: 200)

    self.present(vc, animated: true, completion: nil)
}

func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
    return UIModalPresentationStyle.none
}

func popoverPresentationControllerShouldDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) -> Bool {
    return true
}

这适用于iPad和iPhone。
结果: 在弹出控制器中弹出另一个视图控制器:

我正在使用Swift。 - Charlie Fish
同样的问题。UIBarButtonItem 将视图控制器显示为弹出窗口,但是当您单击弹出窗口内部的按钮时,它不会在弹出窗口内显示,而是全屏显示。 - Charlie Fish
你的意思是在一个弹出视图控制器中再弹出另一个视图控制器吗? - tomfriwel
是的。所以 UIBarButtonItem 显示了一个弹出窗口。在这个视图控制器/弹出窗口中,我有按钮。我希望这些按钮在原始弹出窗口内显示视图控制器,而不是作为全屏幕视图控制器。我更喜欢只使用 storyboard 来实现这一点,而不是使用代码。但如果必须使用代码也可以。使用 storyboard 更加清晰简洁。 - Charlie Fish
如果不是 UIBarButtonItem,你需要使用 sourceViewsourceRect。我还添加了一个弹出另一个视图控制器的图片。 - tomfriwel
当我点击弹出窗口内的按钮时,我希望弹出窗口视图被替换为新的视图控制器。或者将新的视图控制器推入现有的弹出窗口中。我不想要两个弹出窗口。当我使用Storyboard Present As Popover时,当前的行为是出现两个弹出窗口。 - Charlie Fish

5

这仅适用于Storyboard。

1)创建一个UIViewController(蓝色),并从您的UIBarButtonItem上按住ctrl+拖动(鼠标),将其拖到UIViewController上,并选择“present as Popover”(就像你做的那样)。

2)单击UIViewController(蓝色),然后单击编辑器 ->嵌入 ->导航控制器(这将是让下一个控制器保留在弹出窗口中的技巧)

3)创建第二个UIViewController(绿色)

4)在第一个UIViewController(蓝色)中创建一个UIButton,然后从按钮上按住ctrl +拖动到第二个UIViewController(绿色)上,选择“show”

最终在Storyboard中应该看起来像这样:

enter image description here

结果如下:

enter image description here

enter image description here

如果您想在没有navigationBar的情况下使用PopOver,则可以在蓝色控制器中使用:

self.navigationController?.isNavigationBarHidden = true

如果要从绿色视图返回到蓝色视图,可以在绿色控制器中使用以下方法:

@IBAction func backToBlueController(sender: UIButton) {
        self.navigationController?.popViewController(animated: true)
}

补充:

如果您不想使用弹出窗口,您还可以将segue种类从barButtonItem更改为navigationController到

模态呈现

并在Storyboard中将演示方式更改为

表单表格

enter image description here

一目了然的是,即使您不需要navigationBar,您也应始终使用UINavigationController来管理导航,因为导航控制器为您提供了一个导航堆栈,可以从中弹出和推入。

UINavigationController参考


谢谢!有没有办法删除顶部的导航栏?它实际上不符合我的设计。我可能会稍后重新设计它,以使其符合应用程序的样式,但现在不行。此外,在'blue'和'green'视图内都有一个按钮,可以运行dismiss(animated:false,completion:nil)。有没有办法在'blue'视图中关闭整个弹出窗口,在'green'视图中返回到'blue'视图?我知道这可能可以通过导航栏来解决,但它并不符合应用程序的风格。此外,在iPhone上,导航栏在“blue”视图上没有关闭按钮。 - Charlie Fish
self.navigationController.navigationBarHidden = true 将会移除导航栏。(在蓝色控制器中)而 self.navigationController.popViewControllerAnimated(true) 在绿色控制器中将会把绿色控制器返回到蓝色控制器。 - Retterdesdialogs
抱歉,在我的国家现在是晚上11点,我只能在周一看如何关闭弹出窗口,但这绝对是可能的。 - Retterdesdialogs
我可以使用 dismiss 来关闭弹出视图。我的最后一个问题是,是否可以在没有导航控制器和弹出视图的情况下显示 green 视图。我是否可以只做类似于 if self.navigationController? 的操作,并在其中放置 self.navigationController.popViewControllerAnimated(true),并在 else 语句中放置 dismiss(animated: false, completion: nil)?如果没有导航控制器并且它是从另一部分显示的而不是从导航控制器或弹出视图中显示的,那么这样会回到 dismiss 吗? - Charlie Fish
我认为你可以在蓝色上使用self.dismissViewControllerAnimated(true)来关闭整个弹出视图。 - Retterdesdialogs
我想我弄清楚了!只需要努力实现它。我现在会为你的答案点赞。通常我不会接受答案和授予奖金,直到它结束(只是让您知道)。非常感谢您的帮助!如果有机会,请在答案中包含这些评论中的所有信息,那将太棒了。非常感谢。 - Charlie Fish

0

你尝试过EzPopup(https://github.com/huynguyencong/EzPopup)吗?它是一个Swift pod。只需要几行代码:

// init YourViewController
let contentVC = ...

// Init popup view controller with content is your content view controller
let popupVC = PopupViewController(contentController: contentVC, popupWidth: 100, popupHeight: 200)

// show it by call present(_ , animated:) method from a current UIViewController
present(popupVC, animated: true)

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