Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Popover presentation style on iPhone devices - possible any more?

I'm trying to define a popover view attached to a view like this:

desired popover appearance

Here's my code:

class MyController: UIViewController, UIPopoverPresentationControllerDelegate {

    ...

    func displaySignOut(_ sender: UIButton) {
        let vc = UIStoryboard(name: "Main", bundle: nil)
            .instantiateViewController(withIdentifier: "signOutPopover")
        vc.modalPresentationStyle = .popover
        vc.preferredContentSize = CGSize(width: 100, height: 30)
        present(vc, animated: true, completion: nil)

        let pc = vc.popoverPresentationController!
        pc.sourceView = sender
        pc.sourceRect = sender.bounds
        pc.delegate = self
    }

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

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

Because the popover is so small, I'd like to use this style on all devices. I've followed the usual advice (e.g., here) on overriding adaptivePresentationStyle to return UIModalPresentationStyle.none.

This works fine on iPad devices, but on iPhones, it doesn't. On smaller iPhone devices, it comes up full screen all the time. On larger screens (e.g., iPhone 7 Plus), it comes up wrong, but, weirdly, switches to a popover presentation (in both portrait and landscape) if I rotate the device after the popover appears. (If I dismiss the popover and bring it up again, it's wrong again until I rotate the device.) Furthermore, in landscape it comes up in a strange configuration (not full screen as in portrait):

How the popover appears in landscape on iPhone 7 Plus

Unlike with a popover presentation, this does not dismiss if I tap outside the popover view itself.

The Apple documentation says (in part):

In a horizontally compact environment, popovers adapt to the UIModalPresentationOverFullScreen presentation style by default.

The "by default" strongly suggests that there's a way to override this behavior. But (as is consistent with this post), overriding adaptivePresentationStyle in the delegate doesn't seem to be the way to do this any more (although it used to work). So is there a new way to modify the default behavior?

I'm using XCode 8.3.3 and Swift 3.1, targeting iOS 9+.

like image 938
Ted Hopp Avatar asked Jul 24 '17 16:07

Ted Hopp


People also ask

What is a popover ios?

A popover is a transient view that appears above other content onscreen when people click or tap a control or interactive area.


Video Answer


2 Answers

I have created one custom class with storyboard inside that connect outlet of button and implemented below code.

import UIKit
class PopOverViewController: UIViewController {

    @IBOutlet weak var button: UIButton!
    override func viewDidLoad() {
        super.viewDidLoad()
        button.backgroundColor = UIColor.purple
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    //Updating the popover size
    override var preferredContentSize: CGSize {
        get {
            let size = CGSize(width: 80, height: 60)
            return size
        }
        set {
            super.preferredContentSize = newValue
        }
    }


    //Setup the ViewController for popover presentation
    func updatePopOverViewController(_ button: UIButton?, with delegate: AnyObject?) {
        guard let button = button else { return }
        modalPresentationStyle = .popover
        popoverPresentationController?.permittedArrowDirections = [.any]
        popoverPresentationController?.backgroundColor = UIColor.purple
        popoverPresentationController?.sourceView = button
        popoverPresentationController?.sourceRect = button.bounds
        popoverPresentationController?.delegate = delegate
    }

}

And then Inside ViewController implemented one function to show popOver on iphone

func showPopOver(button: UIButton!) {
 let viewController = PopOverViewController()
 viewController.updatePopOverViewController(button, with: self)
  present(viewController, animated: true, completion: nil)
}

Note:- Tested and this should work on Portrait as well Landscape mode

like image 192
Hussain Shabbir Avatar answered Dec 07 '22 12:12

Hussain Shabbir


iOS 15 has some new ways to solve this problem. Take a look at the WWDC21 Session "Customize and Resize Sheets in UIKit" https://developer.apple.com/wwdc21/10063 Pretty simple new interface for popovers and customized sheets. Shows how to do non-modal interaction with pop over and the view behind it.

like image 24
Will Loew-Blosser Avatar answered Dec 07 '22 12:12

Will Loew-Blosser