Customize UINavigationBar with inset image - ios

I have this navigation bar I am trying to implement that looks like this:
I know I can either put the image directly in the nav bar or as a header image below it, but I have no idea how to inset it so that it is contained in both the main container view and breaching the navigation bar as well.
Any ideas would be helpful!

I guess it's achievable using two images:
background: will match the navigation bar frame
icon: let's say an image 50x50 centered to the background in x-axis and y-axis with offset of its height / 2.0
Then you may try to use autolayout constraints doing so:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
guard let navbar = self.navigationController?.navigationBar else {return} // be sure to have defined a navigation controller
navbar.clipsToBounds = false // so the icon will be visible outside the nav bar
let niceBkg = UIImageView(image: UIImage(named: "bkg"))
navbar.addSubview(niceBkg)
niceBkg.translatesAutoresizingMaskIntoConstraints = false
niceBkg.leftAnchor.constraint(equalTo: navbar.leftAnchor).isActive = true
niceBkg.rightAnchor.constraint(equalTo: navbar.rightAnchor).isActive = true
niceBkg.topAnchor.constraint(equalTo: self.navigationController!.view.topAnchor).isActive = true
niceBkg.bottomAnchor.constraint(equalTo: navbar.bottomAnchor).isActive = true
let niceIcon = UIImageView(image: UIImage(named: "icon"))
niceBkg.addSubview(niceIcon)
niceIcon.translatesAutoresizingMaskIntoConstraints = false
niceIcon.widthAnchor.constraint(equalToConstant: 50).isActive = true
niceIcon.heightAnchor.constraint(equalToConstant: 50).isActive = true
niceIcon.centerXAnchor.constraint(lessThanOrEqualTo: niceBkg.centerXAnchor).isActive = true
niceIcon.bottomAnchor.constraint(greaterThanOrEqualTo: niceBkg.bottomAnchor, constant: 25).isActive = true
}
}
on iPhoneX the result is:
About your scenario, you probably need only the icon and a navigationBar with a proper background color. However I added both autolayout configurations because might be useful for someone else, especially if the navigationBar's background is quite complex with border, decorations and so on.

Related

My navigation bar is not moving up when scrolling UITableView with background image

I have this view hierarchy on a view embedded in a UINavigationController:
When I scroll the UITableView the navigation bar is not moving up (the title is not becoming smaller) it stays like this:
If I remove the image view as background view everything works well.
My navigation is configured like this:
navigationItem.title = "Title here"
navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.tintColor = .white
navigationController?.navigationBar.barStyle = UIBarStyle.blackTranslucent
navigationController?.navigationBar.backgroundColor = .clear
A project demonstrating the problem is available here:
https://drive.google.com/file/d/181Aggala2ZfGN0lDjEtHWg0vobkM0iJc/view?usp=sharing
I already tried to change the insets of the tableview but it didn't work.
tableView.contentInset = UIEdgeInsets(top: navigationController?.navigationBar.height, left: 0, bottom: 0, right: 0)
Thanks!
As you discovered, to make large title fonts work as you want them to, the UIScrollView or any of its subclass needs to be the first element in the view hierarchy.
To fix your problem, you can try setting the background image to be the background of the UITableView directly.
Edit: Okay soo according to your comment you want a background behind everything including navigation bar. There is one way of achieving this and that is to subclass your UINavigationController and inside viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
let image = UIImage(named: "wallpaper")
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.frame = UIScreen.main.bounds
//this below part is important. Make sure to set it to 0 otherwise it will cover everything else
view.insertSubview(imageView, at: 0)
}
And then make sure your UIViewController containing the UITableView has a clear color for the UIView and remove the background image from that UIViewController

why UITabbarController is going too bottom

I have Implemented top items a view with UICollectionview and UIPagecontroller to get android like pagetabs.
For each menu there is a container ViewController but in one of them need UITabBarController.
Why UITabBarController is going down.
I have tried moving menuVIew(Contacts,Recents,etc) up but still did not work.
For the top view, use UISegmentedControl, and make background color, same as border color.
For the tab bar, you mean that it is covered by home indicator?
Turn on Use Safe Area Layout Guides, for this UITabController, and you should be good to go.
let tabBar = UITabBar()
override func viewDidLoad() {
super.viewDidLoad()
addTabbar()
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
addHeightConstraintToTabbar()
}
func addTabbar() -> Void {
self.view.addSubview(tabBar)
tabBar.translatesAutoresizingMaskIntoConstraints = false
tabBar.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
tabBar.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
tabBar.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
let item1 = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.bookmarks, tag: 1)
let item2 = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.contacts, tag: 2)
tabBar.items = [item1, item2]
self.view.bringSubview(toFront: tabBar)
}
func addHeightConstraintToTabbar() -> Void {
let heightConstant:CGFloat = self.view.safeAreaInsets.bottom + 49.0
tabBar.heightAnchor.constraint(equalToConstant: heightConstant).isActive = true
}
Result:
I have faced this issue before for iPhone X. I found a weird solution of this as below:
Change the bottom constraint from TabBar to Safe Area not the Super view and change the constraint value to 1 as shown in the below image.
This works on both The normal devices and devices with notch display. Check out the screenshots :
Hope this helps you.

