Swift: Tableview scrolls under navigation bar but over status bar? - ios

I hid the navigation bar's shadow using the following trick:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
I also have the following set:
self.extendedLayoutIncludesOpaqueBars = true
self.automaticallyAdjustsScrollViewInsets = true
self.tabBarController?.tabBar.isHidden = true
Everything looks fine on my page, except that when I scroll up my tableView it goes under the navigation bar as expected, but above the status bar:
How do I make sure that the tableView scrolls under both the navigation bar and status bar?

This will place the UITableView below the status bar.
self.edgesForExtendedLayout=UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars=NO;
self.automaticallyAdjustsScrollViewInsets=NO;

You hid the default background of the navigation bar so this is to be expected. It means you are creating the green background in the navigation bar by yourself. You have to manually extend it to cover both status bar and navigation bar which is what the default background would do.
Or use a green image instead of a transparent one.

I had same problem and the only thing which helped was to set a top anchor of my table view to safeArea topAnchor
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true

You can try table view as under the UIEdgeInsetMake and also its scroll view
tableView.contentInset = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
tableView.scrollIndicatorInsets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)

Related

Part over navigation bar has different background color

I am really struggling figuring out why there's a part on top of the navigation bar that has a different color than the navigation bar.
I have set the navigation like this:
navigationController?.navigationBar.tintColor = .white
navigationController?.navigationBar.backgroundColor = .primaryBlack
navigationController?.setNavigationBarHidden(false, animated: true)
And for some reason only one part is with that color but not everything. In some other parts that part is completely transparent making it look really odd.
I encountered this issue when ever my navigation bar is using large titles and push a view controller onto the navigation stack of the navigation controller, this gap seems to be at the top:
There seems to be some gap created for some reason and the large title navigation bar starts under the status bar.
The reason I understand as per the documentation is that the base view goes under the UINavigationBar and when this view is scrolled, the UINavigationBar needs to transform.
When a navigation controller contains a navigation bar and a scroll
view, part of the scroll view’s content appears underneath the
navigation bar. If the edge of the scrolled content reaches that bar,
UIKit applies the appearance settings in this property.
Simplest thing I do is to make the underlying view the same color as the navigation bar background in the view controller and keep the result of your code the same:
// Same as your code, only changed background to blue
navigationController?.navigationBar.tintColor = .white
navigationController?.navigationBar.backgroundColor = .blue
navigationController?.setNavigationBarHidden(false, animated: true)
// What I added
view.backgroundColor = .blue
This gives me:
Update using UINavigationBarAppearance
Can you try updating using UINavigationBarAppearance
// From your code, not sure of it's purpose
navigationController?.setNavigationBarHidden(false, animated: true)
let appearance = UINavigationBarAppearance()
// Color of the nav bar background
appearance.backgroundColor = .black // primary black for you
// Color for the titles
appearance.largeTitleTextAttributes
= [NSAttributedString.Key.foregroundColor : UIColor.white]
appearance.titleTextAttributes
= [NSAttributedString.Key.foregroundColor : UIColor.white]
navigationController?.navigationBar.standardAppearance = appearance
navigationController?.navigationBar.scrollEdgeAppearance = appearance
// Color for the back button
navigationController?.navigationBar.tintColor = .white
Result:

Supplymentary header view not taking to status bar collection view

I make this screen with collection view with using supplementary HeaderView. I want to make this HeaderView to the status bar. I make clear color to status bar but it is not working. Please help me with it.
I think you need to make the next, delete this view and put this image in the back of the navigation bar, the next is putting navigation bar transparent and the tint color in white like this :
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.view.backgroundColor = .clear
self.navigationController?.navigationBar.tintColor = UIColor.white
You could try to get the contents of the collection view started earlier.
collectionView.contentInset.top = -14
So, first of all in your info.plst tap "+" button and this line.
Than in your UIViewController add this method.
override var prefersStatusBarHidden: Bool {
return true
}
Status bar will be hidden only in this viewController.

UITableView under transparent navigation bar

