Статьи

Применение размытия по Гауссу к UIViews с расширениями протокола Swift

Вот  забавный небольшой эксперимент,  демонстрирующий силу расширений протокола Swift   для применения  фильтра CIGaussianBlur  Core Image к любому UIView без затрат на разработку. Код может быть расширен для применения любого фильтра Core Image, такого как полутоновый экран или настройка цвета.

Blurable  — это простой протокол, который заимствует некоторые методы и переменные из  UIView:

 var layer: CALayer { get }
    var subviews: [UIView] { get }
    var frame: CGRect { get }

    func addSubview(view: UIView)

    func bringSubviewToFront(view: UIView)

… и добавляет несколько своих:

Очевидно, что, будучи протоколом, он сам по себе мало что делает. Однако, добавив расширение, я могу ввести функциональность по умолчанию. Кроме того, расширяя  UIView  для реализации  Blurable,  каждый компонент от сегментированного элемента управления до горизонтального ползунка может быть размытым:

    

extension UIView: Blurable

    {



    }

Механика  Blurable

Получить размытое представление  UIView  довольно просто: мне нужно начать контекст изображения, использовать метод renderInContext слоя представления для рендеринга в контекст, а затем получить UIImage из контекста:

    UIGraphicsBeginImageContextWithOptions(CGSize(width: frame.width, height: frame.height), false, 1)



    layer.renderInContext(UIGraphicsGetCurrentContext()!)



    let image = UIGraphicsGetImageFromCurrentImageContext()







    UIGraphicsEndImageContext();

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


    guard let blur = CIFilter(name: "CIGaussianBlur") else

    {

        return

    }





    blur.setValue(CIImage(image: image), forKey: kCIInputImageKey)

    blur.setValue(blurRadius, forKey: kCIInputRadiusKey)



    let ciContext  = CIContext(options: nil)



    let result = blur.valueForKey(kCIOutputImageKey) as! CIImage!



    let boundingRect = CGRect(x: -blurRadius * 4,

        y: -blurRadius * 4,

        width: frame.width + (blurRadius * 8),

        height: frame.height + (blurRadius * 8))



    let cgImage = ciContext.createCGImage(result, fromRect: boundingRect)







    let filteredImage = UIImage(CGImage: cgImage)

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

Следующим шагом является добавление UIImageView в мое представление и скрытие всех остальных представлений. Я подклассифицировал UIImageView к BlurOverlay, так что когда дело доходит до его удаления, я могу быть уверен, что я не удаляю существующий UIImageView: 

 let blurOverlay = BlurOverlay()
    blurOverlay.frame = boundingRect

    blurOverlay.image = filteredImage

    subviews.forEach{ $0.hidden = true }


    addSubview(blurOverlay)

Когда дело доходит до размытия, я хочу убедиться, что последнее подпредставление — это один из моих BlurOverlay, удалите его и раскройте существующие виды:

  func unBlur()
    {
        if let blurOverlay = subviews.last as? BlurOverlay
        {
            blurOverlay.removeFromSuperview()

            subviews.forEach{ $0.hidden = false }
        }

    }

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

  var isBlurred: Bool
  {
      return subviews.last is BlurOverlay
  }

Размытие UIView

Чтобы размыть и удалить размытие, просто вызовите blur () и unBlur () в  UIView :


    segmentedControl.unBlur()
    segmentedControl.blur(blurRadius: 2)

Исходный код

Как всегда,  исходный код этого проекта доступен в моем репозитории GitHub здесь . Наслаждайтесь!