当 BarButtonItem 在打开状态下被按下时,关闭 iPad UIPopoverController

发布于 2024-08-29 03:14:47 字数 620 浏览 4 评论 0原文

在 iPad 上使用分割视图,我有以下代码:

- (void) splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc {
  barButtonItem.title = @"Categories";
  NSMutableArray *items = [[toolbar items] mutableCopy];
  [items insertObject:barButtonItem atIndex:0];
  [toolbar setItems:items animated:YES];
  [items release];
  self.popoverController = pc;
}

这可以很好地在按下按钮时显示弹出窗口。但是,如果在按钮已经打开时按下按钮,我还希望弹出窗口关闭,以遵循良好的指导原则。我该怎么做呢? (即,如果用户重复单击此按钮,则弹出窗口应该出现并隐藏所有其他点击。)

Using a split view on the iPad, I have the following code:

- (void) splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc {
  barButtonItem.title = @"Categories";
  NSMutableArray *items = [[toolbar items] mutableCopy];
  [items insertObject:barButtonItem atIndex:0];
  [toolbar setItems:items animated:YES];
  [items release];
  self.popoverController = pc;
}

This works well to show the popover when the button is pressed. However, I'd also like to have the popover dismiss if the button is pressed while it is already open to follow good guidelines. How would I go about doing this? (i.e. if the user repeatedly clicks this button, the popover should come and hide every other hit.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

楠木可依 2024-09-05 03:14:47

当 splitViewController 显示 popover 时,将调用以下方法。
只需检查是否为 nil,然后忽略它:)

- (void)splitViewController:(UISplitViewController*)svc popoverController:(UIPopoverController*)pc willPresentViewController:(UIViewController *)aViewController{
  if ([pc isPopoverVisible]) {
     [pc dismissPopoverAnimated:YES];
  }
}

When splitViewController display popover, below method will be called.
Just check if not nil, then dismiss it :)

- (void)splitViewController:(UISplitViewController*)svc popoverController:(UIPopoverController*)pc willPresentViewController:(UIViewController *)aViewController{
  if ([pc isPopoverVisible]) {
     [pc dismissPopoverAnimated:YES];
  }
}
深居我梦 2024-09-05 03:14:47

Apple 的 HIG 表示,弹出窗口内不应有明确的关闭按钮,但要执行您所要求的操作,您有两种选择。

1) 发布 NSNotification

2) 深入查看视图层次结构,直到获得弹出框实例

1) 无论您在哪个视图中呈现弹出框,在 viewDidLoad 方法中:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissThePopover) name:@"popoverShouldDismiss" object:nil];

创建一个名为“dismissThePopover”的方法,并在 dealloc 方法中, 在 popoverController 的“关闭”按钮中,输入

-(void)dismissThePopover {
    [self.popoverController dismissPopoverAnimated:YES];
}

-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

以下行:

[[NSNotificationCenter defaultCenter] postNotificationName:@"popoverShouldDismiss" object:nil];

这样做会向应用程序发送通知,并且由于您已经注册了其他视图控制器来侦听它,因此每当它看到该通知时,它都会调用您指定的选择器,在在这种情况下,解雇ThePopover。

2)深入到你的视图层次结构中找到 self.popoverController

检查一下,你的肯定会有所不同,但总体思路是相同的。从 AppDelegate 开始,进入第一个视图控制器,进入子视图,直到到达 self.popoverController 对象。

MyAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
//appDelegate instance, in this case it's the .m file for your ApplicationDelegate

UISplitViewController *svc = appDelegate.splitViewController;
//In this case the first view inside the appDelegate is a SplitView, svc

UINavigationController *navc = [[svc viewControllers]objectAtIndex:0];
//a navigationController is at index:0 in the SplitView hierarchy. DetailView is at index:1

NSArray *vcs = [navc viewControllers];
//vcs is the array of different viewcontrollers inside the Navigation stack for nvc

iPadRootViewController *rootView = [vcs objectAtIndex:0];
//declare the rootView, which is the .m file that is at index:0 of the view array

