Вот забавный небольшой эксперимент, демонстрирующий силу расширений протокола 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 здесь . Наслаждайтесь!