How to show view in statusbar in iOS? - ios

I want to show view in statusbar which should be visible to my all View Controller
Example: I need to show "No Internet Connection" in status bar and it will hide after we get connectivity of internet?

You can add a view directly to the status bar:
// get the status bar
let statusBar = UIApplication.shared.value(forKey: "statusBarWindow") as? UIWindow
// create a subview & add it to the status bar
let subview = UIView(frame: CGRect(x: 20, y: 0, width: 20, height: 10))
subview.backgroundColor = .red
statusBar?.addSubview(subview)
statusBar?.bringSubview(toFront: subview)
If you declare the statusBar and the noNetworkConnectionView globally, you can access it from anywhere to show or hide it dynamically.
Result:
Disclaimer: I am not sure whether Apple will approve apps that modify the status bar in this way.

Create a view
let statusView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 40))
statusView.tag = 1101 //used to get view whenever required
statusView.backgroundColor = UIColor.red.withAlphaComponent(0.6)
//set other properties
Show view on window
//show on window, will be visible in all view controller
UIApplication.shared.delegate?.window??.addSubview(statusView)
UIApplication.shared.delegate?.window??.bringSubview(toFront: statusView)
Hide View
//to hide that view
UIApplication.shared.delegate?.window??.viewWithTag(1101)?.removeFromSuperview()

Related

iOS SearchController Searchbar does not work after adding constraint programmatically

I have an iOS project whereby the SearchController's SearchBar is added to the view as a subview:
let subView = UIView(frame: CGRect(x: 0, y: 65.0, width: 350.0, height: 45.0))
subView.addSubview((self.searchController.searchBar))
self.view.addSubview(subView)
As shown in the screenshot below, the searchbar is partially obscured by the navigation bar:
As such, I added the following constraint:
subView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([subView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor)])
The searchbar is now positioned correctly below the navigation bar as shown:
However, I'm now not able to click onto the searchbar to input any text. How can I resolve this?
How I resolved this at the end.
I still made use of a subView for the searchbar. But this time, instead of giving a fixed value for y, I used the heights of the safeArea and the navigation bar as shown:
let window = UIApplication.shared.windows.first
let safeheight = window?.safeAreaInsets.top
let navHeight = self.navigationController?.navigationBar.frame.height
let subView = UIView(frame: CGRect(x: 0, y: safeheight! + navHeight!, width: 350.0, height: 45.0))
subView.addSubview((self.searchController.searchBar))
self.view.addSubview(subView)
This time, the searchbar was positioned correctly and worked perfectly.

UIView with round corners has black background

I am trying to create a UIView with round corners the round corners are rendering perfectly but there is an odd black background behind the view. How do I get rid of the black background?
CODE
import UIKit
import PlaygroundSupport
// The background rectange for main view
let backgroundRectangle = CGRect(x: 0, y: 0, width: 500, height: 500)
// Main view
let mainView = UIView(frame: backgroundRectangle)
// Color of the main view
mainView.backgroundColor = .darkGray
// Corner radius
mainView.layer.cornerRadius = 50
mainView.layer.masksToBounds = false
// Present the view to Playground's live view
PlaygroundPage.current.liveView = mainView
RENDERED UI
EDIT
import UIKit
import PlaygroundSupport
// Holder rectangle
let holderRectangle = CGRect(x: 0, y: 0, width: 500, height: 500)
// Holder view
let holderView = UIView(frame: holderRectangle)
// The background color of the holder view is clear
holderView.backgroundColor = .clear
// Main rectangle
let mainRectangle = CGRect(x: 0, y: 0, width: 500, height: 500)
// Main view
let mainView = UIView(frame: mainRectangle)
// The background color of the main view is black
mainView.backgroundColor = .white
// Create a corner radius for the main view
mainView.layer.cornerRadius = 30
mainView.layer.masksToBounds = false
// Make the main view a subview of the holder view
holderView.addSubview(mainView)
// Present the holder view in the live view
PlaygroundPage.current.liveView = holderView
This is happening because, there is no other view present behind your mainView. Please add a view behind mainView or embed your mainView into UIView assign a background color of your choice to the newly created view. Thats it your issue resolved.

