I use a floating popover to present suggestions in my UI. When the user wants to select an item from the menu bar in the splitview controller, the first tap just dismisses the popover. Therefore, the user has to tap twice, to activate a menu item.
If the user wants to activate the trash can, he has to tap it twice. Once to dismiss the other popover, and once to activate the trash can.
What's the best way to avoid this?
Wild guess here - but perhaps passThroughViews - add the button view and then in the button action, dismiss the popover (need to determine if it is active). A bit hacky but could work.
Related
On an iPad, you can use controller.modalPresentationStyle = UIModalPresentationFormSheet to show a centered modal on the screen. A common technique is to allow the user to dismiss the modal by clicking "outside" or "behind" it. This is covered in numerous other answers (Iphone SDK dismissing Modal ViewControllers on ipad by clicking outside of it,
Dismiss modal view form sheet controller on outside tap), usually by adding a tap gesture to the view's UIWindow.
My question is, how do I make this accessible to users in VoiceOver mode? The native action sheets allow clicks outside the sheet to dismiss, and even prompt the user, saying "double tap to dismiss popup window". How can I expose the UIWindow tap gesture in the same way?
From Apple:
https://support.apple.com/guide/iphone/learn-voiceover-gestures-iph3e2e2281/ios
Dismiss an alert or return to the previous screen: Two-finger scrub
(move two fingers back and forth three times quickly, making a “z”).
If the modal sheet is opened, we can prompt the user to "make a z gesture" to go back.
There is basically no way to do this with the FormSheet presentation. You can use the Popover presentation, but it behaves differently in some cases.
My solution was to check UIAccessibilityIsVoiceOverRunning() and add an extra close button element to the top of FormSheet that can be clicked via voiceover. I also implemented accessibilityPerformEscape for the global escape gesture.
I am using custom popover controller(WYPopoverController) for iPhone and showing UIReferenceLibraryViewController in it. The view does come perfectly but UIReferenceLibraryViewController has 'Done' button on its navigation bar and when I click on it, it does not respond. Though if I click outside the popover then popover disappears. I simply want to disappear popover when 'Done' button is pressed.
Please note, if I use UIPopoverController for iPad, then 'Done' button in UIReferenceLibraryViewController does respond. Not sure what am I missing in custom implementation.
Any help is much appreciated.
The problem to me seems like part of a terrible design by Apple, where the reference library controller dismisses itself rather than providing a delegate method notifying you to dismiss it. First, open a bug report with Apple and post the bug report number so people can duplicate it.
In absence of better options, I would suggest replacing the controller's navigation item's bar button item with your own, where that button would notify you of the user's tap and you'd dismiss the controller properly. This is a partial solution, as the reference library controller is a complex case, where it maintains a navigation stack internally. You may have to dig in the view controller parent/child hierarchy to find all cases.
Consider changing your design in the meantime, presenting the view modally instead of a popover on phone/pod devices.
I have a UIBarButtonItem in a navigation item that displays a UIActionSheet with a button to toggle a quick setting:
The action sheet is presented from the button item:
[calendarSettingsSheet showFromBarButtonItem:self.navigationItem.leftBarButtonItem animated:YES];
However, here's the problem I'm encountering:
When I tap below the navigation bar, for example anywhere in the calendar, the UIActionSheet dismisses, which is expected. Any touch outside the sheet, in my opinion, should dismiss it.
But: I can still tap on the "Settings" and "Done" buttons in the navigation bar, and not only is the action sheet not dismissed, but the buttons function.
So, tapping "Settings" while the UIActionSheet is open, causes another to be opened. This can easily be avoided by checking to see if the action sheet is already open.
But, the "Done" button dismisses the entire calendar view, leaving the UIActionSheet hovering over the view that originally presented the calendar.
Is this intended behavior? While I could disable the buttons when the action sheet is presented, and enable them when it's dismissed, this seems like an unnecessary workaround.
Is this intended behavior?
Yes.
From the documentation of showFromBarButtonItem:animated:
On iPad, this method presents the action sheet in a popover and adds the toolbar that owns the button to the popover’s list of passthrough views. Thus, taps in the toolbar result in the action methods of the corresponding toolbar items being called. If you want the popover to be dismissed when a different toolbar item is tapped, you must implement that behavior in your action handler methods.
I am attempting to display a passcode screen that appears after X amount of inactivity. I use presentViewController:animated:completion: on the root view controller, and it works as expected, except when a popover is already being displayed. The popover, displayed from a bar button item, appears over the presented passcode screen.
Is there a way to dismiss or hide all visible popovers when presenting a view controller?
Create and add a 2nd window over the first. Present the passcode screen in the 2nd window. This will allow it to appear over any and all views from the first window. When you dismiss the passcode screen, be sure to remove the new window and make the 1st one key again.
Do you have a reference to the popover? Then you can just call
[popover dismissPopoverAnimated:NO];
when you go to shop the passcode overlay.
EDIT
Looping through subviews and seeing if you can dimiss a popover. I'd really recommend trying to find some other way of doing things as this is just icky. But it should work (untested).
for (UIView* view in self.view.subviews) {
if([view respondsToSelector:#selector(dismissPopoverAnimated:)]){
[(UIPopoverController*)view dismissPopoverAnimated:NO];
}
}
NSNotifications are a good tool for this problem. Have all your views or controllers that present popovers listen for a notification named, say, WillPresentPasscodeScreen, and implement a method that dismisses the popover when the notification comes in. Then, before you present your passcode VC, post a WillPresentPasscodeScreen notification -- no more popovers, regardless of where you are in the app.
I've got a modal view that has "Cancel" button (the button dismisses modal).
In the modal, I'm shoving a small UIPopover.
What I'm trying to achieve is:
When the UIPopover is visible, if uset touches "Cancel" it will do both:
hide popover (it's happening now, since that's the click outside popup)
hide modal - as if user touched "Cancel" without popup
Is there a way to do it?
UIPopoverControllerDelegate is not providing any help (or I'm not seeing it :) )
Thanks :)
Before presenting the popover, add the Cancel button to the popover's passthroughViews array:
popoverController.passthroughViews = [NSArray arrayWithObject:cancelButton];
This will let the Cancel button respond to touches while the popover is displayed without automatically dismissing the popover.
Then in your Cancel button's action method, call dismissPopoverAnimated: on the popover before dismissing the modal view.
You'll need to keep a reference to the popover in an ivar (eg. popoverController) to do this.