Position Navigation Bar top of the safe area - ios

I upgraded to a new iphone and upgrade my apps. I added in the x/xr/xs layout so the black borders are gone now.
I have a navigation bar at the top of my views but now it rides up into the status bar too much? How do I fix this? Doing it programmatically and not storyboard (to learn code).
Some code:
func buildTopbar()
{
statusbar = UIView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 20));
statusbar.backgroundColor = UIColor(red: 247/255, green: 247/255, blue: 247/255, alpha: 1.0);
navigationbar = UINavigationBar(frame: CGRect(x: 0, y: 20, width: self.view.bounds.width, height: 44));
navigationbar.barTintColor = UIColor(red: 247/255, green: 247/255, blue: 247/255, alpha: 1.0);
let texta = UIBarButtonItem(title: "A", style: .plain, target: self, action: #selector(settingToolbar(sender:)));
let textb = UIBarButtonItem(title: "B", style: .plain, target: self, action: #selector(inviteToolbar(sender:)));
texta.tintColor = ColorHelper.primaryColor();
textb.tintColor = ColorHelper.primaryColor();
...
navigationbar.setItems([title], animated: false);
self.view.addSubview(statusbar);
self.view.addSubview(navigationbar);
}
I set the status bar at 20 which was what it was in the old phones.

I'd recommend to create a UINavigationController and add your controller to that Navigation Controller, it will automatically adjust the navigation bar.
In case you want to manually add the navigation bar.
You must set it's frame Y position right.
To calculate starting Y position of Nav bar
let startingYPos = UIApplication.sharedApplication.statusBarFrame.size.height;
navigationbar = UINavigationBar(frame: CGRect(x: 0, y: startingYPos, width: self.view.bounds.width, height: 44));

My suggestion is go with adding some constraints for the top.And set the constraints values based on your iPhone device size or iOS Versions. Recently i achieved it by setting like this. My issues was with iOS Version, my view is near to status bar.So i set some constraints programatically and handled it. This way it wont affect the iphone screens below iphone 7.
In Viewdidload()
if #available(iOS 11, *) {
}
else{
topConstraints.constant = 20
}
Here i checked the version's. You can also check the device and you can set the constraints. If you want for the device check, let me know.
Hope it will work !!

Height of status bar has changed now from 20pt to 44pt (from iPhone X onwards). If you want to use your existing code, you need to apply device specific check for status bar height.
Here is a post which explains nav bar layout(for iPhone X and later devices) in more detail:
What is the top bar height of iPhone X?

I would suggest you to take UIScreen height & put it in a condition:
if UIScreen.main.bounds.size.height > 750 {
navigationBar = UINavigationBar(frame: CGRect(x: 0, y: 43, width: view.frame.size.width, height: 44))
}
else{
navigationBar = UINavigationBar(frame: CGRect(x: 0, y: 20, width: view.frame.size.width, height: 44))
}
it may not work if your view's having a scrolling view & it's height is set to more than default value, then try :-
view.bounds.size.height

You can have it aligned to the safe area even without UINavigationController or some "magic" fixed height constants.
You should have #IBOutlet of your navigation bar (or reference if navigation bar is made programmatically). Also, keep the bar's top constraint to Safe area.
Make your ViewController conform to UINavigationBarDelegate and set delegate of navigation bar (navigationBar.delegate = self)
Implement this function and return .topAttached:
func position(for bar: UIBarPositioning) -> UIBarPosition { return .topAttached }

Related

Custom View in Navigationbar titleView disappear iOS Swift

