January 20, 2024

50. Онбординг на SwiftUI (iOS 14+)

В этой статье покажу вариант реализации онбординга на SwiftUI с поддержкой iOS 14. Нам пригодятся наработки из предыдущих статей: про размытие и про получение размера вьюхи.

Демо онбординга

Особенности этого онбординга

  1. Можно переключаться между шагами в обе стороны (и вперед, и назад)
  2. Переходы между шагами выполняются с анимацией
  3. Гибкая настройка шагов
  4. Работает с iOS 14

Что нужно учесть при использовании

Навбар

В демо на видео можно заметить, что при переходе к кнопке в навбаре:

  • выполняется скрытие заголовка экрана
  • контент немного перемещается наверх (до перехода к следующему шагу, когда заголовок снова возвращается)
  • скрывается крестик для закрытия онбординга (т.к. его перекрывает навбар, даже без текста)

Размытие

В представленной реализации есть принудительное ожидание перед запуском онбординга, чтобы корректно сработало размытие:

     private func showOnboardingIfNeeded(isReady: Bool) {
      guard !showOnboarding, isReady else { return }
      Task {
        // Ждем 0.5 сек, чтобы корректно отобразить блюр
        try? await Task.sleep(nanoseconds: 500_000_000)
        showOnboarding = true
      }
    }

Форма тултипа и стрелка

Тултипом называю UI-элемент, где располагаются тексты с информацией о текущем шаге онбординга и кнопки для управления онбордингом.

Не нужно перегибать палку с радиусом углов - стрелка может остаться в воздухе как на скриншоте ниже:

Демо "летающей" стрелки из-за слишком большого радиуса углов

Есть еще магический extraXOffset, который нужен для выравнивания стрелки (быстрое и рабочее решение):

func path(in rect: CGRect) -> Path {
      let maxBoundedCornerRadius = min(
        min(cornerRadius, rect.width / 2),
        rect.height / 2
      )
      /// Используется во избежание конфликтных ситуаций с радиусом,
      /// чтобы `shape` не ломался из-за слишком большого радиуса углов
      let minBoundedCornerRadius = max(maxBoundedCornerRadius, 0.0)
      /// Магическое число, необходимо для выравнивания стрелки по центру
      let extraXOffset: CGFloat = 12
      switch arrowModel.direction { // }
}

Стили

В моем видео цвета, шрифты и элементы на экране выбраны для примера - их можно и нужно поменять на свои, чтобы было красиво.

Заключение

Работать над этим онбордингом было интересно и непросто, самое сложное - поддерживать iOS 14. Если есть возможность отказаться от iOS 14 в пользу iOS 16.4, например, то можно заменить TooltipShape на popover + presentationCompactAdaptation, и сэкономить много времени.

Уверен, что в моей реализации можно многое улучшить.

Код для этой статьи можно посмотреть тут, а другие статьи - тут.