別のUIViewController
をモーダルに表示するUIViewController
があります。モーダルビューコントローラーに、iOS7で導入されたぼかし/透過性を持たせたいです。新しいUIVisualEffect
を使用してみましたが、UIViews
でのみ機能し、UIViewControllers
では機能しないようです。
これが私が書いたコードです。サブビューとして追加したすべてのビューは、その下のぼやけたビューの上にあるユーザーインターフェイスに表示したいものです。
提示するビューコントローラーでは、ブラーを適用する前にモーダルビューコントローラーに渡す画面のスクリーンショットを撮ります。
View Controllerの提示:
- (UIImage *)viewImage {
CGSize size = CGSizeMake(self.view.frame.size.width,self.view.frame.size.height);
UIGraphicsBeginImageContext(size);
[self.view drawViewHierarchyInRect:(CGRect){CGPointZero, self.view.frame.size.width, self.view.frame.size.height} afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
モーダルビューコントローラーの場合:
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:[[UIImageView alloc] initWithImage:self.backgroundImage]];
//self.backgroundImage is the image that the method above returns, it's a screenshot of the presenting view controller.
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
[blurEffectView setFrame:self.view.bounds];
[self.view addSubview:blurEffectView];
[self.view bringSubviewToFront:self.cancelButton];
[self.view bringSubviewToFront:self.titleLabel];
[self.view bringSubviewToFront:self.tableView];
}
UIVisualEffectViewを使用する場合、スナップショットを生成する必要はありません。 「 IImage *)viewImage」を削除し、モデルビューコントローラーで、ビューコントローラービューと一致するサイズのUIVisualEffectViewを追加し、すべての「コントロール」ビューをUIVisualEffectViewのcontentViewに追加してみてください。
- (void)viewDidLoad {
[super viewDidLoad];
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
[blurEffectView setFrame:self.view.bounds];
[self.view addSubview:blurEffectView];
[blurEffectView.contentView addSubview:self.cancelButton];
[blurEffectView.contentView addSubview:self.titleLabel];
[blurEffectView.contentView addSubview:self.tableView];
}
---(https://developer.Apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIVisualEffectView/index.html
ストーリーボードでは試していませんが、テスト済みの動作スニペットを次に示します。始めるのに良い場所かもしれません。 objcへの翻訳はかなり簡単なはずです
これが現在のViewControllerです
import UIKit
class BaseViewController: UIViewController {
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
override func viewDidLoad() {
super.viewDidLoad()
var backgroundImage = UIImageView(image: UIImage(named: "image"))
self.view.addSubview(backgroundImage)
var button = UIButton(frame: CGRectMake(0, 100, 320, 50))
button.setTitle("Lorem Ipsum", forState: UIControlState.Normal)
button.backgroundColor = UIColor.redColor()
button.addTarget(self, action: "onButtonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
}
func onButtonTapped(sender: UIButton?) {
var modal = ModalViewController(nibName: nil, bundle: nil)
modal.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
self.presentViewController(modal, animated: true, completion: {})
}
}
これがモーダルです
import UIKit
class ModalViewController: UIViewController {
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.clearColor()
let effect = UIBlurEffect(style: UIBlurEffectStyle.Light)
let blurView = UIVisualEffectView(effect: effect)
blurView.frame = self.view.bounds
self.view.addSubview(blurView)
}
}
In Swift 3
新しいUIViewControllerへのモーダル遷移を実行していて、最後のVCを確認できるように、背景が明確なコンテキスト上でそれを実行していることがわかりました。 IBで設定されたUIVisualEffectビューの使用は正しく機能しません。取得できるのは、新しいビューのプレゼンテーションの最後にレンダリングされるぼかしです。
Interface Builderの場合:
別のビューへのモーダルセグエを構築し、種類:モーダルに提示、遷移:クロスフェードを作成します。次に、「showMainMenu」のような識別子を付けます。
宛先VCで、最初のビューがAspectToFitが設定されたUIImageViewになるように設定し、制約のために両側を0-0-0-0に設定します。 2番目のSubViewは、VCの側面で0-0-0-0に設定されたUIBlurViewです。次に、素敵な対照的なテキストのように、UIBlurViewの上に要素を配置します。
セグエするVCのUIImageViewに設定する背景の変数を作成します。
var background:UIImage! = UIImage()
今すぐセグエを実行すると、ぼけが飛び出し、ひどく見えることに気付くでしょう。
この問題を解決するには、UIImageのこの拡張コードを使用してスナップショットを作成するコードを記述します
extension UIImage {
class func takeScreenshot(view: UIView) -> UIImage? {
// Create screenshot
UIGraphicsBeginImageContext(view.bounds.size)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let screenshot:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
print("Taking Screenshot")
UIGraphicsEndImageContext()
return screenshot
}
}
それから私のセグエで私は次のことをします:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showMainMenu" {
let vc = segue.destination as! MainViewController
// I am using a VERY long scroll view so self.view.window! ensures that you only take a picture of your actual view instead of a view that is longer than your screen size.
let screenshot: UIImage = UIImage.takeScreenshot(view: self.view.window!)!
vc.background = screenshot
}
}
セグエされたら、新しいViewControllerで必ずこれを実行してください。
// set the image over to the background image.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.backgroundImage.image = background
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// prevent the blurView for just popping in due to the segue
UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveEaseInOut, animations: {
// make the background transparent so you can now see what is beneath that layer.
self.backgroundImage.alpha = 0
})
}
このようにして、コードをあまり使わずに、甘いモーダルIBフェードインを取得できます。さらに、最後のVC現在の要素の下に移動要素がある場合は、ぼかしの下に表示されます。
お役に立てれば!
私のgitでデモプロジェクトをチェックアウトしてください!
https://github.com/yungdai/Smooth-blur-transition-using-storyboard
最も簡単な方法は、このコードをコピーしてviewDidLoadに貼り付けることです:)
UIVisualEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = self.view.bounds;
self.view insertSubview:visualEffectView atIndex:0];
@YarGnawhに感謝します。これはiOS8でテストされました
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
[blurEffectView setFrame:self.view.bounds];
self.tableView.backgroundView = blurEffectView;
これは上記の答えの組み合わせです。
これは、iOS9.2.1用のXcode7.2.1(Swift 2.1。)のInterfaceBuilderで機能します。
コードはシミュレーターとデバイスでテストされています。
Interface Builderの場合:
viewDidLoad
のUIViewController
の3番目のステップを設定しても機能しませんUIViewController
をクリックし、Custom Class
"-Class
の下でYOUTransparentModalVC
(または任意の名前)をクリックすることを忘れないでください。コード内:
import UIKit
let IMAGE_OVERLAY_NAME = "backgroundColorExample"
class YOUTransparentModalVC: UIViewController
{
private var backgroundImageOverlayIV:UIImageView!
override func viewDidLoad()
{
super.viewDidLoad()
self.setupTransparentView()
self.setupDissmissingVCOnTap()
self.setupBackgroudImage()
}
private func setupTransparentView()
{
self.view.backgroundColor = UIColor.clearColor()
let effect = UIBlurEffect(style: UIBlurEffectStyle.Light)
let blurView = UIVisualEffectView(effect: effect)
blurView.frame = self.view.bounds
self.view.addSubview(blurView)
}
private func setupBackgroudImage()
{
self.backgroundImageOverlayIV = UIImageView(frame: self.view.frame)
self.backgroundImageOverlayIV.image = UIImage(named: IMAGE_OVERLAY_NAME)
self.view.addSubview(self.backgroundImageOverlayIV)
}
private func setupDissmissingVCOnTap()
{
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissVC")
view.addGestureRecognizer(tap)
}
func dismissVC()
{
self.dismissViewControllerAnimated(true, completion: nil)
}
}
storyboardとconstraintsのみを使用してぼかし効果を示すサンプルプロジェクトを見てください。 -)。
GitHubデモ: リンク