UIPopoverController *pc = [rootView popoverController];
//HERE WE GO!!! popoverController is a property of iPadRootViewController's instance rootView, hereby referred to as pc.

[pc dismissPopoverAnimated:YES];
//bye bye, popoverController!

希望这有帮助

Apple's HIG says there should not be an explicit dismiss button inside a popover, but to do what you're asking, you have two options.

1) post an NSNotification

OR

2) drill down into your view hierarchy until you have the popover instance

1) in whichever view you are presenting the popover in, in the viewDidLoad method:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissThePopover) name:@"popoverShouldDismiss" object:nil];

create a method called "dismissThePopover" and in the dealloc method, removeObserver

-(void)dismissThePopover {
    [self.popoverController dismissPopoverAnimated:YES];
}

-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

In your popoverController "dismiss" button, enter this line:

[[NSNotificationCenter defaultCenter] postNotificationName:@"popoverShouldDismiss" object:nil];

Doing that sends a notification to the app, and since you've registered your other view controller to listen for it, whenever it sees that notification it calls the selector you specify, in this case, dismissThePopover.

2) drill down into your view hierarchy to find self.popoverController

check this out, yours will be different, surely, but the overall idea is the same. Start at your AppDelegate, move into the first viewcontroller, move into subviews until you get to your self.popoverController object.

MyAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
//appDelegate instance, in this case it's the .m file for your ApplicationDelegate

UISplitViewController *svc = appDelegate.splitViewController;
//In this case the first view inside the appDelegate is a SplitView, svc

UINavigationController *navc = [[svc viewControllers]objectAtIndex:0];
//a navigationController is at index:0 in the SplitView hierarchy. DetailView is at index:1

NSArray *vcs = [navc viewControllers];
//vcs is the array of different viewcontrollers inside the Navigation stack for nvc

iPadRootViewController *rootView = [vcs objectAtIndex:0];
//declare the rootView, which is the .m file that is at index:0 of the view array

UIPopoverController *pc = [rootView popoverController];
//HERE WE GO!!! popoverController is a property of iPadRootViewController's instance rootView, hereby referred to as pc.

[pc dismissPopoverAnimated:YES];
//bye bye, popoverController!

Hope this helps

三生路 2024-09-05 03:14:47

这要容易得多,因为 popoverController 是一个属性。方便参考。

