I want to hide the status bar after calling UIImagePickerController on iOS 10.2.
There are several questions with answers that don't work for Swift 3.0.
The suggested answers are:
extend UINavigationController to override preferStatusBarHidden, because UIImagePickerController is a subclass of UINavigationController.
So I tried:
extension UINavigationController{
open override var prefersStatusBarHidden: Bool{
return true
}
}
extend UIImagePickerController to override prefersStatusBarHidden.
So I tried:
extension UIImagePickerController{
open override var prefersStatusBarHidden: Bool{
return true
}
}
create and use a subclass of UIImagePicker
So I tried:
class MyImagePickerController: UIImagePickerController{
override var prefersStatusBarHidden: Bool{
return true
}
}
None of the above solutions work for me.
The status bar can be permanently hidden with the following extension to UIImagePickerController :
extension UIImagePickerController {
open override var childViewControllerForStatusBarHidden: UIViewController? {
return nil
}
open override var prefersStatusBarHidden: Bool {
return true
}
}
This is working for Swift 3, on iOS 10.
You are adding the delegate method method of UINavigationControllerDelegate like below.
class PersonalInfoVC: UIViewController, UIImagePickerControllerDelegate , UINavigationControllerDelegate{
Adding the delegate and hide the status bar in it.
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool){
UIApplication.shared.isStatusBarHidden = true
}
None of those answers worked for me on iOS 13. I had to set this flag on the presenting view controller before presenting the image picker:
viewController.modalPresentationCapturesStatusBarAppearance = YES;
[viewController presentViewController:picker animated:YES completion:nil];
The status bar can be hidden and show when presenting view controller UIImagePickerController swift 4+
picker.dismiss(animated: true, completion: {
if let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView {
statusBar.isHidden = true
}
})
picker.dismiss(animated: true, completion: {
if let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView {
statusBar.isHidden = false
}
})
Related
I have a requirement of light content in status bar with black background, however some of the screen needs black status bar content with white background, hence I've kept View controller-based status bar appearance to YES in info.plist to adopt status bar style based on view controllers requirement.
My problem is whenever I present SFSafariViewController from any view controller it is taking black status bar content and white background by default i.e status bar style is .default everytime.
I tried overriding preferredStatusBarStyle in SFSafariViewController subclass and no look so far.
Below is my code
import UIKit
import SafariServices
extension SFSafariViewController {
override open var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .lightContent
}
}
class MyViewController: UIViewController, SFSafariViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.barTintColor = UIColor.lightGray
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
#IBAction func presentSafari(sender: AnyObject) {
let safari = SFSafariViewController(url: URL(string: "https://www.google.com/")!)
safari.delegate = self
present(safari, animated: true) {
}
}
// MARK: - SFSafariViewControllerDelegate
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
dismiss(animated: true, completion: nil)
}
}
Set modalPresentationCapturesStatusBarAppearance to takes over control of status bar appearance from the presenting view controller.
#IBAction func presentSafari(sender: AnyObject) {
let safari = SFSafariViewController(url: URL(string: "https://www.google.com/")!)
safari.delegate = self
safari.modalPresentationCapturesStatusBarAppearance = true
if #available(iOS 10.0, *) {
safari.preferredBarTintColor = .yellow
} else {
// Fallback on earlier versions
safari.view.tintColor = .yellow
}
present(safari, animated: true) {
}
}
extension SFSafariViewController {
override open var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
When you present a view controller by calling the present(_:animated:completion:) method, status bar appearance control is transferred from the presenting to the presented view controller only if the presented controller's modalPresentationStyle value is UIModalPresentationStyle.fullScreen. By setting this property to true, you specify the presented view controller controls status bar appearance, even though presented non-fullscreen.
Output: Screenshot
iOS 10.0+
preferredBarTintColor
The color to tint the background of the navigation bar and the toolbar.
Ref: https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller/2274394-preferredbartintcolor
Since your View controller-based status bar appearance is set to YES in Info.plist, you will need to apply the color information on preferredBarTintColor, like so:
let safari = SFSafariViewController(url: URL(string: "https://google.com")!)
//This:
safari.preferredBarTintColor = .black
present(safari, animated: true, completion: nil)
And... no need for the following:
extension SFSafariViewController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return .default
}
}
the status bar style for my application is white except when image picker controller is presented and I have already extend my UINavigationController but it doesn't seem to be working on any view present only on pushed views does anyone have solution??
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .lightContent
}
}
I have also try this method , but the navigationController is a let and the
preferredStatusBarStyle is read-only
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
viewController.navigationItem.title = "willShow"
navigationController.preferredStatusBarStyle = UIStatusBarStyle.lightContent
}
When you present something modally and you want it to determine the status bar style you need to set modalPresentationCapturesStatusBarAppearance = true
For example:
let navigationController = UINavigationController(rootViewController: MyViewController())
navigationController.modalPresentationCapturesStatusBarAppearance = true
present(navigationController, animated: true)
You'll also need to check if the current UINavigationController is a UIImagePickerController and return .lightContent from preferredStatusBarStyle as UIImagePickerController has a prefers the .default out of the box.
open override var preferredStatusBarStyle: UIStatusBarStyle {
if self is UIImagePickerController {
return .lightContent
}
return topViewController?.preferredStatusBarStyle ?? .lightContent
}
I created a new project. I have a NavigationController. In the RootViewController I have a containerView with a table and just one cell. If I click on the cell I push a new UIViewController. So my Main.storyboard looks like this:
What I want:
I want first to have a white NavigationBartitle. Then pushing to secondVC I want to change the NavigationBarTitle to black. Then clicking on back the color should change back to a white title.
What I've did:
I did a custom NavigationViewController. There I was changing the func willShow viewController. In this I wrote the titleColor should change depending on which screen the navigationController changes to.
My code:
import UIKit
class SettingsNavigationViewController: UINavigationController {}
// MARK: - Controller Lifecycle
extension SettingsNavigationViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
override var preferredStatusBarStyle: UIStatusBarStyle {
guard let child = self.childViewControllers.last else {
return .lightContent
}
return child is ViewController ? .lightContent : .default
}
}
// MARK: - NavigationController Delegate Implementation
extension SettingsNavigationViewController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
let isSettingsContainer = viewController is ViewController
let backgroundColor = isSettingsContainer ? UIColor.cyan : UIColor.white
let titleColor = isSettingsContainer ? UIColor.white : UIColor.black
let image = isSettingsContainer ? UIImage() : nil
navigationController.navigationBar.shadowImage = image
navigationController.navigationBar.setBackgroundImage(image, for: .default)
navigationController.transitionCoordinator?.animate(alongsideTransition: { (context) in
navigationController.navigationBar.tintColor = titleColor
navigationController.navigationBar.barTintColor = backgroundColor
navigationController.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor : titleColor]
})
}
}
What happened instead:
If I change the screen to seconndVC the navBarTitleColor changes black. If I click on back it stays black. But it should change to white.
The complete project I also uploaded to github: https://github.com/Sonius94/stackNaviTitle
The possible solution could be, add a SecondViewController and in your SecondViewController you should implement the following :
override func willMove(toParentViewController parent: UIViewController?) {
super.willMove(toParentViewController: parent)
if parent == nil {
// Add your navigation bar appearance for FirstViewController
}
}
I want make all ViewController stay portrait except video player controller. So I made a custom navigator extended by UINavigationController.
class MyNavigationController: UINavigationController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask{
return .portrait
}
}
All is OK but status bar still rotate to landscape like this:
Anyone can help me about this? Thanks a lot and swift code will better for me.
I solved it by delete UIMainStoryboardFile in info.plist. By the way,I don't use storyboard so I add navigation controller by
self.window = UIWindow.init(frame: UIScreen.main.bounds)
self.window?.makeKeyAndVisible()
let a = ViewController()
let nav = PumpNavigationController.init(rootViewController: a)
self.window?.rootViewController = nav
I am creating an app for iPad Pro. It will only be used in Landscape mode. This get photos for imageView the app, I use the UIImagePickerController.
Abou the UIImagePickerController:
I've been studying the Docs of UIImagePickerController and one fact important is:
From Docs:
The UIImagePickerController class supports portrait mode only. This class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified, with one exception. You can assign a custom view to the cameraOverlayView property and use that view to present additional information or manage the interactions between the camera interface and your code.
The solution I've found to show UIImagePickerController in landscape mode is displayed as Popover.
What I have:
THIS IS A PROJECT EXAMPLE
My Storyboard:
http://i.stack.imgur.com/rUckK.png
1 NavigationBar with 1 Bar Button
1 Image View
My Swift Code:
import UIKit
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
#IBOutlet var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return .Landscape
}
#IBOutlet var itemBarButton: UIBarButtonItem!
#IBAction func getImageButton(sender: UIBarButtonItem) {
let image = UIImagePickerController()
image.delegate = self
image.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
image.view.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
image.modalPresentationStyle = .Popover
image.popoverPresentationController?.barButtonItem = sender
self.presentViewController(image, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let theInfo: NSDictionary = info as NSDictionary
let img: UIImage = theInfo.objectForKey(UIImagePickerControllerOriginalImage) as! UIImage
imageView.image = img
self.dismissViewControllerAnimated(true, completion: nil)
}
}
My question is:
Knowing that I can not show UIImagePickerController in landscape, I can change the size of UIImagePickerController displayed in Popover?
If the answer is yes, how can I do this?
I tried to use the image.view.frame but do not get change.