Статьи

Реализация выпадающего выбора поведения в приложениях iOS

Как и радиокнопки и флажки , iOS не предоставляет встроенный элемент управления «выпадающим», как это обычно бывает на других платформах. Исторически, было возможно эмулировать этот тип управления, используя контроллер popover; однако до недавнего времени эта опция была доступна только на устройствах iPad и iPhone 6+ в горизонтальной ориентации. Начиная с iOS 9, теперь всплывающие окна можно использовать на любом устройстве с поддержкой iOS, что позволяет разработчикам использовать эту популярную абстракцию независимо от форм-фактора или ориентации устройства.

Эта статья иллюстрирует реализацию простого раскрывающегося списка, который позволяет пользователю указать цвет фона для представления. Доступ к списку можно получить, нажав кнопку «Цвет» на панели навигации приложения:

Реализация

Основное представление в приложении управляется классом с именем SelectionViewController, который представлен в контроллере навигации. Элемент кнопки правой панели контроллера, помеченный «Цвет», обеспечивает доступ к раскрывающемуся списку. В viewDidLoadметоде SelectionViewControllerсоздает элемент кнопки панели и назначает метод обработчика действия, который будет вызываться при касании элемента. Он также инициализирует экземпляр ColorPickerViewControllerкласса контроллера, который будет использоваться для представления пользователю списка вариантов цвета:

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) {
        ...
    }
}

showColorPickerМетод вызывается в ответ на кране на кнопку «Color». Это определяется следующим образом:

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)
}

Сначала метод получает ссылку на контроллер представления контроллера представления палитры цветов и приводит его к экземпляру UIPopoverPresentationController. Так как модальный стиль представления контроллера представления палитры цветов был установлен на UIModalPresentationStyle.Popoverin viewDidLoad, это допустимый актерский состав.

Затем, метод связывает контроллер представления средства выбора цветов с элементом кнопки правой панели контроллера представления выбора (кнопка «Цвет»), гарантируя, что стрелка всплывающего окна будет указывать на кнопку. Затем он устанавливает белый цвет фона контроллера презентации, чтобы стрелка соответствовала табличному представлению, когда оно отображается во всплывающем окне. Наконец, он устанавливает сам контроллер представления выбора в качестве делегата контроллера представления. Это позволяет контроллеру принудительно отображать палитру цветов в виде фактического всплывающего окна, а не представления по умолчанию для текущего устройства (которое может быть полноэкранным, если пользователь работает на устройстве с горизонтальным ограничением, таком как iPhone в портретная ориентация, например).Это делается путем возврата UIModalPresentationStyle.Noneиз adaptivePresentationStyleForPresentationController:метода UIPopoverPresentationControllerDelegate:

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

Наконец, showColorPickerпредставлен контроллер вида палитры цветов, в результате чего всплывающее окно появляется на экране.

ColorPickerViewControllerКласс обеспечивает фактическое содержание для выпадающего зрения выбора. Это реализовано следующим образом:

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использует инфраструктуру MarkupKit, чтобы упростить конструкцию своего представления. Разметка для представления определяется следующим образом:

<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>

Сначала он объявляет экземпляр предоставленного LMTableViewMarkupKit подкласса, UITableViewкоторый облегчает определение содержимого статического табличного представления. Он устанавливает режим выбора первого (и единственного) раздела табличного представления на «singleCheckmark», что гарантирует, что за один раз будет выбрана только одна строка. Он также устанавливает нулевую оценку заголовка раздела и высоты нижнего колонтитула таблицы, чтобы гарантировать, что представление не выделяет никакого начального или конечного пространства для верхнего или нижнего колонтитула. Наконец, он объявляет ячейки, которые представляют параметры цвета. Используя valueсвойство, добавленное UITableViewCellMarkupKit, оно связывает шестнадцатеричное значение цвета с каждой ячейкой. Это значение будет использовано позже для установки цвета фона основного вида.

ColorPickerViewControllerпереопределяет, loadViewчтобы загрузить определение представления из разметки. Он также переопределяет viewWillAppear:вызов layoutIfNeededсвоего табличного представления, а затем устанавливает собственный предпочтительный размер содержимого, соответствующий размеру содержимого табличного представления. Этот шаг важен, поскольку он позволяет автоматически изменять размер всплывающего окна в соответствии с размером содержимого табличного представления.

SelectionViewControllerРеализует tableView:didSelectRowAtIndexPath:ответ на ввод пользователя в табличном представлении палитры цветов:

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)
}

Сначала код получает экземпляр для выбранной ячейки и получает ассоциированное с ним шестнадцатеричное значение цвета. Затем он вызывает colorValue:метод LMViewBuilderдля преобразования шестнадцатеричного значения в экземпляр UIColor, который он устанавливает в качестве значения цвета фона представления. Наконец, он отклоняет поповер.

Резюме

Эта статья продемонстрировала реализацию простого выпадающего списка с использованием контроллера представления popover. Обратите внимание, что хотя в примере использовался MarkupKit для упрощения реализации всплывающего окна, это не является строго обязательным. Например, a ColorPickerViewControllerс пользовательским делегатом для обработки уведомлений о выборе будет работать так же хорошо, хотя и с немного большими усилиями и кодом.

Для получения дополнительной информации о MarkupKit, посетите сайт проекта GitHub . Дополнительные примеры смотрите в вики проекта .