Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kylehowells/1c31ef6072e9162615b45bb7ff127852 to your computer and use it in GitHub Desktop.
Save kylehowells/1c31ef6072e9162615b45bb7ff127852 to your computer and use it in GitHub Desktop.
Examples of the different UIBlurEffect styles available in iOS
import UIKit
import PhotosUI
class SystemBlurExamplesViewController: UIViewController, PHPickerViewControllerDelegate {
// MARK: - Setup View
override func loadView() {
self.view = SystemBlurExamplesView()
}
var exampleView: SystemBlurExamplesView {
return self.view as! SystemBlurExamplesView
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.exampleView.effectsButton.showsMenuAsPrimaryAction = true
self.exampleView.vibrancyButton.showsMenuAsPrimaryAction = true
self.exampleView.pickImageButton.addTarget(self, action: #selector(didPressImageSelect), for: .touchUpInside)
self.currentStyle = self.blurEffects[3]
}
// MARK: - Button Action
@objc func didPressImageSelect() {
var config = PHPickerConfiguration()
config.selectionLimit = 1
config.filter = PHPickerFilter.images
let pickerViewController = PHPickerViewController(configuration: config)
pickerViewController.delegate = self
self.present(pickerViewController, animated: true, completion: nil)
}
// MARK: - Background Effects
struct EffectInfo {
let style: UIBlurEffect.Style
let name: String
}
let blurEffects:[EffectInfo] = [
EffectInfo(style: .extraLight, name: "ExtraLight"),
EffectInfo(style: .light, name: "Light"),
EffectInfo(style: .dark, name: "Dark"),
EffectInfo(style: .regular, name: "Regular"),
EffectInfo(style: .prominent, name: "Prominent"),
EffectInfo(style: .systemUltraThinMaterial, name: "SystemUltraThinMaterial"),
EffectInfo(style: .systemThinMaterial, name: "SystemThinMaterial"),
EffectInfo(style: .systemMaterial, name: "SystemMaterial"),
EffectInfo(style: .systemThickMaterial, name: "SystemThickMaterial"),
EffectInfo(style: .systemChromeMaterial, name: "SystemChromeMaterial"),
EffectInfo(style: .systemUltraThinMaterialLight, name: "SystemUltraThinMaterialLight"),
EffectInfo(style: .systemThinMaterialLight, name: "SystemThinMaterialLight"),
EffectInfo(style: .systemMaterialLight, name: "SystemMaterialLight"),
EffectInfo(style: .systemThickMaterialLight, name: "SystemThickMaterialLight"),
EffectInfo(style: .systemChromeMaterialLight, name: "SystemChromeMaterialLight"),
EffectInfo(style: .systemUltraThinMaterialDark, name: "SystemUltraThinMaterialDark"),
EffectInfo(style: .systemThinMaterialDark, name: "SystemThinMaterialDark"),
EffectInfo(style: .systemMaterialDark, name: "SystemMaterialDark"),
EffectInfo(style: .systemThickMaterialDark, name: "SystemThickMaterialDark"),
EffectInfo(style: .systemChromeMaterialDark, name: "SystemChromeMaterialDark"),
]
private func generateBlurMenu() {
var menuOptions:[UIMenuElement] = []
for effect in self.blurEffects {
let isCurrentStyle = (self.currentStyle.style == effect.style)
let action = UIAction.init(title: effect.name, state: isCurrentStyle ? .on : .off, handler: { [weak self] action in
self?.currentStyle = effect
})
menuOptions.append(action)
}
let menu = UIMenu(title: "Blur Styles", children: menuOptions)
self.exampleView.effectsButton.menu = menu;
}
// MARK: - Vibrancy Effects
struct VibrancyInfo {
let style: UIVibrancyEffectStyle?
let name:String
}
let vibrancyEffects:[VibrancyInfo] = [
VibrancyInfo(style: nil, name: "None"),
VibrancyInfo(style: .label, name: "Label"),
VibrancyInfo(style: .secondaryLabel, name: "Secondary Label"),
VibrancyInfo(style: .tertiaryLabel, name: "Tertiary Label"),
VibrancyInfo(style: .quaternaryLabel, name: "Quaternary Label"),
VibrancyInfo(style: .fill, name: "Fill"),
VibrancyInfo(style: .secondaryFill, name: "Secondary Fill"),
VibrancyInfo(style: .tertiaryFill, name: "Tertiary Fill"),
VibrancyInfo(style: .separator, name: "Separator"),
]
private func generateStyleMenu() {
var menuOptions:[UIMenuElement] = []
for effect in self.vibrancyEffects {
let isCurrentStyle = (self.vibrancyEffect == effect.style)
let action = UIAction.init(title: effect.name, state: isCurrentStyle ? .on : .off, handler: { [weak self] action in
self?.vibrancyEffect = effect.style
self?.exampleView.vibrancyLabel.text = effect.name
self?.exampleView.vibrancyEffectView.setNeedsLayout()
})
menuOptions.append(action)
}
let menu = UIMenu(title: "Vibrancy Styles", children: menuOptions)
self.exampleView.vibrancyButton.menu = menu;
}
// MARK: - Update Background
var currentStyle:EffectInfo = EffectInfo(style: .regular, name: "Regular") {
didSet {
self.refreshStyle()
}
}
var vibrancyEffect:UIVibrancyEffectStyle? = nil {
didSet {
self.refreshStyle()
}
}
private func refreshStyle() {
self.exampleView.titleLabel.text = self.currentStyle.name
self.exampleView.setNeedsLayout()
let blurEffect = UIBlurEffect(style: self.currentStyle.style)
self.exampleView.effectsView.effect = blurEffect
if let vibrancyEffect = self.vibrancyEffect {
let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect, style: vibrancyEffect)
self.exampleView.vibrancyEffectView.effect = vibrancyEffect
}
else {
self.exampleView.vibrancyEffectView.effect = nil
}
self.generateBlurMenu()
self.generateStyleMenu()
}
// MARK: - PHPickerViewControllerDelegate
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
for result in results {
result.itemProvider.loadObject(ofClass: UIImage.self) { object, error in
if let resultObject = object as? UIImage {
DispatchQueue.main.async {
self.exampleView.backgroundImageView.image = resultObject
}
}
}
}
picker.dismiss(animated: true)
}
}
// MARK: - SystemBlurExamplesView
class SystemBlurExamplesView : UIView {
let backgroundImageView:UIImageView = {
let imv = UIImageView()
imv.contentMode = .scaleAspectFill
if let im = UIImage(named: "transparentGrid") {
imv.backgroundColor = UIColor(patternImage: im)
}
return imv
}()
let pickImageButton:UIButton = {
let b = UIButton(type: .custom)
var config = UIButton.Configuration.filled()
config.image = UIImage(systemName: "photo")
b.configuration = config
b.sizeToFit()
return b
}()
let effectsButton:UIButton = {
let b = UIButton(type: .custom)
var config = UIButton.Configuration.filled()
config.image = UIImage(systemName: "sparkles")
b.configuration = config
b.sizeToFit()
return b
}()
let vibrancyButton:UIButton = {
let b = UIButton(type: .custom)
var config = UIButton.Configuration.filled()
config.image = UIImage(systemName: "sparkles")
b.configuration = config
b.sizeToFit()
return b
}()
let effectsView:UIVisualEffectView = {
let efv = UIVisualEffectView()
efv.effect = UIBlurEffect(style: .regular)
return efv
}()
let vibrancyEffectView:UIVisualEffectView = {
let efv = UIVisualEffectView()
return efv
}()
let titleLabel:UILabel = {
let l = UILabel()
l.backgroundColor = UIColor.white
l.textColor = UIColor.black
l.font = UIFont.systemFont(ofSize: 15, weight: .medium)
l.adjustsFontSizeToFitWidth = true
l.allowsDefaultTighteningForTruncation = true
return l
}()
let iconImageView:UIImageView = {
let imv = UIImageView()
imv.image = UIImage(systemName: "sun.haze")
return imv
}()
let vibrancyLabel:UILabel = {
let l = UILabel()
l.text = "Vibrancy Label"
l.textColor = UIColor.black
l.font = UIFont.systemFont(ofSize: 16, weight: .bold)
l.adjustsFontSizeToFitWidth = true
l.allowsDefaultTighteningForTruncation = true
return l
}()
// MARK: - Setup
override init(frame: CGRect) {
super.init(frame: frame)
self.commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
self.commonInit()
}
func commonInit() {
self.addSubview(self.backgroundImageView)
self.addSubview(self.pickImageButton)
self.addSubview(self.effectsButton)
self.addSubview(self.titleLabel)
self.addSubview(self.vibrancyButton)
self.addSubview(self.effectsView)
self.effectsView.contentView.addSubview(self.vibrancyEffectView)
self.vibrancyEffectView.contentView.addSubview(self.vibrancyLabel)
self.vibrancyEffectView.contentView.addSubview(self.iconImageView)
}
// MARK: - Layout
override func layoutSubviews() {
super.layoutSubviews()
let size = self.bounds.size
let safeArea = self.safeAreaInsets
self.backgroundImageView.frame = self.bounds
self.pickImageButton.frame = {
var frame = CGRect()
frame.size = self.pickImageButton.bounds.size
frame.origin.x = safeArea.left + 10
frame.origin.y = safeArea.top + 10
return frame
}()
self.effectsButton.frame = {
var frame = CGRect()
frame.size = self.effectsButton.bounds.size
frame.origin.x = size.width - (safeArea.right + frame.width + 10)
frame.origin.y = safeArea.top + 10
return frame
}()
self.vibrancyButton.frame = {
var frame = CGRect()
frame.size = self.vibrancyButton.bounds.size
frame.origin.x = size.width - (safeArea.right + frame.width + 10)
frame.origin.y = self.effectsButton.frame.maxY + 10
return frame
}()
self.titleLabel.frame = {
var frame = CGRect()
let labelSize = self.titleLabel.sizeThatFits(size)
frame.size = labelSize
let maxWidth = (self.effectsButton.frame.origin.x - self.pickImageButton.frame.maxX) - 10
frame.size.width = min(frame.width, maxWidth)
frame.origin.y = self.effectsButton.frame.midY - (frame.height * 0.5)
frame.origin.x = (size.width - frame.width) * 0.5
return frame
}()
let buttonBottomY = self.vibrancyButton.frame.maxY
let availableHeight = (size.height - (buttonBottomY + safeArea.bottom))
let effectWidth = min(size.width * 0.8, (availableHeight * 0.6))
self.effectsView.frame = {
var frame = CGRect()
frame.size.width = effectWidth
frame.size.height = effectWidth
frame.origin.x = (size.width - effectWidth) * 0.5
frame.origin.y = (buttonBottomY + (availableHeight * 0.5)) - (frame.height * 0.5);
return frame
}()
self.vibrancyEffectView.frame = self.effectsView.bounds
self.vibrancyLabel.frame = {
var frame = CGRect()
let labelSize = self.vibrancyLabel.sizeThatFits(size)
frame.size = labelSize
let maxWidth = (self.effectsView.bounds.width * 0.9)
frame.size.width = min(frame.width, maxWidth)
frame.origin.y = (self.effectsView.bounds.height - frame.height) * 0.5
frame.origin.x = (self.effectsView.bounds.width - frame.width) * 0.5
return frame
}()
self.iconImageView.frame = {
var frame = CGRect()
frame.size.width = 40
frame.size.height = 40
frame.origin.x = (self.effectsView.bounds.width - frame.width) * 0.5
frame.origin.y = self.vibrancyLabel.frame.minY - (frame.height + 4)
return frame
}()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment