Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a popover from a UIButton in Swift

I wish to create a small popover about 50x50px from a UIButton. I have seen methods using adaptive segue's but I have my size classes turn of thus meaning I can not use this features!

How else can I create this popover? Can I create it with code inside my button IBACtion? Or is there still a way I can do this with storyboards?

like image 535
user4671001 Avatar asked Mar 18 '15 21:03

user4671001


4 Answers

You can do one of the following two options :

  • Create an action for the UIButton in your UIViewController and inside present the ViewController you want like a Popover and your UIViewController has to implement the protocol UIPopoverPresentationControllerDelegate, take a look in the following code :

    @IBAction func showPopover(sender: AnyObject) {
    
        var popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("StoryboardIdentifier") as! UIViewController
    
        popoverContent.modalPresentationStyle = .Popover
        var popover = popoverContent.popoverPresentationController
    
        if let popover = popoverContent.popoverPresentationController {
    
           let viewForSource = sender as! UIView
           popover.sourceView = viewForSource
    
           // the position of the popover where it's showed
           popover.sourceRect = viewForSource.bounds
    
           // the size you want to display
           popoverContent.preferredContentSize = CGSizeMake(200,500)
           popover.delegate = self
        }            
    
        self.presentViewController(popoverContent, animated: true, completion: nil)
    }
    
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
       return .None
    }
    

    According to the book of @matt Programming iOS 8:

    A popover presentation controller, in iOS 8, is a presentation controller (UIPresentationController), and presentation controllers are adaptive. This means that, by default, in a horizontally compact environment (i.e. on an iPhone), the .Popover modal presentation style will be treated as .FullScreen. What appears as a popover on the iPad will appear as a fullscreen presented view on the iPhone, completely replacing the interface.

    To avoid this behavior in the iPhone you need to implement the delegate method adaptivePresentationStyleForPresentationController inside your UIViewController to display the Popover correctly.

  • The other way in my opinion is more easy to do, and is using Interface Builder, just arrange from the UIButton to create a segue to the ViewController you want and in the segue select the Popover segue.

I hope this help you.

like image 116
Victor Sigler Avatar answered Nov 09 '22 14:11

Victor Sigler


Swift 4 Here is fully working code. So here you will see popup window with size of 250x250:

    import UIKit

    class ViewController: UIViewController {

        @IBOutlet weak var button: UIButton!

        override func viewDidLoad() {
            super.viewDidLoad()

// in case if you don't want to make it via IBAction
            button.addTarget(self, action: #selector(tapped), for: .touchUpInside)
        }

        @objc
        private func tapped() {

            guard let popVC = storyboard?.instantiateViewController(withIdentifier: "popVC") else { return }

            popVC.modalPresentationStyle = .popover

            let popOverVC = popVC.popoverPresentationController
            popOverVC?.delegate = self
            popOverVC?.sourceView = self.button
            popOverVC?.sourceRect = CGRect(x: self.button.bounds.midX, y: self.button.bounds.minY, width: 0, height: 0)
            popVC.preferredContentSize = CGSize(width: 250, height: 250)

            self.present(popVC, animated: true)
        }
    }


// This is we need to make it looks as a popup window on iPhone
    extension ViewController: UIPopoverPresentationControllerDelegate {

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

Take into attention that you have to provide popVC identifier to one viewController you want to present as a popup.

Hope that helps!

like image 28
wm.p1us Avatar answered Nov 09 '22 12:11

wm.p1us


Here you can present a popover on button click.

func addCategory( _ sender : UIButton) {

        var popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
        var nav = UINavigationController(rootViewController: popoverContent)
        nav.modalPresentationStyle = UIModalPresentationStyle.Popover
        var popover = nav.popoverPresentationController
        popoverContent.preferredContentSize = CGSizeMake(50,50)
        popover.delegate = self
        popover.sourceView = sender
        popover.sourceRect = sender.bounds

        self.presentViewController(nav, animated: true, completion: nil)

    }
like image 2
Usman Javed Avatar answered Nov 09 '22 14:11

Usman Javed


Swift 4 Version

Doing most work from the storyboard

I added a ViewController, went to it's attribute inspector and ticked the "Use Preferred Explicit size". After that I changed the Width and Height values to 50 each.

Once this was done I ctrl clicked and dragged from the Button to the ViewController I added choosing "Present as Popover" and naming the segue Identifier as "pop"

Went to the ViewController where I had my Button and added the following code:

class FirstViewController: UIViewController, UIPopoverPresentationControllerDelegate {
    @IBOutlet weak var popoverButton: UIButton! // the button

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "pop" {
            let popoverViewController = segue.destination
            popoverViewController.modalPresentationStyle = .popover
            popoverViewController.presentationController?.delegate = self
            popoverViewController.popoverPresentationController?.sourceView = popoverButton
            popoverViewController.popoverPresentationController?.sourceRect  = CGRect(x: 0, y: 0, width: popoverButton.frame.size.width, height: popoverButton.frame.size.height)
        }
    }
    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        return UIModalPresentationStyle.none
    }



    override func viewDidLoad() {
        super.viewDidLoad()
    }

}
like image 1
Korpel Avatar answered Nov 09 '22 14:11

Korpel