Reputation: 1966
I could be completely googling the wrong thing however I am trying to achieve this effect when images don't fit the required aspect ratio/dimensions. However, if the image is of size and doesn't require resizing, then this effect is not necessary. It's seen on the majority of large social medias, especially in stories.
Source: Google Images
Is there a library or code that mimics this sort of behaviour?
Upvotes: 2
Views: 2684
Reputation: 561
The traditional UIKit solution is creating your own control view. Following is @IBDesignable and @IBInspectable class BlurImageView subclass of UIView. Create a file with name BlurImageView.swift and add following code to it. In storyboard in your view controller add an UIVIew and change its custom class using identity inspector to BlurImageView. Set image and you are all set.
@IBDesignable
class BlurImageView: UIView {
private var backgroundImageView: UIImageView!
private var foregroundImageView: UIImageView!
private lazy var blurEffectView: UIVisualEffectView = UIVisualEffectView(effect: UIVisualEffect())
@IBInspectable
public var alphaForBlurEffect: CGFloat = 0.7 {
didSet {
applyBlur()
}
}
public var blurEffect = UIBlurEffect(style: .regular) {
didSet {
applyBlur()
}
}
@IBInspectable
public var image: UIImage? {
set {
backgroundImageView.image = newValue
foregroundImageView.image = newValue
}
get {
return foregroundImageView.image
}
}
// MARK: Initilisation
override init(frame: CGRect) {
super.init(frame: frame)
setupImages()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupImages()
}
private func createBlurEffectView() -> UIVisualEffectView {
// create effect
let effectView = UIVisualEffectView(effect: blurEffect)
// set boundry and alpha
effectView.frame = self.bounds
effectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
effectView.alpha = alphaForBlurEffect
return effectView
}
fileprivate func addImageView() -> UIImageView {
let imageView = UIImageView(frame: self.bounds)
imageView.clipsToBounds = true
self.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
imageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
return imageView
}
private func setupImages() {
self.clipsToBounds = true
// Setup background view
backgroundImageView = addImageView()
backgroundImageView.contentMode = .scaleAspectFill
applyBlur()
// setup foreground view
foregroundImageView = addImageView()
foregroundImageView.contentMode = .scaleAspectFit
}
private func applyBlur() {
blurEffectView.removeFromSuperview()
// generate new view
blurEffectView = createBlurEffectView()
backgroundImageView.addSubview(blurEffectView)
}
}
Upvotes: 0
Reputation: 561
Here is SwiftUI solution inline with the one mentioned by Chris
I tested it using Xcode 11.2 and iOS 13.2. Note: I did not include the two test images named "VRectImage" and "HRectImage".
struct BlurImageView: View {
let name = "VRectImage" // "VRectImage"
var body: some View {
ZStack {
Image(self.name)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 300, height: 300)
.clipped()
.blur(radius: 15)
Image(self.name)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 300, height: 300)
}
.clipped()
}
}
Upvotes: -1
Reputation: 8126
"Normally" i would say, this is the solution:
...but sigh unfortunately - and i have no idea why - the .fit does not work anymore as i tested it (just could test on 13.2) and it does not (!) show the whole picture but with .filled) ( to test it you have to insert a portrait photo, which is bigger than the screen to see my effect)
or shouldn't .fit show the whole picture? Am i wrong!?
struct ContentView: View {
var name : String
var body: some View {
ZStack {
Image(self.name)
.resizable()
.scaledToFill()
.blur(radius: 15)
Image(self.name)
.resizable()
.scaledToFit()
}
}
}
Upvotes: 2