Hide status bar whenever nav bar is hidden - SWIFT iOS8 - swift

How can I had the status bar whenever the view is scrolling with:
self.navigationController?.hidesBarsOnSwipe = true
or if not hide the status bar, how can I keep my status bar from overlaying my view?
ty awesome stackoverflow community

A Swift 3 elegant solution:
open override var prefersStatusBarHidden: Bool {
return navigationController?.isNavigationBarHidden ?? false
}

Sorry if this answer is a little late, but here is one way to do it.
Use the prefersStatusBarHidden() method within your view controller.
override func prefersStatusBarHidden() -> Bool {
if self.navigationController?.navigationBarHidden == true {
return true
} else {
return false
}
}
Basically says that when the Nav bar is hidden, then the status bar is too and vice versa.

Related

iOS non blocking status bar

I'm trying to place an image behind the status bar.
I'm able to turn it transparent but It's still blocking the image from appearing behind it.
Does anybody know how to make the status bar apart of the editable screen and/or safe area? I don't want to delete it, just want to put stuff behind it.
Here's what IB looks like
Code
override func viewWillAppear(_ animated: Bool) {
setNeedsStatusBarAppearanceUpdate()
}
override func viewDidLoad() {
super.viewDidLoad()
venueInfoTableView.dataSource = self
venueInfoTableView.delegate = self
// Do any additional setup after loading the view, typically from a nib.
venueInfoTableView.separatorStyle = .none
}
override var preferredStatusBarStyle : UIStatusBarStyle {
return UIStatusBarStyle.lightContent
//return UIStatusBarStyle.default // Make dark again
}
And here's the result
You should disable automaticallyAdjustsScrollViewInsets
if #available(iOS 11.0, *) {
self.venueInfoTableView.contentInsetAdjustmentBehavior = .never
} else {
self.automaticallyAdjustsScrollViewInsets = false
}
contentInsetAdjustmentBehavior This property specifies how the safe
area insets are used to modify the content area of the scroll view.
The default value of this property is automatic.

Swift 3 | Unable to hide status bar on a ViewController

I want to show the status bar on portrait mode only, when I rotate the screen the status bar hides as intended but if I push / show a new View Controller the status bar appears again.
I've tried the following without success:
Setting View controller-based status bar appearance to NO in the info.plist file
Using setNeedsStatusBarAppearanceUpdate() on self and on NavigationController
Setting prefersStatusBarHidden: Bool to true
Also tried UIApplication.shared.setStatusBarHidden(true, with: UIStatusBarAnimation.none)
Also extending NavigationController. seen here
Any help will be appreciated. Thanks.
Try Following Code
override var prefersStatusBarHidden: Bool {
if UIDevice.current.orientation.isPortrait{
return false
}
return true
}

Swift - Adding a navigation bar that overrides the existing one

I have multiple VC's embedded in one NavigationController.
I have one VC, lets name it VCNotTransparent, that I want the bar to be not transparent, and on other VC's I want it to be transparent.
So in the main VC, I added these lines for making the bar transparent:
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.isTranslucent = true
So now all of my bars are transparent in the app.
How can I make VCNotTransparent not transparent without it changing all of the other VC's? one solution I thought of is to add a new navigation bar only in VCNotTransparent, but I do not know how to do that.
EDIT
I also tried embedding VCNotTransparent in its own NavigationController, which works almost, but the issue is that I have navigation from it to some other VC's and they become not transparent as well, since they are sub navigation of the VCNotTransparent.
Handle this by enum -
Do below within your MainVC -
public enum NavigationType: Int {
case transparent = 1
case notTransparent = 2
}
var currentNavigationType: NavigationType?
override func viewDidLoad() {
super.viewDidLoad()
self.currentNavigationType = .transparent // default
self.setupNavigationControllerStyle()
}
func setupNavigationControllerStyle (){
switch self.currentNavigationType! {
case .transparent:
//do code here for transparent
case .notTransparent:
//do code here for not transparent
default:
break
}
}
default it will show transparent bar. in which controller you don't want transparent bar just update the currentNavigationType property from there like below -
class VCNotTransparent: MainVC {
override func viewWillAppear(_ animated: Bool) {
self.currentNavigationType = .notTransparent
super.viewWillAppear(animated)
}
}

Menu from tab bar in storyboarding

