UINavigationController - clear background using UIBlurEffect - ios

I am using UIBlurEffect in a UIViewController which is presented with a .crossDissolve transition style. The UIViewController has a collectionView added to its view so both have a clear background.
HomeViewController.swift
func showLiveDealsCategory(sender:UITextField){
let catSelection = LiveDealCategorySelection()
//let navContr = UINavigationController(rootViewController: catSelection)
catSelection.modalPresentationStyle = .custom
catSelection.modalTransitionStyle = .crossDissolve
self.present(catSelection, animated: true, completion: nil)
}
LiveDealCategorySelection.swift
func setupBackgroundView(){
if !UIAccessibilityIsReduceTransparencyEnabled() {
self.view.backgroundColor = .clear
let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = (self.view?.bounds)!
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.view?.addSubview(blurEffectView)
} else {
self.collectionView?.backgroundColor = UIColor.black
}
}
This is the result where you can see the mapView behind LiveDealCategorySelection:
The problem is when I embed the view controller inside a UINavigationController because I am not able to set its background color to .clear:
func showLiveDealsCategory(sender:UITextField){
let catSelection = LiveDealCategorySelection()
let navContr = UINavigationController(rootViewController: catSelection)
catSelection.modalPresentationStyle = .custom
catSelection.modalTransitionStyle = .crossDissolve
self.present(navContr, animated: true, completion: nil)
}
In LiveDealCategorySelection I tried:
override func viewWillAppear(_ animated: Bool) {
if self.navigationController != nil {
self.navigationController!.view.backgroundColor = .clear
self.navigationController!.view.tintColor = .clear
}
}
and I also tried to set the background color to .clear when I instantiate the navigation controller but I get a black background. Any idea?

You just forgot to move the presentation style to the UINavigationController
navContr.modalPresentationStyle = .custom

With navigation controller you cannot achieve that you want. Only Modal presentation with OverCurrentContext, supports transition from one view controller to another with clear or semi transparent background.
If you want blur background for this view controller then present this view controller using modal presentation with 'custom (or over current context)'
else try this:
func showLiveDealsCategory(sender:UITextField){
let catSelection = LiveDealCategorySelection()
let navContr = UINavigationController(rootViewController: catSelection)
navContr.modalPresentationStyle = .custom // << Mark this update
catSelection.modalPresentationStyle = .custom
catSelection.modalTransitionStyle = .crossDissolve
self.present(navContr, animated: true, completion: nil)
}

Related

Present VC programmatically

How to present UIViewController() inside of UINavigationController ? My controller presenting not fullscreen. I want my app to look like this enter image description here, but it is end up like this enter image description here
I making app without Storyboard(Programmatically)
let customVC = UIViewController()
customVC.view.backgroundColor = .green
customVC.modalPresentationStyle = .fullScreen
let navVC = UINavigationController(rootViewController: customVC)
self.present(navVC, animated: true, completion: nil)
let customVC = DestinationController()
let navVC = UINavigationController(rootViewController: customVC)
// this line overFullScreen
navVC.modalPresentationStyle = .overFullScreen
// for more style
navVC.modalTransitionStyle = .crossDissolve
self.present(navVC, animated: true, completion: nil)
your class where you want to go or present
class DestinationController:UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
}
}

UIViewController blur background turns into gray

I would like to use blur background for my view controller but as soon as the view is loaded, the whole thing turns into gray.
I present the view controller by performing a segue from another view, and in the viewDidLoad() method of the view controller, I implement the blur effect as given below
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.clear
let blurBgView = UIVisualEffectView(effect: UIBlurEffect(style: .extraLight))
blurBgView.translatesAutoresizingMaskIntoConstraints = false
view.insertSubview(blurBgView, at: 0)
NSLayoutConstraint.activate([
blurBgView.heightAnchor.constraint(equalTo: view.heightAnchor),
blurBgView.widthAnchor.constraint(equalTo: view.widthAnchor),
])
}
This is how it looks like
How can I implement a blur background for my view controller?
I use XCode 9.3, Swift 4.1
Thanks
Present your view controller and set its modalPresentationStyle from your initial vc:
let newController = NewViewController()
newController.modalPresentationStyle = .overCurrentContext
present(newController, animated: true, completion: nil)
Or, if you are preparing for the segue:
let newController: NewViewController = segue.destination as! NewViewController
newController.modalPresentationStyle = .overCurrentContext
And in the NewViewController class in viewDidLoad() add your code.