Correct placement of UIImageView in UIBarButtonItem

When attempting to place a UIImageView(UIImage) into a UIBarButtonItem on a UINavigationBar, the image gets placed in the middle of the bar and also has wide fields covering the entire bar. So, doesn't look like a small button on the left.
I've tried various tricks with frame resizing, contentMode settings.
The below code is from my View Controller, which is part of the Navigation Controller stack. Added this image into Assets:
http://pluspng.com/img-png/png-hd-bike-ktm-bike-png-500.png
for testing, named it bike.png and used it in UIImage below.
override func viewDidLoad() {
super.viewDidLoad()
let image = UIImage(named: "bike")
let imageView = UIImageView(image: image)
imageView.backgroundColor = .blue //for debugging
imageView.contentMode = .scaleAspectFit
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: imageView)
}
The expected result would be to have the image of the motorbike in the left, rather than in the middle. Also, no empty fields to the left and to the right (highlighted in blue for debugging) of the image.
EXPECTED (drew up in Paintbrush):
REALITY:
Ended up resolving as:
imageView.widthAnchor.constraint(equalToConstant: (navigationController?.navigationBar.frame.height)!).isActive = true

UIPickerView width constraint issue

I need to add UIPickerView to UIAlertController. I use code:
let alertView = UIAlertController()
let pickerView = UIPickerView()
pickerView.translatesAutoresizingMaskIntoConstraints = false
alertView.view.addSubview(pickerView)
pickerView.topAnchor.constraint(equalTo: alertView.view.topAnchor, constant: 50).isActive = true
pickerView.bottomAnchor.constraint(equalTo: alertView.view.bottomAnchor, constant: -50).isActive = true
pickerView.centerXAnchor.constraint(equalTo: alertView.view.centerXAnchor).isActive = true
pickerView.widthAnchor.constraint(equalTo: alertView.view.widthAnchor).isActive = true
present(alertView, animated: true)
Here it is a result:
Why width of the UIPickerView more than UIAlertController?
Also I tried:
pickerView.widthAnchor.constraint(equalTo: alertView.view.widthAnchor, multiplier: 0.5).isActive = true
But got the same result...
when you give a constraint of width which exactly doing right.Issue is from your side look below image when you give a width constant of alertview.view which one UIalertController's main view.For better understand look below image(last view behind blue colour view colour and PickerView color is red.).
Now,we show actual alerview which one subview of main view(in above image Blue colour with Ok button).
change width constraint with subview instead of main view like:-
For better under standing:-
for view in alertView.view.subviews {
print(view)
//just add color which is shown in bellow image.
view.backgroundColor = UIColor.blue
}
So, Solution is like:-
pickerView.widthAnchor.constraint(equalTo: alertView.view.subviews[0].widthAnchor).isActive = true
Result:-
I hope this help you,
Thanks

Swift 4: Mask not working for UIImage?

I'm running the code below (simplified to important blocks) trying to make a side menu animation like the one done in this video: https://www.youtube.com/watch?v=ej5laXv2dzQ&vl=en. I'm trying to do the entire project without using Storyboard (heard it's a good practice, I'm sorta a newbie to iOS development lol), which means I need to create the mask for the side menu programmatically, and have changed some code to fit my needs. Whenever I run the code below, however, the image view that I'm setting the mask on disappears. The program builds, but the side menu image view just isn't appearing (image shown below). Where am I going wrong? Thanks.
let maskView: UIImageView = {
let iv = UIImageView()
iv.backgroundColor = .blue
return iv
}()
let sideMenu: UIImageView = {
let iv = UIImageView()
iv.image = "example.png"
iv.frame.origin.x = -80 //Setting side menu image view to off the left side of the screen so that it can slide in when tapped
return iv
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(maskView)
view.addSubview(sideMenu)
maskView.translatesAutoresizingMaskIntoConstraints = false
maskView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
maskView.widthAnchor.constraint(equalTo: 60).isActive = true
maskView.heightAnchor.constraint(equalTo: view.frame.height).isActive = true
sideMenu.translatesAutoresizingMaskIntoConstraints = false
sideMenu.rightAnchor.constraint(equalTo: view.leftAnchor).isActive = true // So when tapped, it slides 80px to the right, entering the screen
sideMenu.widthAnchor.constraint(equalTo: 80).isActive = true
sideMenu.heightAnchor.constraint(equalTo: view.frame.height).isActive = true
sideMenu.mask = maskView // this is always the line that makes the sideMenu disappear
}
Image of the issue (should have a white background for the side menu on the left):
Image
You need to set Y constraint like top or centerY
maskView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
sideMenu.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

Resources