iOS 13 под лупой

    Dynamic Type – хорошо, но работает не всегда. Сейчас я расскажу, как увеличиваются маленькие контролы в iOS 13 бесплатно, без регистрации и смс.


    В прошлой статье мы натянули дайнамик тайп на меню iOS-приложения Dodo Pizza. Получилось неплохо. Но таббар под меню как был маленький, так им и остался – он не видоизменяется в зависимости от настройки размера текста.


    Эта фича ещё не дошла до релиза, за что мне стыд и позор

    – Но как же так, Dodo? Вы что, не заботитесь о людях с плохим зрением?
    – Спокуха!

    Немного о встроенном режиме «Лупа»


    Системный таббар показывает превьюху каждого таба по лонг-тапу. Попробуйте включить «доступный» размер текста, а потом долго жать на любой таб в системном таббаре (например, в Музыке или в Фото). На экране появится вот такая вот всплывайка:


    Помимо таббара режим «лупы» поддерживается кнопками в навбарах и тулбарах:


    Полями поиска:


    И ещё некоторыми контролами.

    И, начиная с iOS 13, мы можем легко добавить такое же поведение своим контролам.

    Как прикрутить UILargeContentViewerItem к приложению


    К сожалению, этот протокол довольно скудно описан в документации, но это не беда, потому что его API выглядит довольно просто:

    @available(iOS 13.0, *)
    public protocol UILargeContentViewerItem : NSObjectProtocol {
        var showsLargeContentViewer: Bool { get }
    
        var largeContentTitle: String? { get }
    
        var largeContentImage: UIImage? { get }
    
        var scalesLargeContentImage: Bool { get }
    
        var largeContentImageInsets: UIEdgeInsets { get }
    }

    Достаточно реализовать несколько из этих методов, названия которых говорят сами за себя, и ваш контрол будет показывать большую превьюху по лонг-тапу.

    Очень простая реализация


    Давайте навернём этот протокол на какую-нибудь кнопку в приложении. Например, на кнопку i в карточке продукта:


    Добавляем 3 строчки кода:

    nutritionButton.showsLargeContentViewer = true
    nutritionButton.addInteraction(UILargeContentViewerInteraction())
    nutritionButton.largeContentTitle = nutritionButton.accessibilityValue


    Готово. Круто, да?

    Только вот чёт иконка, которая подтягивается по дефолту, мне не нравится. Будет лучше, если она будет не двухцветная, а одноцветная с вырезанной формой буквы i. Такая как раз используется для .highlighted-стейта кнопки.

    nutritionButton.largeContentImage = nutritionButton.image(for: .highlighted)


    Норм.

    А теперь завернём в экстеншн:

    extension UIView {
        public func enableLargeContent(title: String? = nil,
                                       image: UIImage? = nil,
                                       scales: Bool = true,
                                       insets: UIEdgeInsets = .zero) {
            guard !showsLargeContentViewer else { return }
            
            showsLargeContentViewer = true
            addInteraction(UILargeContentViewerInteraction())
            
            largeContentTitle = title
            largeContentImage = image
            scalesLargeContentImage = scales
            largeContentImageInsets = insets
        }
    }

    nutritionButton.enableLargeContent(title: nutritionButton.accessibilityValue,
                                       image: nutritionButton.image(for: .highlighted))

    На самом деле многие стандартные иос-контролы уже реализуют часть методов этого протокола. А этот режим выключен, потому что надо стараться по-настоященскому увеличивать контент, а не прятать всё за лупой.

    Перефразирую: используйте эту фичу только в крайнем случае, когда ну совсем никак не можете увеличить контрол.
    Документация на всё это дело доступна в икскоде, если открыть интерфейс UILargeContentViewerItem.


    Демо-проект в моём репо на GitHub
    Dodo Pizza Engineering
    249,41
    О том как IT доставляет пиццу
    Поделиться публикацией

    Похожие публикации

    Комментарии 0

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое