この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
磨りガラス効果のUIView
iOS 7からUIToolBarやUINavigationBarに磨りガラス効果が導入されましたが、 APIとして磨りガラス効果を持ったUIViewが提供されることはなく、 磨りガラス効果を使うためには iOS-blurや UIImage-BlurredFrameなどの OSSを用いる方法がありました。
iOS 8では磨りガラス効果を実現できるUIViewサブクラスとしてUIVisualEffectViewが提供されています。
早速その使い方を確認していきましょう。
何ができるか?
UIVisualEffectViewは背後に描画されたレイヤにエフェクトをかけ、内部のcontentViewに置かれたUIViewに対してもエフェクトを掛けることができます。
UIVisualEffectViewに適用可能なエフェクトとしてはUIBlurEffectとUIVibrancyEffectがあります。
- UIBlurEffect: 背後のレイヤに磨りガラス効果のエフェクトをかけ、内部のcontentViewに置かれたUIViewに対しては何も作用しません。
- UIVibrancyEffect: UIBlurEffectが適用されたViewの上に置かれる使用方法が想定されています。内部のcontentViewに置かれたUIViewに対して、UIBlurEffectがかかったViewの背後レイヤに対応したエフェクトを掛けることができます。エフェクトはcontentViewに対してのみ作用し、subViewに作用しないことに注意してください。
以下サンプルアプリのコードを中心に具体的な実装方法を解説していきます。
import UIKit
class ViewController: UIViewController {
@IBOutlet var darkImageView: UIImageView?
@IBOutlet var lightImageView: UIImageView?
@IBOutlet var extraLightImageView: UIImageView?
override func viewDidLoad() {
super.viewDidLoad()
addEffectViews()
}
func addEffectViews() {
// 磨りガラスViewを生成
let darkBlurView =
blurEffectView(
fromBlurStyle: .Dark,
frame: darkImageView!.frame)
let lightBlurView =
blurEffectView(
fromBlurStyle: .Light,
frame: lightImageView!.frame)
let extraLightBlurView =
blurEffectView(
fromBlurStyle: .ExtraLight,
frame: extraLightImageView!.frame)
self.view.addSubview(darkBlurView)
self.view.addSubview(lightBlurView)
self.view.addSubview(extraLightBlurView)
// Vibrancyエフェクト
let darkVibrancyView =
vibrancyEffectView(
fromBlurEffect: darkBlurView.effect as UIBlurEffect,
frame: darkBlurView.bounds)
let lightVibrancyView =
vibrancyEffectView(
fromBlurEffect: lightBlurView.effect as UIBlurEffect,
frame: lightBlurView.bounds)
let extraLightVibrancyView =
vibrancyEffectView(
fromBlurEffect: extraLightBlurView.effect as UIBlurEffect,
frame: extraLightBlurView.bounds)
darkBlurView.contentView.addSubview(darkVibrancyView)
lightBlurView.contentView.addSubview(lightVibrancyView)
extraLightBlurView.contentView.addSubview(extraLightVibrancyView)
// Vibrancyエフェクトのかかった画像を追加する
addLogoImageForVibrancyView(darkVibrancyView)
addLogoImageForVibrancyView(lightVibrancyView)
addLogoImageForVibrancyView(extraLightVibrancyView)
// Vibrancyエフェクトのかかったラベルを追加する
addLabelWithText("Dark", forVibrancyView: darkVibrancyView)
addLabelWithText("Light", forVibrancyView: lightVibrancyView)
addLabelWithText("ExtraLight", forVibrancyView: extraLightVibrancyView)
}
// 磨りガラス効果のViewを生成
func blurEffectView(fromBlurStyle style: UIBlurEffectStyle, frame: CGRect) -> UIVisualEffectView {
let effect = UIBlurEffect(style: style)
let blurView = UIVisualEffectView(effect: effect)
blurView.frame = frame
return blurView
}
// VibrancyエフェクトのViewを生成
func vibrancyEffectView(fromBlurEffect effect: UIBlurEffect, frame: CGRect) -> UIVisualEffectView {
let vibrancyEffect = UIVibrancyEffect(forBlurEffect: effect)
let vibrancyView = UIVisualEffectView(effect: vibrancyEffect)
vibrancyView.frame = frame
return vibrancyView
}
// VibrancyエフェクトのViewにロゴイメージを追加
func addLogoImageForVibrancyView(vibrancyView: UIVisualEffectView) {
let logoImage = UIImage(named: "classmethod").imageWithRenderingMode(.AlwaysTemplate)
let imageView = UIImageView(image: logoImage)
imageView.frame = CGRect(origin: CGPointZero, size: logoImage.size / 2)
imageView.contentMode = .ScaleAspectFit
vibrancyView.contentView.addSubview(imageView)
}
// VibrancyエフェクトのViewにラベルを追加
func addLabelWithText(text: NSString, forVibrancyView vibrancyView: UIVisualEffectView) {
let label =
UILabel(frame:
CGRect(origin:
CGPoint(
x: 10.0,
y: vibrancyView.bounds.height / 2),
size:
CGSize(
width: vibrancyView.bounds.width,
height: 20.0)
)
)
label.text = text
vibrancyView.contentView.addSubview(label)
}
}
// CGSizeのリサイズのためのカスタム演算子
func / (lhs: CGSize, rhs: CGFloat) -> CGSize {
return CGSize(width: lhs.width / rhs, height: lhs.height / rhs)
}
こちらのサンプルコードではStoryboardで生成されたUIImageViewがIBOOutletで参照されています。
UIBlurEffect
背後のレイヤに磨りガラス効果のエフェクトを掛けるためには次のようにUIBlurEffectを生成します。それを元に各エフェクトに応じたUIVisualEffectViewを作成します。
l66 - l72
// 磨りガラス効果のViewを生成
func blurEffectView(fromBlurStyle style: UIBlurEffectStyle, frame: CGRect) -> UIVisualEffectView {
let effect = UIBlurEffect(style: style)
let blurView = UIVisualEffectView(effect: effect)
blurView.frame = frame
return blurView
}
UIBlurEffectではUIBlurEffectStyleとして三種類のエフェクトが選べます
enum UIBlurEffectStyle : Int {
case ExtraLight
case Light
case Dark
}
一つ一つのエフェクトを見てみましょう
元画像 | Dark |
---|---|
![]() |
![]() |
Light | ExtraLight |
![]() |
![]() |
UIVibrancyEffect
追加されたUIBlurEffectの種類に応じて、内部に置かれたコンテンツに対して背後レイヤーの影響が強いVibrancyエフェクトを与えます。
まずはコンテンツを置くVibrancyEffect用のViewを生成している箇所を見てみましょう。
l74 - l80
// VibrancyエフェクトのViewを生成
func vibrancyEffectView(fromBlurEffect effect: UIBlurEffect, frame: CGRect) -> UIVisualEffectView {
let vibrancyEffect = UIVibrancyEffect(forBlurEffect: effect)
let vibrancyView = UIVisualEffectView(effect: vibrancyEffect)
vibrancyView.frame = frame
return vibrancyView
}
UIVibrancyEffectは以下のようにBlurEffectのcontentViewの上におきます。
l48-l52
// 磨りガラスエフェクトのかかったUIVisualEffectViewのcontentViewに
// VibrancyエフェクトかかったUIVisualEffectViewを置く
darkBlurView.contentView.addSubview(darkVibrancyView)
lightBlurView.contentView.addSubview(lightVibrancyView)
extraLightBlurView.contentView.addSubview(extraLightVibrancyView)
Vibrancyエフェクトを掛けるViewを置くためのUIVisualEffectViewが用意出来ました。
次に例としてUIImageViewとUILabelを内部のcontentViewに置くことでVibrancyエフェクトをかけてみましょう。
UIImageとの併用
UIImageをVibrancyエフェクトに対応させるためにはUIImageのrenderingModeプロパティをUIImageRenderingMode.AlwaysTemplateに設定する必要があります。
l82-l89
// VibrancyエフェクトのViewにロゴイメージを追加
func addLogoImageForVibrancyView(vibrancyView: UIVisualEffectView) {
let logoImage = UIImage(named: "classmethod").imageWithRenderingMode(.AlwaysTemplate)
let imageView = UIImageView(image: logoImage)
imageView.frame = CGRect(origin: CGPointZero, size: logoImage.size / 2)
imageView.contentMode = .ScaleAspectFit
vibrancyView.contentView.addSubview(imageView)
}
レンダリングモードの調整されたUIImageは、UIButton等に設置されてもUIButtonをVibrancyエフェクトのかかったViewのcontentViewに入れればやはりエフェクトがかかります。
UILabelとの併用
UILabelについては、内部のcontentViewに置くだけで適切に調整されたエフェクトがかかります。
l91-l107
// VibrancyエフェクトのViewにラベルを追加
func addLabelWithText(text: NSString, forVibrancyView vibrancyView: UIVisualEffectView) {
let label =
UILabel(frame:
CGRect(origin:
CGPoint(
x: 10.0,
y: vibrancyView.bounds.height / 2),
size:
CGSize(
width: vibrancyView.bounds.width,
height: 20.0)
)
)
label.text = text
vibrancyView.contentView.addSubview(label)
}
最後にこれらのサンプルコードで生成された画面を見てみましょう。