I'm having a problem with the titleView in navigation bar in iOS. I've created a custom view for the titleView, but every time I push another controller, the titleView immediately appear and disappear when I go back to the first view controller. Here's my code.
override func viewDidLoad() {
super.viewDidLoad()
let logo = UIImage(named: "img_appbar_logo")?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
logoContainer = UIView(frame: CGRect(x: 0, y: 0, width: 180, height: 40))
logoContainer.backgroundColor = UIColor.clear
animatedLogo = UIImageView(frame: CGRect(x: 0, y: 0, width: logoContainer.frame.width, height: logoContainer.frame.height))
animatedLogo.contentMode = .scaleAspectFit
animatedLogo.clipsToBounds = true
animatedLogo.image = logo
logoContainer.addSubview(animatedLogo)
navigationItem.titleView = logoContainer
}
I've already fixed the issue related to titleView in Navigation bar. I found out that after I push another controller and pop back, the titleView will be replaced by the view of empty UILabel in the NavigationItem. That's why the titleView appear then disappear.
How I fixed the issue?
I added the custom view directly to the navigation bar. Here's the code
let logo = UIImage(named: "img_appbar_logo")?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
logoContainer = UIView(frame: CGRect(x: 0, y: 0, width: 180, height: 40))
logoContainer.backgroundColor = UIColor.red
animatedLogo = UIImageView(frame: CGRect(x: 0, y: logoContainer.frame.origin.y, width: logoContainer.frame.width, height: logoContainer.frame.height))
animatedLogo.contentMode = .scaleAspectFit
animatedLogo.clipsToBounds = true
animatedLogo.image = logo
logoContainer.addSubview(animatedLogo)
navigationController?.navigationBar.addSubview(logoContainer) <--- new
//navigationItem.titleView = logoContainer <---- old
Then remove the view on viewWillDisappear
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
logoContainer.removeFromSuperview()
}
Set the titleView in viewWillAppear since the titleView gets replaced by the title in the previous controller

Height of Navigation Bar in swift 4

In swift 3, I was able to change the height of a custom navigation bar using constraints and simply setting the height. Now I cannot do that anymore. It doesn't actually change the height of the navigation bar in the storyboard. Even when I go to the size inspector, the height field is gray and I am not able to change it. What is the best practice if I am presenting a view modally and want to display a navigation bar? It doesn't display automatically since it is a modally segue.
I had a similar issue, so i started to research and i found a solution that works for me... I'm gonna show how i did it, but i have to say that i don't use storyboards, so it is all in code...
1) You have to create a class of type "UIView", and then put this code in it:
class ExtendedNavBarView: UIView {
override func willMove(toWindow newWindow: UIWindow?) {
super.willMove(toWindow: newWindow)
layer.shadowOffset = CGSize(width: 0, height: CGFloat(1) / UIScreen.main.scale)
layer.shadowRadius = 0
layer.shadowColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1).cgColor
layer.shadowOpacity = 0.25
}
2) Then, go to the class where you have your navigationController. In the viewDidLoad method, put this code:
navBar.shadowImage = #imageLiteral(resourceName: "TransparentPixel")
let extendedBar = ExtendedNavBarView()
extendedBar.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 82) //The height value is gonna determinate the total height of the navbar
view.addSubview(extendedBar)
extendedBar.backgroundColor = UIColor(red: 249/255, green: 249/255, blue: 249/255, alpha: 1.0)
Basically is an extension view for the navigationBar, depending of the value you put in the height, the total navbar is gonna be more or less taller.
If you want to learn more about it, you can go here:
Custom NavigationBar
Also, the "TransparentPixel" image is in the page, you just have to download the sample project.

How to set a button to most right side of navigation - iOS

I set a button to right side of navigation bar:
my view controller:
I want to set a burger icon,red cycle and a label to this button. like this:
my code:
self.navigationController?.navigationBar.barTintColor = self.utilities.hexStringToUIColor(hex: "#00b8de")
var imageview2 = UIImage(named: "menulogo")
imageview2 = imageview2?.imageResize(sizeChange: CGSize(width: 25, height: 25))
btnMenu.setImage(imageview2,for:UIControlState.normal)
btnMenu.setTitle("", for: .normal)
// setup the red circle UIView
let redCircleView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
redCircleView.backgroundColor = UIColor.red
redCircleView.layer.cornerRadius = view.frame.size.width / 2
// setup the number UILabel
let label = UILabel(frame: CGRect(x: 30, y: 0, width: 20, height: 20))
label.textColor = UIColor.white
label.font = UIFont.systemFont(ofSize: 10)
label.text = "16"
// adding the label into the red circle
redCircleView.addSubview(label)
// adding the red circle into the menu button
btnMenu.addSubview(redCircleView)
with above codes I have three problems:
my burger image isn't in most right side of navigation.
my cycle view doesn't show
my icon is white, but it shows blue!
btnMenu is my button in navigation.
I have use this library for set badge on navigation button.
MIBadgeButton is badge button written in Swift with high
UITableView/UICollectionView performance.
https://github.com/mustafaibrahim989/MIBadgeButton-Swift

