Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Implementing Drop-down Selection Behavior in iOS Applications

DZone's Guide to

Implementing Drop-down Selection Behavior in iOS Applications

This article demonstrates the implementation of a simple drop-down list using a popover presentation controller. Note that, while the example uses MarkupKit to help simplify the implementation of the popover, this is not strictly necessary.

· Mobile Zone
Free Resource

Discover how to focus on operators for Reactive Programming and how they are essential to react to data in your application.  Brought to you in partnership with Wakanda

Like radio buttons and checkboxes, iOS does not provide a native "drop-down" selection control like those commonly found on other platforms. Historically, it has been possible to emulate this type of control using a popover controller; however, until recently, this option was only available on iPads and iPhone 6+ devices in landscape orientation. Beginning with iOS 9, popovers can now be used on any iOS-enabled device, allowing developers to take advantage of this popular abstraction regardless of form factor or device orientation.

This article illustrates the implementation of a simple drop-down list that allows a user to specify a background color for a view. The list is accessed by tapping on the "Color" button in the application's navigation bar:

Implementation

The main view in the application is managed by a class named SelectionViewController, which is presented within a navigation controller. The controller's right bar button item, labeled "Color", provides access to the drop-down list. In the viewDidLoad method, SelectionViewController creates the bar button item and assigns the action handler method that will be called when the item is tapped. It also initializes an instance of ColorPickerViewController, the controller class it will use to present the list of color options to the user:

class SelectionViewController: UIViewController, UIPopoverPresentationControllerDelegate, UITableViewDelegate {
    let colorPickerViewController = ColorPickerViewController()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = UIColor.whiteColor()

        title = "Color Picker"

        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Color", style: UIBarButtonItemStyle.Plain, target: self, action: "showColorPicker")

        colorPickerViewController.modalPresentationStyle = .Popover
        colorPickerViewController.tableView.delegate = self
    }

    func showColorPicker() {
        ...
    }

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

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        ...
    }
}

The showColorPicker method is called in response to a tap on the "Color" button. It is defined as follows:

func showColorPicker() {
    let colorPickerPresentationController = colorPickerViewController.presentationController as! UIPopoverPresentationController

    colorPickerPresentationController.barButtonItem = navigationItem.rightBarButtonItem
    colorPickerPresentationController.backgroundColor = UIColor.whiteColor()
    colorPickerPresentationController.delegate = self

    presentViewController(colorPickerViewController, animated: true, completion: nil)
}

The method first gets a reference to the color picker view controller's presentation controller and casts it to an instance of UIPopoverPresentationController. Since the color picker view controller's modal presentation style was set to UIModalPresentationStyle.Popover in viewDidLoad, this is a valid cast.

Next, the method associates the color picker's presentation controller with the selection view controller's right bar button item (the "Color" button), ensuring that the popover's arrow will point to the button. It then sets the presentation controller's background color to white, so the arrow will match the table view when it is displayed in the popover. Lastly, it sets the selection view controller itself as the presentation controller's delegate. This allows the controller to enforce that the color picker is presented as an actual popover, rather than the default presentation for the current device (which may be full-screen, if the user is running on a horizontally-constrained device such as an iPhone in portrait orientation, for example). It does this by returning UIModalPresentationStyle.None from the adaptivePresentationStyleForPresentationController: method of UIPopoverPresentationControllerDelegate:

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

Finally, showColorPicker presents the color picker view controller, causing the popover to appear on screen.

The ColorPickerViewController class provides the actual content for the drop-down selection view. It is implemented as follows:

class ColorPickerViewController: UITableViewController {
    override func loadView() {
        view = LMViewBuilder.viewWithName("ColorPickerView", owner: self, root: nil)
    }

    override func viewWillAppear(animated: Bool) {
        tableView.layoutIfNeeded()

        preferredContentSize = tableView.contentSize
    }
}

ColorPickerViewController uses the MarkupKit framework to help simplify its view construction. The markup for the view is defined as follows:

<LMTableView style="plainTableView" estimatedSectionHeaderHeight="0" estimatedSectionFooterHeight="0">
    <?sectionSelectionMode singleCheckmark?>

    <UITableViewCell textLabel.text="Red" value="#ff0000"/>
    <UITableViewCell textLabel.text="Yellow" value="#ffff00"/>
    <UITableViewCell textLabel.text="Green" value="#00ff00"/>
    <UITableViewCell textLabel.text="Blue" value="#0000ff"/>
    <UITableViewCell textLabel.text="Purple" value="#ff00ff"/>
</LMTableView>

It first declares an instance of LMTableView, a MarkupKit-provided subclass of UITableView that facilitates the definition of static table view content. It sets the selection mode of the table view's first (and only) section to "singleCheckmark", which ensures that only a single row will be selected at a time. It also sets the table view's estimated section header and footer heights to zero to ensure that the view does not allocate any leading or trailing space for a header or footer. Finally, it declares the cells that represent the color options. Using the value property added to UITableViewCell by MarkupKit, it associates a hex color value with each cell. This value will be used later to set the main view's background color.

ColorPickerViewController overrides loadView to load the view definition from markup. It also overrides viewWillAppear: to call layoutIfNeeded on its table view and then sets its own preferred content size to match the table view's content size. This step is important, as it allows the popover to automatically resize itself to match the size of the table view's content.

SelectionViewController implements tableView:didSelectRowAtIndexPath: to respond to user input on the color picker's table view:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath)

    self.view.backgroundColor = LMViewBuilder.colorValue(cell!.value as! String)

    dismissViewControllerAnimated(true, completion: nil)
}

The code first obtains an instance to the selected cell and gets its associated hex-encoded color value. It then calls the colorValue: method of LMViewBuilder to translate the hex value to an instance of UIColor, which it sets as the value of the view's background color. Finally, it dismisses the popover.

Summary

This article demonstrated the implementation of a simple drop-down list using a popover presentation controller. Note that, while the example used MarkupKit to help simplify the implementation of the popover, this is not strictly necessary. For example, a ColorPickerViewController with a custom delegate for handling selection notifications would work just as well, albeit with a bit more effort and code.

For more information about MarkupKit, see the GitHub project site. For additional examples, see the project wiki.

Learn how divergent branches can appear in your repository and how to better understand why they are called “branches".  Brought to you in partnership with Wakanda

Topics:
ios ,mobile ,markupkit ,ui ,ui programmatically

Published at DZone with permission of Greg Brown, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}