if ([self.popoverController isPopoverVisible]) {
    //using the setters and getters "goes thru the proper channels" when accessing objects
    [self.popoverController dismissPopoverAnimated:YES];
} else {
    UIPopoverController *pc = [[UIPopoverController alloc] initWithContentViewController:YOUR_VIEW_CONTROLLER];
    self.popoverController = pc;
    [pc release];

    //get the button instance you set on the toolbar
    UIBarButtonItem *categoryButton = [[toolbar items] objectAtIndex:0];
    [self.popoverController presentPopoverFromBarButtonItem:categoryButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}

我实际上刚刚意识到您指的是 Delegate 方法中的代码,用于在 splitView 的 index:0 处显示 viewController。这个答案不一定适用于此,但适用于您在 iPad 上访问和创建 popoverController 的任何其他时间。如果不先检查弹出窗口是否可见,您要么会崩溃,要么会打开多个弹出窗口。

感谢您抽出时间。

This is a lot easier because the popoverController is a property. Makes it easier to reference.

if ([self.popoverController isPopoverVisible]) {
    //using the setters and getters "goes thru the proper channels" when accessing objects
    [self.popoverController dismissPopoverAnimated:YES];
} else {
    UIPopoverController *pc = [[UIPopoverController alloc] initWithContentViewController:YOUR_VIEW_CONTROLLER];
    self.popoverController = pc;
    [pc release];

    //get the button instance you set on the toolbar
    UIBarButtonItem *categoryButton = [[toolbar items] objectAtIndex:0];
    [self.popoverController presentPopoverFromBarButtonItem:categoryButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}

I actually just realized that you're referring to the code inside the Delegate method for displaying the viewController at index:0 of your splitView. This answer doesn't necessarily apply to that, but does apply to any other time you're accessing and creating popoverControllers on the iPad. Without checking if a popover is visible first, you will either crash, or open several popovers.

Thanks for your time.

眼趣 2024-09-05 03:14:47

你可以尝试下面的方法

if(![popoverController isPopoverVisible]){
   // Show popover
}
else{
   // close popover
   [popoverController dismissPopoverAnimated:YES];
}

You could try the below

if(![popoverController isPopoverVisible]){
   // Show popover
}
else{
   // close popover
   [popoverController dismissPopoverAnimated:YES];
}
败给现实 2024-09-05 03:14:47

如果您使用默认的 UISplitViewController 设置,则创建的导航栏按钮将显示 RootViewController 的弹出窗口。

如果您想确保不会同时打开多个弹出窗口,只需在 RootViewController 出现时关闭弹出窗口即可。这是我用来解决这个问题的代码:

- (void) viewWillAppear:(BOOL)animated {
  if ([self.popover isPopOverVisible]) {
    [self.popover dismissPopoverAnimated:YES];
  }
  [super viewWillAppear:YES];
}

If you are using the default UISplitViewController setup, then the navigation bar button that is created displays a popover of your RootViewController.

If you want to make sure you don't have multiple pop-ups on at once, you can simply dismiss pop-ups whenever your RootViewController will appear. Here's code I used to solve this problem:

- (void) viewWillAppear:(BOOL)animated {
  if ([self.popover isPopOverVisible]) {
    [self.popover dismissPopoverAnimated:YES];
  }
  [super viewWillAppear:YES];
}
月野兔 2024-09-05 03:14:47

我用来在 RootViewController.m 中显示弹出窗口的代码:

- (IBAction) addCategory:(id)sender {
  AddCategoryViewController *content = [[AddCategoryViewController alloc] init];
  UIPopoverController *aPopover = [[UIPopoverController alloc]
                                   initWithContentViewController:content];

  aPopover.delegate = self;

  // Store the popover in a custom property for later use.
  self.addCategoryPopover = aPopover;
  addCategoryPopover.delegate = self;
  [aPopover release];
  [content release];

  [addCategoryPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}

我曾经尝试从另一个类中消除它:

-(IBAction)saveAddCategory:(id)sender {
  rootViewController = [[RootViewController alloc] init];
  [rootViewController dismissPopover];
}

我的 dismissPopover 函数如下所示:

- (void) dismissPopover {
  if ([self.addCategoryPopover isPopoverVisible]) {
    [self.addCategoryPopover dismissPopoverAnimated:YES];
  }
  if (addCategoryPopover.popoverVisible == YES) {
    [addCategoryPopover dismissPopoverAnimated:YES];
  }
}

The code I used to show the popover in RootViewController.m:

- (IBAction) addCategory:(id)sender {
  AddCategoryViewController *content = [[AddCategoryViewController alloc] init];
  UIPopoverController *aPopover = [[UIPopoverController alloc]
                                   initWithContentViewController:content];

  aPopover.delegate = self;

  // Store the popover in a custom property for later use.
  self.addCategoryPopover = aPopover;
  addCategoryPopover.delegate = self;
  [aPopover release];
  [content release];

  [addCategoryPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}

This I used to try and dismiss it from another class:

-(IBAction)saveAddCategory:(id)sender {
  rootViewController = [[RootViewController alloc] init];
  [rootViewController dismissPopover];
}

My dismissPopover function looks like:

- (void) dismissPopover {
  if ([self.addCategoryPopover isPopoverVisible]) {
    [self.addCategoryPopover dismissPopoverAnimated:YES];
  }
  if (addCategoryPopover.popoverVisible == YES) {
    [addCategoryPopover dismissPopoverAnimated:YES];
  }
}
遇到 2024-09-05 03:14:47

是的,您可以按如下方式设置modalPresentationStyle

controller.modalPresentationStyle = UIModalPresentationFormSheet;

Yes, you can set the modalPresentationStyle as following:

controller.modalPresentationStyle = UIModalPresentationFormSheet;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文