At the moment I have a standard tab bar, when tapped goes to its corresponding viewController. But I want to make a menu pop out from tab bar when more tab is selected, as shown in below image.
Is any suggestion to implement this?
Thanks in advance.
I would recommend you do so:
First, you should think of all the tab types that could be in tab bar. On your screenshot there are tabs, that present controller, and tab, that presents menu. So we could create enum with all these types:
enum TabType {
case controller
case menu
}
After that you can store array of tab types in order they are shown in tab bar, for your screenshot like so
let tabTypes: [TabType] = [.controller, .controller, .controller, .controller, .menu]
Then you should implement UITabBarControllerDelegate's func tabBarController(_:, shouldSelect:) -> Bool method, which returns true if tab bar is allowed to select the passed controller, and false otherwise.
If you return true than all other work (like presenting view controller and other stuff) tab bar controller will do for you.
In your case you want to execute custom action on tab click, so you should return false. Before returning you should present your menu.
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if let index = tabBarController.viewControllers?.index(of: viewController),
index < tabBarTypes.count {
let type = tabBarTypes[index]
switch type {
case .menu:
// perform your menu presenting here
return false
case .controller:
// do nothing, just return true, tab bar will do all work for you
return true
}
}
return true
}
In this implementation you can easily change tab types order or add some another tab type and handle it appropriate.
Its not good UI but although if you want.
First You have to implement delegate method of UITabbarControllerDelegate as below
func tabBarController(_ tabBarController: UITabBarController, shouldSelect
viewController: UIViewController) -> Bool {
if viewController.classForCoder == moreViewController.self
{
let popvc = MoreSubMenuViews(nibName: "MoreSubMenuViews", bundle: Bundle.main)
self.addChildViewController(popvc)
let tabbarHeight = tabBar.frame.height
let estimatedWidth:CGFloat = 200.0
let estimatedHeight:CGFloat = 300.0
popvc.view.frame = CGRect(x:self.view.frame.width - estimatedWidth, y: self.view.frame.height - estimatedHeight - tabbarHeight, width: estimatedWidth, height: estimatedHeight)
self.view.addSubview(popvc.view)
popvc.didMove(toParentViewController: self)
print("sorry stop here")
return true // if you want not to select return false here
}else{
//remove popup logic here if opened
return true
}
}
Here moreViewController is last tab controller & MoreSubMenuViews is nib/xib file which contains buttons shown in you image.
Instead of showing a menu, you could use a scrollable tabs view for a better UI. If you prefer using a library, here's a simple scrollable tab-bar you could implement.
This is an abuse of the UI patterns layout in Apples HIG. Specifically:
Use a tab bar strictly for navigation. Tab bar buttons should not be used to perform actions. If you need to provide controls that act on elements in the current view, use a toolbar instead.
This control should be used to flatten your app hierarchy. It seems that in this case you are mixing functionality of the button. Sometimes it selects a separate view controller, sometimes it displays a action list. This is a confusing situation for users and should be avoided.
A way you could achieve this and still adhere to HIG is by using navigation or tool bars. Imbed this control in a toolbar button. The most simple case would be to invoke a UIActionController with the .actionSheet style selected.
As per my understanding what you want is that, tab 1 is selected and user goes to tab 5 then background will be tab 1 & vice-versa for tab 2,3 & 4 and there should be pop up like buttons as shown in your image. please correct me if I'm wrong.
For this you have to capture the image while user navigate through tabs.
Please find below code in AppDelegate,
var currentImage: UIImage! //It will be public variable
Tabbar delegate methods,
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
if tabBarController.selectedIndex == 4 {
let moreVC = tabBarController.selectedViewController as! MoreVC
moreVC.currentImage = currentImage
}
}
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if tabBarController.selectedIndex != 4 {
let navController = tabBarController.selectedViewController as! UINavigationController
let viewController = navController.viewControllers.last
currentImage = Common.imageWithView(inView: (viewController?.navigationController?.view)!) //UIImage(view: (viewController?.navigationController?.view)!)
}
return true
}
Here I've taken static 4 as last tab index & MoreVC will be the associated ViewController of tab index 4.
Common class to get image from view,
class Common {
static func imageWithView(inView: UIView) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(inView.bounds.size, inView.isOpaque, 0.0)
defer { UIGraphicsEndImageContext() }
if let context = UIGraphicsGetCurrentContext() {
inView.layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
return image
}
return nil
}
}
Please find MoreVC,
#IBOutlet weak var imageView: UIImageView!
var currentImage: UIImage! {
didSet {
imageView.image = currentImage
}
}
Please find below image for MoreVC Storyboard. Look it does not contain NavigationController like all other ViewControllers.
Let me know in case of any queries.
1)
Create a "Tab5ViewController" and use this:
static func takeScreenshot(bottomPadding padding: CGFloat = 0) -> UIImage? {
let layer = UIApplication.shared.keyWindow!.layer
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(CGSize(width: layer.frame.size.width, height: layer.frame.size.height - padding), false, scale)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
layer.render(in: context)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return screenshot
}
Use the screenshot as a background image for your "Tab5ViewController"
2) In your "Tab5ViewController" you can have the stack component (the additional tabs) and then just add/remove child view controllers based on the selection
3)
fix edge cases (like tab selection highlight and so on...)

Check whether status bar is hidden or visible

I want to check condition for statusbar. How can i check condition if status bar is visible or not .
please anyone guide me to do this..
Thank you all
Check if status bar is hidden:
Objective C:
if ([UIApplication sharedApplication].isStatusBarHidden) {
// do stuff here...
}
Swift:
if UIApplication.shared.isStatusBarHidden {
// do stuff here...
}
Hide status bar:
override var prefersStatusBarHidden: Bool {
return true
}
Swift 3
if UIApplication.shared.isStatusBarHidden {
// Do something
}
To hide the status bar (setStatusBarHidden is deprecated in iOS 9)
override in your ViewController:
override var prefersStatusBarHidden: Bool {
return true
}
You can check the current state by using the statusBarHidden property of [UIApplication sharedApplication]
You can set the current state using – setStatusBarHidden:withAnimation:
See the docs for more awesome stuff.
HTH
U can Also check this in xib of interface builder in view attributes u can see four options for it gray/ black/ translucent/ unspecified..