Navigation bar on iPhone popover

I don't ask for a lot out of life, but I'd give a lot to know how to get a navigation bar on this popover:
Here's my storyboard:
And here's my code presenting the popover:
#IBAction func doButton(_ sender: Any) {
let vc = PopViewController()
vc.preferredContentSize = CGSize(width: 260,height: 300)
vc.modalPresentationStyle = .popover
vc.view.backgroundColor = UIColor.green
if let pres = vc.presentationController {
pres.delegate = (self as UIAdaptivePresentationControllerDelegate)
}
self.present(vc, animated: true)
if let pop = vc.popoverPresentationController {
pop.sourceView = (sender as! UIView)
pop.sourceRect = (sender as! UIView).bounds
pop.backgroundColor = vc.view.backgroundColor
}
}
}
extension ViewController : UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}
}
(Thanks to #matt, BTW, for the above code!)
I've searched high and low on Google yet haven't found an answer that I could understand. I tried to add the nav bar in Storyboard, but no dice--the only element that would accept it was the prototype cell in the table view.
Please don't redirect to something written 7 years ago--I've already read most of them, and I'm using Swift now. Certainly, I may have overlooked a clear answer, and I'll be humble and contrite if that's the case. But meantime, I'd sure appreciate some help if ya got it!
Thanks!
Change your right tableview controller to a navigation controller with a tableViewController root. The navigation Controller gets an identifier : "navigation".
Now you can change the first code of doButton function, and keep the rest.
#IBAction func doButton(_ sender: Any) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "navigation") as! UINavigationController
vc.preferredContentSize = CGSize(width: 260,height: 300)
vc.modalPresentationStyle = .popover
vc.view.backgroundColor = UIColor.green
if let pres = vc.presentationController {
pres.delegate = (self as UIAdaptivePresentationControllerDelegate)
}
self.present(vc, animated: true)
if let pop = vc.popoverPresentationController {
pop.sourceView = (sender as! UIView)
pop.sourceRect = (sender as! UIView).bounds
pop.backgroundColor = vc.view.backgroundColor
}
}
finally , you will get the nav bar in your popover.

Swift Modal View Controller with transparent background going beyond tab bar

I tried same code mention in gist : https://gist.github.com/barbietunnie/e5547f35180436ac102cac52a15f8ca3
func showModal() {
let modalViewController = ModalViewController()
modalViewController.modalPresentationStyle = .OverCurrentContext
presentViewController(modalViewController, animated: true, completion: nil)
}
class ModalViewController: UIViewController {
override func viewDidLoad() {
view.backgroundColor = UIColor.clearColor()
view.opaque = false
}
}
Its working fine but in case of tab bar the content is getting beyond tab bar, How can we make content visible upper/front of tab bar?
It worked via vc.modalPresentationStyle = .overFullScreen
I hope it will work for you,
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let controller = mainStoryboard.instantiateViewController(withIdentifier: "ModalViewController") as! ModalViewController
controller.modalPresentationStyle = .overCurrentContext
Thank You.

Modal view controller does not cover status bar

