January 6, 2024

48. Изучаем размытие в SwiftUI

Посмотрим как применять размытие в SwiftUI и сравним с размытием из UIKit.

Для наглядной проверки размытия будем использовать список значений CGFloat, составленный с использованием stride:

enum BlurExample {
  static let regularItems = Array(
    stride(
      from: CGFloat(0.01),
      through: CGFloat(0.2),
      by: 0.005
    )
  )
}

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

#Preview("SwiftUI_blur_1") {
  ScrollView {
    VStack(spacing: 0) {
      ForEach(BlurExample.regularItems, id: \.self) { level in
        Text("Степень размытия \(level)")
          .frame(maxWidth: .infinity, alignment: .leading)
          .blur(radius: level) // <- применяем размытие
      }
    }
  }
}

В результате получается экран почти без размытия:

Проверка размытия в SwiftUI - 1

Теперь применим размытие из UIKit (ссылка на код тут) с теми же значениями в новом превью:

#Preview("UIVisualEffectView") {
  ScrollView {
    VStack(spacing: 0) {
      ForEach(BlurExample.regularItems, id: \.self) { level in
        Text("Степень размытия \(level)")
          .frame(maxWidth: .infinity, alignment: .leading)
          .overlay( // <- накладываем UIKit-размытие поверх текста
            UIVisialEffectViewRepresentable(
              effect: UIBlurEffect(style: .dark),
              intensity: level
            )
          )
      }
    }
  }
}

Результат совершенно другой:

Проверка размытия в SwiftUI - 2, используется UIVisualEffect

Теперь поменяем значения размытия в списке, чтобы получить похожий эффект в SwiftUI с применением модификатора blur:

enum BlurExample {
  static let regularItems = Array(
    stride(
      from: CGFloat(0.01),
      through: CGFloat(0.2),
      by: 0.005
    )
  )
  static let extraItems = Array( // <- тут новые значения
    stride(
      from: CGFloat(0.01),
      through: CGFloat(4),
      by: 0.1 // <- сильно отличается шаг между элементами
    )
  )
}

И сделаем превью с этими значениями:

#Preview("SwiftUI_blur_2") {
  ScrollView {
    VStack(spacing: 0) {
      ForEach(BlurExample.extraItems, id: \.self) { level in
        Text("Степень размытия \(level)")
          .frame(maxWidth: .infinity, alignment: .leading)
          .blur(radius: level) // <- применяем размытие
      }
    }
  }
}

Получили результат сильно похожий на вариант с использованием UIKit:

Проверка размытия в SwiftUI - 3

Как видно на скриншотах, можно достичь похожего результата на SwiftUI/UIKit, но для чего может пригодиться размытие из UIKit?

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

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

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