I am trying to present a PopOver view controller, specifically to show a small filters screen next to a TextField. However it is showing as a full-screen view controller. filters_button is the one that should trigger the pop-over. Any ideas why this is showing full screen as if it were a normal ViewController?
func showFilters(){
let tableViewController = UITableViewController()
tableViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
tableViewController.preferredContentSize = CGSizeMake(20, 20)
presentViewController(tableViewController, animated: true, completion: nil)
let popoverPresentationController = tableViewController.popoverPresentationController
popoverPresentationController?.sourceView = filters_button
popoverPresentationController?.sourceRect = CGRectMake(0, 0, filters_button.frame.size.width, filters_button.frame.size.height)
}
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
return .None
}
Note: At the top of my class I declare that it conforms the "UIPopoverPresentationControllerDelegate" protocol
Fixed:
Given that for the PopOver to work on iPhone devices, you need to set the delegate of popoverPresentationController before the viewController is presented, that way the method below gets called by the delegate. So add
popoverPresentationController?.delegate = self
below
popoverPresentationController?.sourceRect = filters_button.frame
and move
self.presentViewController(filtersVC, animated: true, completion: nil)
to the end of the function.
You should add the following
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}
Related
I am trying to make a popover menu with the following code:
import UIKit
class BeobachtungViewController: UIViewController, UIPopoverPresentationControllerDelegate {
#IBAction func addClicked(_ sender: AnyObject) {
// get a reference to the view controller for the popover
let popController = UIStoryboard(name: "Personenakte", bundle: nil).instantiateViewController(withIdentifier: "popoverId")
// set the presentation style
popController.modalPresentationStyle = UIModalPresentationStyle.popover
// set up the popover presentation controller
popController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.up
popController.popoverPresentationController?.delegate = self
popController.popoverPresentationController?.sourceView = sender as! UIView // button
popController.popoverPresentationController?.sourceRect = sender.bounds
// present the popover
self.present(popController, animated: true, completion: nil)
}
// UIPopoverPresentationControllerDelegate method
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
// Force popover style
return UIModalPresentationStyle.none
}
}
This is working on iPad, but, on an iPhone, the popup takes the whole iPhone screen. I just want a small window with an arrow. I found several tutorials but none worked for me.
Change your delegate method to:
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
// return UIModalPresentationStyle.FullScreen
return UIModalPresentationStyle.none
}
I couldn't show popover controller as popover in iPhone whereas it works very well with iPad.
Any ideas on how to do that in iPhone.
As far as I have searched I couldn't find any.
anyways to make the popover appear in iphone as it is in iPad is appreciated !
Set yourself as the popover view controller's delegate before presenting it, and implement the delegate method adaptivePresentationStyle(for:traitCollection:) to return .none. This will cause the popover to stop adapting on iPhone as a fullscreen presented view controller and turn into an actual popover just like on the iPad.
This is a complete working example that presents the popover in response to a button tap:
class ViewController: UIViewController {
#IBAction func doButton(_ sender: Any) {
let vc = MyPopoverViewController()
vc.preferredContentSize = CGSize(400,500)
vc.modalPresentationStyle = .popover
if let pres = vc.presentationController {
pres.delegate = self
}
self.present(vc, animated: true)
if let pop = vc.popoverPresentationController {
pop.sourceView = (sender as! UIView)
pop.sourceRect = (sender as! UIView).bounds
}
}
}
extension ViewController : UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}
}
I am presenting a modal popover view like this:
let popover = StatueSelectionController(collectionViewLayout: UICollectionViewFlowLayout())
popover.delegate = self
popover.modalPresentationStyle = .popover
popover.popoverPresentationController?.barButtonItem = navigationItem.rightBarButtonItem
popover.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.up;
popover.preferredContentSize = CGSize(width: 200, height: 300)
present(popover, animated: true, completion: nil)
The popover.delegate = self has nothing to do with UIPopoverControllerDelegate although it does implement that protocol.
The problem is that the popover takes up the whole view. StatueSelectionController, which is a UICollectionViewController, fills up the whole screen and does not change for preferredContentSize.
What am I doing wrong here?
If you want to force the popOver to not cover the full screen on an iPhone, you would have to add a UIPopoverPresentationControllerDelegate method in your code
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}
I am trying to make a popover menu with the following code:
import UIKit
class BeobachtungViewController: UIViewController, UIPopoverPresentationControllerDelegate {
#IBAction func addClicked(_ sender: AnyObject) {
// get a reference to the view controller for the popover
let popController = UIStoryboard(name: "Personenakte", bundle: nil).instantiateViewController(withIdentifier: "popoverId")
// set the presentation style
popController.modalPresentationStyle = UIModalPresentationStyle.popover
// set up the popover presentation controller
popController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.up
popController.popoverPresentationController?.delegate = self
popController.popoverPresentationController?.sourceView = sender as! UIView // button
popController.popoverPresentationController?.sourceRect = sender.bounds
// present the popover
self.present(popController, animated: true, completion: nil)
}
// UIPopoverPresentationControllerDelegate method
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
// Force popover style
return UIModalPresentationStyle.none
}
}
This is working on iPad, but, on an iPhone, the popup takes the whole iPhone screen. I just want a small window with an arrow. I found several tutorials but none worked for me.
Change your delegate method to:
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
// return UIModalPresentationStyle.FullScreen
return UIModalPresentationStyle.none
}
I'm trying to programmatically present a view via an adaptive popover (e.g. in a popover on an iPad, full screen on an iPhone). In order to be able to dismiss the presented view controller on the iPhone, I've tried wrapping it in a navigation controller as in https://stackoverflow.com/a/29956631/5061277 or the nice example here: https://github.com/shinobicontrols/iOS8-day-by-day/tree/master/21-alerts-and-popovers/AppAlert, which looks like:
import UIKit
class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {
#IBAction func handlePopoverPressed(sender: UIView) {
let popoverVC = storyboard?.instantiateViewControllerWithIdentifier("codePopover") as! UIViewController
popoverVC.modalPresentationStyle = .Popover
// Present it before configuring it
presentViewController(popoverVC, animated: true, completion: nil)
// Now the popoverPresentationController has been created
if let popoverController = popoverVC.popoverPresentationController {
popoverController.sourceView = sender
popoverController.sourceRect = sender.bounds
popoverController.permittedArrowDirections = .Any
popoverController.delegate = self
}
}
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
// This line _IS_ reached in the debugger
NSLog("Delagate asked for presentation style");
return .FullScreen
}
func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
// This line _IS_NOT_ reached in the debugger
NSLog("Delegate asked for view controller");
return UINavigationController(rootViewController: controller.presentedViewController)
}
}
While the adaptivePresentationStyleForPresentationController delegate method is called, the presentationController viewControllerForAdaptivePresentationStyle delegate method is not called. As a result there is no way to dismiss the presented controller on an iPhone.
I've tried XCode 6.4 and 7.0b2 on iOS 8.1 through 8.4, both in the simulator and on a device, and in no case is my delegate asked for viewControllerForAdaptivePresentationStyle. Why? Is there a build setting I should be looking at, or could having XCode 7 installed be changing something? This exact code is presented as working in the links above.
You need to present it after configuring it. Alternatively use a segue to make it much easier.
You need to add this method:
-(UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection{
return UIModalPresentationOverFullScreen;
}
The trick is that you must set the
presentation controller’s delegate before calling present(_:animated:completion:);
otherwise, the adaptive presentation delegate methods won’t be called:
let vc = MyViewController()
vc.modalPresentationStyle = .popover
if let pop = vc.popoverPresentationController {
pop.delegate = self // *
}
self.present(vc, animated: true)