Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: How to create a popup menu in iOS

I'm doing some drawing on a custom UIView canvas, and rather than having a set of buttons at the bottom of the view to allow the user to select shapes, I'd like to have the user do a long press gesture, then have a popup-type menu appear with different shapes they can choose. I don't see anything like this in xCode, though I'd assume there's something like that in iOS. I don't want the alert popup that shows up when you have low battery and notifications.

I've looked into using a UIPopoverController but I'm a bit confused about some of the other Stack Overflow questions I've read about it, and also about the documentation given by Apple.

like image 242
NumberOneRobot Avatar asked Dec 01 '14 17:12

NumberOneRobot


People also ask

How do I display an action sheet in Swift?

Enter Swift as Language and Storyboard as User Interface. Choose Next. Go to the Storyboard, drag a Button from the Object Library to the View Controller inside the Storyboard. Double-click the Button and give it a title of"Display Action Sheet".


2 Answers

Floating Menu

I described the steps to achieve floating menu as shown in above image:

  1. Create segue from the barButtonItem to the MenuViewCobtroller of type 'Present as Popover'
  2. In the MenuViewController override the preferredContentSize as:

    override var preferredContentSize : CGSize
    {
        get
        {
            return CGSize(width: 88 , height: 176)
        }
        set 
        {
            super.preferredContentSize = newValue
        }
    }
    

In my case I am returning CGSize with width 100 and size 200. You can set these values so as to fit your floating menu content properly. 4. In the initial/source view controller, in the prepare(for segue: sender) method set self as popoverPresentationController delegate:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ShowMenuSegue" {
        if let tvc = segue.destination as? MenuViewController
        {
            tvc.delegate = self
            if let ppc = tvc.popoverPresentationController
            {
                ppc.delegate = self
            }
        }
    }
}

The source view controller must comply to UIPopoverPresentationControllerDelegate and implement following method:

extension ViewController: UIPopoverPresentationControllerDelegate {

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

That's it. You got the floating menu. Hopefully this will be useful.

like image 98
Pankaj Kulkarni Avatar answered Sep 20 '22 17:09

Pankaj Kulkarni


After you make a connection of that button with the viewController and popover as a segue you will need to prepare. Here is the following code in order to prepare for the popover segue.

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
    if let identifier = segue.identifier
    {
        switch identifier
        {
            case History.SegueIdentifier:

            if let tvc = segue.destinationViewController as? TextViewController
            {
                if let ppc = tvc.popoverPresentationController
                {
                    ppc.delegate = self
                }
                tvc.text = "\(diagnosticHistory)"
            }

            default: break
        }
    }
}

Do keep in mind that if you have an iPhone the popover will take full screen, so you can fix that using this for let's say a text that takes some particular elements.

This will fix the popover to be exactly the size of the elements you have in your text.

@IBOutlet weak var textView: UITextView!
{
    didSet
    {
        textView.text = text
    }
}

var text : String = ""
{
    didSet
    {
        textView?.text = text
    }
}

override var preferredContentSize : CGSize
{
    get
    {
        if textView != nil && presentingViewController != nil
        {
            return textView.sizeThatFits(presentingViewController!.view.bounds.size)
        }
        else
        {
            return super.preferredContentSize
        }
    }

    set {super.preferredContentSize = newValue}

    }
}

I have those 2 in different view controllers but I guess it will work. You will also need to implement UIPopoverPresentationControllerDelegate and

func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
    return UIModalPresentationStyle.None
}

to your first viewController.

like image 31
Korpel Avatar answered Sep 23 '22 17:09

Korpel