I am trying to add a background image to my nav bar using the UINavigationBarAppearance. However, the imageView size is bigger than the navigation bar content view.. How do I fix this?
Result: Notice the imageview overlaps with the safearea
Heiarchy debugger
Code:
private func setupNavBar() {
navigationItem.largeTitleDisplayMode = .never
guard let navigationController = navigationController else { return }
let appearance = navigationController.navigationBar.standardAppearance.copy()
appearance.configureWithTransparentBackground()
appearance.backgroundImage = UIImage.checkmark
appearance.backgroundImageContentMode = .scaleAspectFit
appearance.backgroundColor = .red
navigationController.navigationBar.standardAppearance = appearance
}
Found an alternative. Instead of using the appearance background image, I set the titleView on the navigation item.
let imageView = UIImageView(image: UIImage.checkmark)
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView
Related
I'm implementing a custom Tab bar for my iOS app. Im using the following code to display a background image:
class TabNavigationMenu: UIView {
// ...
// ...
UIGraphicsBeginImageContext(self.frame.size)
UIImage(named: "tabBarbg.png")?.draw(in: self.bounds)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
if let image = image {
self.backgroundColor = UIColor(patternImage: image)
}
}
However, the tab bar is presented like this:
Also, when i make a view and present it anywhere else in the screen, it displays correctly. I'm using the same code there as well. Heres an example:
Any idea what the problem could be? I'm guessing the solution would also solve the faint blue line on top of the view...
You can try this to customize tab bar in ios
//Set the background color
UITabBar.appearance().backgroundColor = .red
tabBar.backgroundImage = UIImage(named: "tabBarbg.png")
//Set the item tint colors
tabBar.tintColor = .white
tabBar.unselectedItemTintColor = .lightGray
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
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.
I'm trying to make my navigation bar transparent in my app, so I tried to change the bar tint's opacity down to 0 so it's completely clear. However, this has absolutely no effect on the color of the background.
I've also tried programmatic solutions, putting the following code in viewDidLoad:
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.isTranslucent = true
navigationController?.view.backgroundColor = .clear
However, I've gotten nothing to work. Is there a way that I'm missing to make my navigation bar completely transparent (but keep the bar buttons not transparent)
self.navigationController?.navigationBar .setBackgroundImage(UIImage(), for: UIBarMetrics.default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.view.backgroundColor = .clear
self.navigationController?.navigationBar.backgroundColor = .clear
self.navigationController?.navigationBar.tintColor = UIColor.white
You must walk through the view hierarchy and find the views that you need to hide. Click on the "Debug View Hierarchy" button to see a list of views and their names.
Here's a function that works for me:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
transparentBackgrounds(navigationController?.navigationBar)
}
func transparentBackgrounds(_ view: UIView?) {
guard let view = view else { return }
let className = String(describing: type(of: view))
print(className)
if ["_UIBarBackground","UIImageView","UIVisualEffectView"].contains(className) {
view.isHidden = true
}
view.backgroundColor = UIColor.clear
for v in view.subviews {
transparentBackgrounds(v)
}
}
I am trying to make a blurred background the UITabBar for my UITabViewController, and the idea is to have it be blurred and transparent so that the views underneath can be seen scrolling by.
Unfortunately I cannot for the life of me get the tab bar to be transparent. No matter what I do, there is always some black background to the tab bar that prevents the underlying view controllers from showing through.
If I change the alpha of the UITabBar to something low I can see that the tableview is indeed behind it, however you can see that the UITabBar has some sort of background to it that is preventing the tableview from fully showing through (and I don't want to bar button items to be invisible, just the tab bar background).
How can this be?
In the custom tab bar's view did load I have:
self.tabBar.translucent = true
self.tabBar.alpha = 0.3
self.tabBar.backgroundColor = UIColor.clearColor().colorWithAlphaComponent(0.0)
self.tabBar.layer.backgroundColor = UIColor.clearColor().colorWithAlphaComponent(0.0).CGColor
self.tabBar.backgroundImage = nil
self.tabBar.shadowImage = nil
and in the AppDelegate I have:
UITabBar.appearance().barTintColor = UIColor.clearColor()
UITabBar.appearance().tintColor = kColorAccent
UITabBar.appearance().translucent = true
UITabBar.appearance().translucent = true
UITabBar.appearance().backgroundColor = UIColor.clearColor()
UITabBar.appearance().backgroundImage = nil
UITabBar.appearance().layer.backgroundColor = UIColor.clearColor().CGColor
UITabBar.appearance().shadowImage = nil
...yeah It's excessive but I want to try everything.
Any ideas on what to do?
Make a UITabBar transparent
Assign a clear image to its backgroundImage. You can use a 1x1 clear.png, or create one programmatically:
self.backgroundImage = UIImage.imageWithColor(UIColor.clearColor())
This will make the UITabBar transparent:
Add a blur effect
Insert a UIVisualEffectView as the rearmost subview.
let frost = UIVisualEffectView(effect: UIBlurEffect(style: .Light))
frost.frame = self.bounds
self.insertSubview(frost, atIndex: 0)
This will insert a UIBlurEffect (frost):
Example
Set the Custom Class for the UITabBar of the Tab Bar Controller to FrostyTabBar.
You have a few options to supply a clearColor image. You can create a clear.png image with an alpha of 0. A programmatic elegant solution is described here.
If using a clear.png, assign it to the Background Image in the Attribute Inspector:
In Interface Builder, pick Style: Default & Translucent.
Once you take control of the background blur with a UIVisualEffectView, you can in turn supply any UIVisualEffect you so desire.
The entire FrostyTabBar class looks like this:
import UIKit
class FrostyTabBar: UITabBar {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let frost = UIVisualEffectView(effect: UIBlurEffect(style: .light))
frost.frame = bounds
frost.autoresizingMask = .flexibleWidth
insertSubview(frost, at: 0)
}
}
► Find this solution on GitHub and additional details including a 1x1 clear.png on Swift Recipes.
I found a prefect solution, you only need to subclass UITabBar and then do the following actions to clean that annoying views
class MainTabBar: UITabBar {
var cleanDone = false
override func layoutSubviews() {
super.layoutSubviews()
self.deleteUnusedViews()
}
func deleteUnusedViews() {
if !self.cleanDone {
var removeCount = 0
for (_, eachView) in (self.subviews.enumerate()) {
if NSStringFromClass(eachView.classForCoder).rangeOfString("_UITabBarBackgroundView") != nil {
eachView.removeFromSuperview()
removeCount += 1
}
if NSStringFromClass(eachView.classForCoder).rangeOfString("UIImageView") != nil {
eachView.removeFromSuperview()
removeCount += 1
}
if removeCount == 2 {
self.cleanDone = true
break
}
}
}
}
}
the only solution that worked for me was this:
UITabBar.appearance().shadowImage = UIImage()
UITabBar.appearance().backgroundImage = UIImage()
and set: (you can do this in storyboard as well)
UITabBar.appearance().barTintColor = UIColor.clear
but what i have to set in storyboard is:
tabbar : translucent -> true