adding custom navigation bar in viewwillappear makes navigation slow?

I have created a custom navigation bar.Now i am adding this into viewwillappear method.Due to this when i return to my view controller it takes time to load.
func addViewToNav()
{
myView = UIView(frame: CGRect(x: 0, y: 20, width: (self.navigationController?.navigationBar.frame.size.width)!-40, height: (self.navigationController?.navigationBar.frame.size.height)!))
imageView.frame = CGRect(x: 5, y: (myView?.frame.size.height)!/2-14, width: 28, height: 28)
let image = UIImage(named: "download")
imageView.contentMode=UIViewContentMode.scaleAspectFill
imageView.image=image
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.cornerRadius = imageView.frame.size.width/2
imageView.clipsToBounds = true
imageView.backgroundColor=UIColor.yellow
label = UILabel(frame: CGRect(x: imageView.frame.size.width+15, y: 0, width: 150, height: (myView?.frame.size.height)!))
label?.text="Label"
label?.textColor=UIColor.white
myView?.addSubview(imageView)
myView?.addSubview(label!)
self.navigationController?.view.addSubview(myView!)
//add tap gesturte on imageview & label
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapBlurButton(_:)))
myView?.isUserInteractionEnabled=true
tapGesture.numberOfTapsRequired=1
myView?.addGestureRecognizer(tapGesture)
}
Please guide how can i make it fast because this is very slow.
It is taking time because every time the controller appears on the screen viewWillAppear will be called and each time the code for creating the custom view, adding it as the subview and then adding gesture recognizer will be executed.
There are 2 ways that might reduce the processing time:
If you want to do it programatically, the add the code to create and add custom navigation bar in viewDidLoad instead of viewWillAppear
Add the custom navigation bar in the storyboard itself and create an outlet connection for it in the controller.

Create UI chat like whatsapp and how to create event touch in navigation bar (iOS xamarin)

I would like to ask about iOS xamarin. I'm creating an application similar to whatsapp, but I ran into the following problems:
Creating an UI like whatsapp in navigation bar (title bar), I dragged ImageView/Label on there, but the ImageView/Label was covered by navigation bar. Just like in the picture below:
When the navigation bar is clicked, I want to direct the user to another controller, but I don't know how to create the event touch/click in navigation bar. Could you give me some pointers on that?
That's do not touch on Navigation bar, its touch on Button placed on the navigation bar. long press on Title /name in WhatsApp, and you will see highlighted area-- (touch portion) - which is a button.
let buttonContainer = UIView(frame: CoreGraphics.CGRect(x: 0, y: 0, width: 200, height: 44));
buttonContainer.backgroundColor = .clear
let lbltitle = UILabel(frame: CoreGraphics.CGRect(x: 0, y: 0, width: 200, height: 44))
lbltitle.text = "TITLE TO DISPLAY"
buttonContainer.addSubview(lbltitle)
let btnTitle = UIButton(type: .custom)
btnTitle.frame = CoreGraphics.CGRect(x: 0, y: 0, width: 200, height: 44);
btnTitle.backgroundColor = .clear;
buttonContainer.addSubview(btnTitle)
btnTitle.removeTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
navigationItem.titleView = buttonContainer
And here is code to push the view controller on the button tap.
#objc func buttonTapped()
{
navigationController?.pushViewController(ChatVC, animated: false)
}

Resources