I'm trying to layout a tableview in a UIViewController with a transparent navigationBar. I already accomplished this, using this code on my custom UINavigationController:
navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationBar.shadowImage = UIImage()
navigationBar.isTranslucent = true
On my storyboard I set my tableView with its edges pinned to the safe area, except for the top one, who is pinned to the top of the super view.
Problem is that my tableView is not starting at the top of the screen but as if the navigation bar is still opaque. I check the tableView insets and all are zero. What I'm doing wrong here?
Thanks
You can try to disable the scroll view insets adjustment.
contentInsetAdjustmentBehavior is available from iOS11 so you can check the availability like in this code:
if (#available(iOS 11.0, *))
{
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
else
{
self.automaticallyAdjustsScrollViewInsets = NO;
}

UINavigationBar transparent + on top of UITableView

I have a transparent UINavigationBar. I also set hidesBarsOnSwipe to true. I want my navigationBar be on top of the content and hides when scrolling. Basically i want to achieve this effect (Navigation Bar on top of the content and also hiddes when scroll):
For now i just have this code and works everything, but i'm not able to put the content of the view behind the navigationBar:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.backgroundColor = .clear
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.hidesBarsOnSwipe = true
Here is a sample project , as you see the tableView is at the bottom of the navigationBar and just goes to the top when it hides the navigationBar.
On your view controller in Interface Builder disable Adjust Scroll View Insets. You can probably do it from code if you want as well.

Black Translucent Navigation Bar Opaque Until First Drag

I have an odd situation where I cannot for the life of me get an app to start with the UINavigationBar set to transparent black. The app consists of a UINavigationController with a UIPageViewController as root. These are loaded from a storyboard when the app launches.
The app runs and the UINavigationBar shows up as opaque. As soon as I start dragging the UIPageViewController it triggers some sort of redraw and the UINavigationBar becomes transparent as desired.
I tried a few different ways of setting the UINavigationBar to transparent black, and none of them produced behavior any different than described:
I set these keys in Info.plist:
<key>UIStatusBarTintParameters</key>
<dict>
<key>UINavigationBar</key>
<dict>
<key>Style</key>
<string>UIBarStyleBlack</string>
<key>Translucent</key>
<true/>
</dict>
</dict>
I set the UINavigationBar appearance in the AppDelegate in didFinishLaunchingWithOptions:
UINavigationBar.appearance().tintColor = UIColor.black
UINavigationBar.appearance().isTranslucent = true
I subclassed UINavigationController and set NavigationBar properties in viewDidLoad():
navigationBar.barStyle = .black
navigationBar.isTranslucent = true
navigationBar.setNeedsDisplay()
I set the NavigationBar properties in viewDidLoad() of the UIPageViewController (the navigation controller's root view controller):
navigationController!.navigationBar.barStyle = .black
navigationController!.navigationBar.isTranslucent = true
navigationController!.navigationBar.setNeedsDisplay()
I also tried toggling the navigation bar on / off to trigger a refresh
navigationController!.isNavigationBarHidden = true
navigationController!.isNavigationBarHidden = false
For the sake of completion, I set the navigation bar properties in viewDidLoad() of the child view controller of the UIPageViewController.
In every single case I get the same behavior: opaque bar until I touch the screen and start a drag, at which point it switches to transparent.
What's odd is that setting other attributes of the navigation bar, such as titleTextAttributes, leftButtonItem, and rightButtonItem works just fine and the changes are reflected immediately.
I had a similar requirement with Swift3 an achieved it in this way:
In your view controller which contains PageViewController add the following code in viewDidLoad()
func makeNavigationTranslucent() -> Void {
self.navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.view.backgroundColor = UIColor.clear
self.navigationController?.navigationBar.backgroundColor = UIColor.init(colorLiteralRed: 0.5, green: 0.5, blue: 0.5, alpha: 0.9)
}
Note : Change navigationBar.backgroundColor to the one which you want.
In your storyboard select your controller and under attribute inspector with simulated metrics heading set top bar to Navigation Translucent Bar. Refer below image :
This is kind of a hacky solution, but I managed to get it working by hiding the default navigation bar and adding a new one over it. In the page view controller viewDidLoad() function:
navigationController!.isNavigationBarHidden = true
let newNavBar = UINavigationBar()
newNavBar.barStyle = .black
newNavBar.isTranslucent = true
newNavBar.titleTextAttributes = [NSFontAttributeName: UIFont.mainFontThin(24),
NSForegroundColorAttributeName: UIColor.white]
// etc...
navigationController!.view.addSubview(newNavBar)
newNavBar.frame = CGRect(
x:0, y:0,
width:navigationController!.view.bounds.width,
height:navigationController!.navigationBar.frame.height + UIApplication.shared.statusBarFrame.height
)
newNavBar.pushItem(navigationItem, animated: false)
This shows the translucent navigation bar like we want, but there's still a small problem where the app status bar is black under the translucent nav bar. As before, once you drag a finger the status bar updates to transparent. I'm not sure how to fix this, adding a call to setNeedsStatusBarUpdate() didn't help. So this is a partial fix.

Resources