Created
January 22, 2020 11:43
-
-
Save lanserxt/b7eb586178c12aad0e36e3255acd2a56 to your computer and use it in GitHub Desktop.
FMBlurable (Swift 5 update)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// FMBlurable.swift | |
// FMBlurable | |
// | |
// Created by SIMON_NON_ADMIN on 18/09/2015. | |
// Copyright © 2015 Simon Gladman. All rights reserved. | |
// | |
// Thanks to romainmenke (https://twitter.com/romainmenke) for hint on a larger sample... | |
import UIKit | |
protocol Blurable | |
{ | |
var layer: CALayer { get } | |
var subviews: [UIView] { get } | |
var frame: CGRect { get } | |
var superview: UIView? { get } | |
func add(subview: UIView) | |
func removeFromSuperview() | |
func blur(radius: CGFloat) | |
func unBlur() | |
var isBlurred: Bool { get } | |
} | |
extension Blurable | |
{ | |
func blur(radius: CGFloat) | |
{ | |
if self.superview == nil | |
{ | |
return | |
} | |
UIGraphicsBeginImageContextWithOptions(CGSize(width: frame.width, height: frame.height), false, 1) | |
guard let context = UIGraphicsGetCurrentContext() else { return } | |
layer.render(in: context) | |
guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return } | |
UIGraphicsEndImageContext(); | |
guard let blur = CIFilter(name: "CIGaussianBlur"), | |
let this = self as? UIView else | |
{ | |
return | |
} | |
blur.setValue(CIImage(image: image), forKey: kCIInputImageKey) | |
blur.setValue(radius, forKey: kCIInputRadiusKey) | |
let ciContext = CIContext(options: nil) | |
guard let result = blur.value(forKey: kCIOutputImageKey) as? CIImage else { return } | |
let boundingRect = CGRect(x:0, | |
y: 0, | |
width: frame.width, | |
height: frame.height) | |
guard let cgImage = ciContext.createCGImage(result, from: boundingRect) else { return } | |
let filteredImage = UIImage(cgImage: cgImage) | |
let blurOverlay = BlurOverlay() | |
blurOverlay.frame = boundingRect | |
blurOverlay.image = filteredImage | |
blurOverlay.contentMode = UIView.ContentMode.left | |
if let superview = superview as? UIStackView, | |
let index = (superview as UIStackView).arrangedSubviews.firstIndex(of: this) | |
{ | |
removeFromSuperview() | |
superview.insertArrangedSubview(blurOverlay, at: index) | |
} | |
else | |
{ | |
blurOverlay.frame.origin = frame.origin | |
UIView.transition(from: this, | |
to: blurOverlay, | |
duration: 0.2, | |
options: UIView.AnimationOptions.curveEaseIn, | |
completion: nil) | |
} | |
objc_setAssociatedObject(this, | |
&BlurableKey.blurable, | |
blurOverlay, | |
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) | |
} | |
func unBlur() | |
{ | |
guard let this = self as? UIView, | |
let blurOverlay = objc_getAssociatedObject(self as? UIView ?? UIView(), &BlurableKey.blurable) as? BlurOverlay else | |
{ | |
return | |
} | |
if let superview = blurOverlay.superview as? UIStackView, | |
let index = (blurOverlay.superview as? UIStackView)?.arrangedSubviews.firstIndex(of: blurOverlay) | |
{ | |
blurOverlay.removeFromSuperview() | |
superview.insertArrangedSubview(this, at: index) | |
} | |
else | |
{ | |
this.frame.origin = blurOverlay.frame.origin | |
UIView.transition(from: blurOverlay, | |
to: this, | |
duration: 0.2, | |
options: UIView.AnimationOptions.curveEaseIn, | |
completion: nil) | |
} | |
objc_setAssociatedObject(this, | |
&BlurableKey.blurable, | |
nil, | |
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) | |
} | |
var isBlurred: Bool | |
{ | |
return objc_getAssociatedObject(self as? UIView ?? UIView(), &BlurableKey.blurable) is BlurOverlay | |
} | |
} | |
extension UIView: Blurable | |
{ | |
func add(subview: UIView) { | |
self.addSubview(subview) | |
} | |
} | |
class BlurOverlay: UIImageView | |
{ | |
} | |
struct BlurableKey | |
{ | |
static var blurable = "blurable" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Cheers!