I'm developing an ios app. I have a a main view and in this view
im trying to present a modal view controller with dimmed background(black with opacity).
The problem is that the status bar is not affected by this color and remains the same.
This is how i present the view controller:
let shareViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ShareViewController") as! ShareViewController
shareViewController.battle = battle
shareViewController.delegate = self
let animation = CATransition()
animation.duration = 1
animation.type = kCATransitionFade
self.view.window?.layer.addAnimation(animation, forKey: kCATransition)
presentViewController(shareViewController, animated: false) {
() in
// nothing here
}
Here are some screenshots to demonstrate the problem:
This is the problem(status bar color):
Problem illustration
This is the modal view in storyboard:
storyboard
I cannot reproduce your problem, the following code works without problems in my single view app:
let viewController = UIViewController()
viewController.modalPresentationStyle = .overFullScreen
viewController.view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
let animation = CATransition()
animation.duration = 1
animation.type = kCATransitionFade
self.view.window?.layer.add(animation, forKey: kCATransition)
self.present(viewController, animated: false, completion: nil)
However note that you should be presenting over the root controller of the view. Sometimes you can get strange effects when presenting from your internal controllers:
self.view.window?.rootViewController?.present(viewController, animated: false, completion: nil)
Also make sure you are using the correct modalPresentationStyle.
Set your view controller as the root view controller of a UIWindow, then present the window at the UIWindowLevelAlert level.
Below is a Swift 3 class used to animate a modal popup over all other UI elements, including the status bar. A scrim view is used to shade background UI and intercept touches to dismiss the view.
import UIKit
class ModalViewController: UIViewController {
private let scrimView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.black
view.alpha = 0.0
return view
}()
private var myWindow: UIWindow?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.clear
// Setup scrim View
view.addSubview(scrimView)
view.topAnchor.constraint(equalTo: scrimView.topAnchor).isActive = true
view.leftAnchor.constraint(equalTo: scrimView.leftAnchor).isActive = true
view.rightAnchor.constraint(equalTo: scrimView.rightAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: scrimView.bottomAnchor).isActive = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismiss as (Void) -> Void))
scrimView.addGestureRecognizer(tapGestureRecognizer)
// Layout custom popups or action sheets
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 0.25) {
self.scrimView.alpha = 0.5
// Animate in custom popups or action sheets
}
}
func present() {
myWindow = UIWindow(frame: UIScreen.main.bounds)
myWindow?.windowLevel = UIWindowLevelAlert
myWindow?.backgroundColor = UIColor.clear
myWindow?.rootViewController = self
myWindow?.isHidden = false
}
func dismiss() {
UIView.animate(
withDuration: 0.25,
animations: {
self.scrimView.alpha = 0.0
// Animate out custom popups or action sheets
},
completion: { success in
self.myWindow = nil
}
)
}
}
To present the view:
let modalView = ModalViewController()
modalView.present()
To dismiss the view, tap anywhere on the scrim.
this code works for me, when I am presenting UIViewController with alpha != 1. present UIViewController like:
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let destinationVC = storyBoard.instantiateViewController(withIdentifier: "AddComment") as! AddCommentViewController
destinationVC.modalPresentationStyle = .overCurrentContext //this line is important
destinationVC.delegate = self
destinationVC.restId = self.restaurant.id
self.present(destinationVC, animated: true, completion: nil)
then in destinationVC view controller
override func viewWillDisappear(_: Bool) {
UIView.animate(withDuration: 1, animations: { () in
self.view.backgroundColor = .clear
})
super.viewWillDisappear(true)
}
override func viewWillAppear(_: Bool) {
UIView.animate(withDuration: 1, animations: { () in
self.view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
})
super.viewWillAppear(true)
}
and set its backgroundColor to .clear in viewDidLoad or storyboard. So UIViewController covers whole screen including status bar.
Here is the solution you might be looking for:
if let window = UIApplication.shared.keyWindow {
window.windowLevel = UIWindowLevelStatusBar + 1
}
The main idea behind this code is, window of your application has a window level which is lower than status bar window level. And what this code does is, just put your window's window level higher than status bar window level, and your window can now cover the status bar. Don't forget, this code has to be called on main thread, just before presenting your view controller. Good luck!
Custom animation transitions should be performed using UIViewControllerAnimatedTransitioning. Here is a tutorial for this purpose:
https://www.raywenderlich.com/110536/custom-uiviewcontroller-transitions
If all you want is a fade animation you can have it by changing the modalTransitionStyle property of the viewController you are going to display.
Try by fixing your code this way:
guard let shareViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ShareViewController") as! ShareViewController else {
//Fallback in case of nil?
return
}
shareViewController.modalTransitionStyle = .crossDissolve
presentViewController(shareViewController, animated: true, completion: nil)
Also please note that presentViewController(shareViewController, animated: true, completion: nil) is for swift 2. The equivalent swift 3 would be present(shareViewController, animated: true, completion: nil)
you can add this code to view controller for Swift 3:
let statusView: UIView = UIView(frame: CGRect(x: 0.0, y: -20.0, width: UIScreen.main.bounds.size.width, height: 20.0))
statusView.backgroundColor = UIColor.black
statusView.alpha = 0.8
self.addSubview(self.statusView)
You could be extremely practical and simply hide the status bar when your modal view controller is up:
override func prefersStatusBarHidden() -> Bool {
return true
}

Resources