Search code examples
iosswiftdrop-down-menuuipickerviewuipopover

Swift/iOS - Whats the alternative to multiple android drop down lists


I'm new to iOS and Swift. I've been making an android app for a couple years now. I'm learning Swift and making it for iOS devices.

I need help with alternative ways of Drop Down lists, since thats what i've using in android.

I've been researching UIPickerViews, UIPopovers with table views and more.

Twist is, i need multiple alternate of drop down lists in one ViewController.

Here is the view in my android app, that i want to look pretty similar in my iOS version.enter image description here


Solution

  • I've been building survey applications for the last couple of months and this exact problem has come up several times. While a UIPickerView mostly makes sense, it doesn't allow the user to see more than just a few options at a time and it doesn't scale well from iPhone 4s to a 6+ or iPad.

    The first thing I would recommend is to create a button for your drop down menu. I've found that just about anything that looks remotely button like works well but making it look like a hyperlink or too inline with what's surrounding it doesn't work as well from a UX perspective.

    Here's what the button I use looks like: This is just a UIButton with a border on it

    All that is is a. UIButton with a thin border around it with a corner radius of ~5.

    As for the actual drop down, I've found popovers to generally be pretty effective. The easiest implementation for me was using UIAlertController. (This is only available in iOS 8+ but should be fine if you're working in swift anyway.) With UIAlertController you can have a very large number of options, a cancel button that's easily accessible, a title, a message all presented to the user in a very standard way. You can set the actions for each button when the controller is created so you don't have to work with delegates at all which keeps your code cleaner.

    Here's what the alert controller for my previous example looks like. This is on an iPhone 5s in landscape which is the smallest layout possible but it scales up automatically as needed for any screen size and offers a similar experience for the user. UIAlertController as a drop down menu

    When the user has selected an answer, update the button text to match the new answer.

    Instead of using UIAlertController, I have created my own custom pop up with a table view but I've found myself basically recreating the alert controller just for the look of it and found it more difficult than it's worth to get the layout just right on every device. With that said, UIAlertController offers almost nothing by way of customizing how it looks, which can be a deal breaker for some.

    I feel like I should add that the reason I use a UIAlertController instead of a UIPickerView is intentional since it allows the user to see more options simultaneously and makes use of the available screen size on an iPad and larger iPhones. Additionally, the feedback after making a selection is instantaneous as the view disappears as soon as a selection is made, Cancel is a standard action which allows the user to quickly not make a selection, and doesn't require the user to scroll if there are only a few options which means that a selection can be made in just one tap.

    Here's the code I used to produce the button and corresponding UIAlertController:

    if (self.question.placeholderText) {
        [self.answerButton setTitle:NSLocalizedString(self.question.placeholderText, @"") forState:UIControlStateNormal];
    } else {
        [self.answerButton setTitle:NSLocalizedString(@"Please Select One", nil) forState:UIControlStateNormal];
    }
    [self.answerButton setTitle:[self paddedString:self.answerButton.titleLabel.text] forState:UIControlStateNormal];
    self.answerButton.titleLabel.textAlignment = NSTextAlignmentLeft;
    self.answerButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
    self.answerButton.titleLabel.font = [UIFont appFont];
    [self.answerButton setTitleColor:[UIColor appColor] forState:UIControlStateNormal];
    [self.answerButton addTarget:self action:@selector(longListLabelTapped) forControlEvents:UIControlEventTouchUpInside];
    self.answerButton.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.0001f];
    self.answerButton.titleLabel.layer.borderColor = [UIColor appColor].CGColor;
    self.answerButton.titleLabel.layer.borderWidth = 1.0f;
    self.answerButton.titleLabel.layer.cornerRadius = 5.0f;
    
    - (NSString *)paddedString:(NSString *)input {
        //This adds some space around the button title just to make it look better
        return [NSString stringWithFormat:@"  %@  ", input];
    }
    

    To create the UIAlertController, you'll need an array of your options.

    _optionsController = [UIAlertController
                          alertControllerWithTitle:self.question.longListTitle
                          message:nil
                          preferredStyle:UIAlertControllerStyleAlert];
    
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
    
    }];
    [_optionsController addAction:cancelAction];
    
    
    for (NSString *optionName in self.question.possibleAnswers) {
        UIAlertAction *action = [UIAlertAction actionWithTitle:optionName
                                                         style:UIAlertActionStyleDefault
                                                       handler:^(UIAlertAction *action) {
                                                           // Do something with the selected answer
                                                           [self.answerButton setTitle:[self paddedString:optionName] 
                                                                              forState:UIControlStateNormal];
                                                       }];
        [_optionsController addAction:action];
    }