Navigation bar overlapping image after back segue

Navigation bar overlaps the image after user back from segue.
When the view first loaded it looks ok but after performing the segue and come back it looks like this.
here is the code for that image
let logoContainer = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 67))
let imageView = UIImageView(frame: CGRect(x: 0, y: -30, width: 200, height: 67))
imageView.contentMode = .scaleAspectFit
let image = UIImage(named: "navbarlogo")
imageView.image = image
logoContainer.addSubview(imageView)
navigationItem.titleView = logoContainer
Honestly, your problem is the fact you are creating an overlap of the ImageView by specifying a -30 y coordinate. It's higher in the z-order (compared to your navigation bar) in one case but lower in the z-order in the segue scenario.
I suspect if you use "Debug View Hierarchy" in XCode in both scenarios, you would be able to see this is what is happening.
I would change your approach as to how the logo container is being laid out

View is behind the extended navigation bar

In the viewDidLoad of the root view controller of the UINavigationController I add the subview to navigationBar and update its frame. Note that the new frame has a longer height than that of the original frame.
The problem is that the top of the subview in view of root view controller is hidden behind the "extended" nav bar even though, in the storyboard, the constraint of the subview is set to vertical spacing to top layout guide. If I remove my subview from from nav bar, the problem disappears.
So, question:
Is it considered normal to add subview to the default nav bar provided by navigation controller?
When is the best time to add subview and update the frame of nav bar?
How can I resolve the issue where part of the view is hidden behind the nav bar with my sub view in it?
Code snippet:
override func viewDidLoad() {
super.viewDidLoad()
title = "Tile"
if let frame = navigationController?.navigationBar.frame {
let label = UILabel(frame: CGRect(x: 0, y: frame.height - 25, width: 25, height: 25))
label.text = "1234"
navigationController?.navigationBar.frame = CGRect(origin: frame.origin, size: CGSize(width: frame.width, height: frame.height + 25))
navigationController?.navigationBar.addSubview(label)
}
}

Frame on ViewController

I have this class:
extension UIViewController {
func waiting() -> UIView{
let strLabel = UILabel(frame: CGRect(x: 50, y: 0, width: 200, height: 50))
strLabel.text = "Aguarde..."
strLabel.textColor = UIColor.whiteColor()
let messageFrame = UIView(frame: CGRect(x: view.frame.midX - 90, y: view.frame.midY - 25 , width: 180, height: 50))
messageFrame.layer.cornerRadius = 15
messageFrame.backgroundColor = UIColor(white: 0, alpha: 0.40)
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
activityIndicator.startAnimating()
messageFrame.addSubview(activityIndicator)
messageFrame.addSubview(strLabel)
view.addSubview(messageFrame)
return messageFrame
}
}
When I need use this class I use:
class MyController: UIViewController{
....
func x(){
let messageFrame = waiting()
//my code
messageFrame.removeFromSuperview()
}
}
The problem is when the frame is showed if I touch anywhere on my app this frame is hidden. I need that when this frame is showed other options staying disabled, when I finish the frame, the options of app is enabled again. How can I do it?
Change the view that you are returning a bit:
Make a "container" view that has the same frame as the view controller's view. Give this view a "clear" background.
Make a "background" view, same size as the "container" view and add it to the container. Give this view a black background and an alpha of, say, 0.4.
Now put the view that you are currently building in your "waiting" method, and add it to the "container" view (NOT to the background view, this should be a sibling of the background view, otherwise your alert will also be transparent).
Make sure all user interaction is disabled on your views (might only need it disabled on the "container" view).
This gives you a container view that covers the entire screen, and it has 2 children: a transparent background of the same size, and your current "waiting" alert thing.
Now if you add the "container" view to your view controller's view, the user can only touch on the container view which does nothing.
(Keep in mind that this doesn't handle screen rotation...you will have to do that yourself if needed.)

Resources