Display navigationbar when scrolling down - swift

On the top of the ViewController, I have a image and I hide the navigationbar, for a better visual effect.
If the user scrolls up, there is a zoom on the image. No problem so far.
If the user scrolls down, I want to display the navigation bar with animation (very light to the correct background color of the navbar)
I ve checked here a good tutorial with the new possibilities with Ios8.
In fact, i need to perform the opposite of hidesBarsOnSwipe
So firstly, to hide the navigationbar I need to
self.navigationController?.isNavigationBarHidden = true
And after some search, I think I will need to use UIScrollViewDelegate.
But I have no idea how could i implement it .
Any hint?

What you have to do is to implement the UIScrollViewDelegate and more precisely the scrollViewDidScroll(_:) method (see documentation). This method is called each time the scroll view is scrolled.
So, in this method, you have to check that the user scrolled down and then hide the navigation bar by calling the setNavigationBarHidden(_:animated:) method of your current navigation controller (see documentation)

func scrollViewDidScroll(_ scrollView: UIScrollView) {
let defaultOffset = view.safeAreaInsets.top
let offset = scrollView.contentOffset.y + defaultOffset
navigationController?.navigationBar.transform = .init(translationX: 0, y: min(0, -offset))
}
use this function and it scrolls up the navigation bar while scrolling up and whenever you scroll down then the navigation bar appears again..

Related

Scrolling with two UICollectionViews

I have two collectionviews in my ViewController. The first one scrolls horizontally and the second scrolls vertically. The horizontal collectionview is at the top of the screen and the vertical scrolling one is right underneath it.
This is similar to how instagram has its stories on top of the instagram feed.
I used this scrollView function to offset the collectionviews when I scroll but the background of the top collectionview still stays on screen. Can anyone assist me with also having the background move when the bottom collectionview scrolls.
Here is my scrollView code:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if feedCollectionView == scrollView {
var scrollBounds = storiesCollectionView.bounds
scrollBounds.origin.y = feedCollectionView.contentOffset.y
storiesCollectionView.bounds = scrollBounds
}
}
Here is a gif of how it looks right now:
I am looking to have similar functionality as the instagram app when you scroll through the home feed.
I think you should just use one collection with two different layouts for each section

UINavigationController weird transparency behaviour when presenting

I'm experiencing a weird glitch with the transparent navigation controller. When presenting a view controller with a UIImage at the top of the navigation controller: at first presents half of its background blur with a dark section, and half with a clear one; and after a very short moment it changes for a full dark background. As shown in the gif:
The UIImage displayed is mostly white, the borders are very close to pure white. So the grey color does not make much sense (less sense makes the rapid change).
I did disable extend edges under top bar in the Storyboard for the presented view controller. So the image is not hidden behind the Navigation Controller. With this option enabled the glitch does not appear, but I don't want to hide part of the image.
Disabling the transparency, solves my problem, but I'd like to be able to keep the transparency effect.
Edit: I did notice the "grey effect" also makes the navigation controller opaque. But only for that view, when going back, is transparent again.
Xcode 11, Swift 5, iOS 13.2, iPhone XS.
Thank you very much for your help.
I finally found the problem.
I didn't want the UIScrollView to bounce on top so I used this code:
extension ProblematicViewController: UIScrollViewDelegate {
/// Prevent bounce at top
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y < 0 {
scrollView.contentOffset.y = 0
}
}
}
Which meant the ViewController's Adjust Scroll View Insets were overwrite (I think). So my scroll view did lay under the UINavigationController, to prevent this from happening, I did disable Extend Edges: Under Top Bars, so the root UIView containing the UIScrollView was not covered by the UINavigationController. So the transparency effect could never happen because the view was never under the top bar. More about Adjust Scroll View Insets on this post (helped me to find the problem).
Removing those lines and enabling Adjust Scroll View Insets and Extend Edges: Under Top Bars, solves the glitch problem, but the UIViewController does not have the "prevent bounce on top" behaviour that I wanted.
This kinda explains the weird behaviour of the UINavigationController because the SO has to calculate a transparency over nothing, but is sill strange, the transparency effect is calculated when the ProblematicViewController is fully presented, and not on viewDidLoad() or another view's life cycle before is shown to the user, so the transition is smooth, even when nothing lays behind the effect.

NavigationBar Translucent Animation

I have a ViewController which starts with a translucent navigationbar with clear background
navigationBar.isTranslucent = true
navigationBar.barTintColor = .clear
I have scrollView as the first child and scrollView's contentInsetAdjustmentBehavior is set to .never. Now when I scroll the view and scrollView.contentOffset.y > 200 I decided to change the navigationbar as
navigationBar.isTranslucent = false
navigationBar.barTintColor = .someColor
the scroll view get pushed down. I understand that when the view is supposed to be below the navigation bar when it is not translucent. But this makes my scroll effect look ugly. I did little research and found that I can enable Under the top bar option from storyboard, nut unfortunately I am building my using swift, and not using storyboard. I also tried using edgesForExtendedLayout = [.top] but did not work form me.
I wanted was a smooth scrolling behaviour while scrolling, with Navigationbar changing the property of translucent with respect to scrolling contentOffset.

sending UIScrollView to Background

I'm midway of finishing my app. I noticed that one of my views needs extra vertical space so I need to add a UIScrollView. Yet when I add that scroll view it overlaps everything else in the view. In simple words if I need to get it to work properly I have to delete everything off the view , add the scroll view, and then re-add everything back! Is there anyway to send this scroll view to the background of the view? This is all the code that concerns the scroll view
#IBOutlet var scrollerForPOfFourBar: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
/* non related code here*/
scrollerForPOfFourBar.userInteractionEnabled = true
scrollerForPOfFourBar.self.contentSize = CGSizeMake(320, 400)
}
I'm assuming you're using Interface Builder since you marked your scrollView as an IBOutlet.
On the view list, on the left, the order of the views specifies their Z order, with the views at the bottom being the ones drawn on top (with the largest Z).
To move your scrollView to the back, drag it just underneath of the view, and drop it there.
Keep in mind that you will have to drag all the views you had in your view into the scrollView (the easiest is to do it in the views navigator as well), and you'll have to set up any Auto Layout constraints again, which will be a pain.
Are you just want to move scrollerForPOfFourBar to back? Try this:
self.view.sendSubviewToBack(scrollerForPOfFourBar)

UITableview changing height when shown from different UINavigationControllers ('More')

I'm having an issue with UITableViewController's tableView changing its frame position when presented from a UITabBarController, within a UINavigationController. The frame is fine when displayed from a regular tab. However, if I move and show the UITableViewController from the 'More' Section, the tableview moves down the same height as the navigation bar (which I don't want it to). When I tested the runtime frame coordinates between proper and nonproper positions, it shows as the same (0.0, 0.0, 320.0, 411.0).
This issue only happens AFTER I've shown the tableView in one Nav Controller and then it's moved and shown in another, like the 'More' VC to the tab, or tab to the 'More' VC
What's going on here and how can I fix this?
The last image is how it looks like when the app launch, as it should be, with he table view right below the nav bar. In the first two however, you can see that the tableview has been moved down.
Thanks in advance!
I was able to solve the issue. It turns out that when you move a UITableView controller within a UINavigationController to the moreNavigationController, 44 pixels are added to the 'top' variables of contentInset and scrollIndicatorInsets. I'm not sure why this is happening or why those 44 pixels aren't being removed when the tableView leaves the 'moreNavigationController', but here's the answer. I'm calling these two lines from within viewWillAppear.
self.tableView.contentInset = UIEdgeInsetsMake(44.0, 0.0, 0.0, 0.0);
self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(44.0, 0.0, 0.0, 0.0);
The UITableViewController has this behaviour that it always try to best fit the screen size. UITableViewController is perfect for fullscreen tableview but otherwize I recommend not using the UITableViewController but instead implement a tableViewControler yourself by implementing both the datasource and delegate. Some did set resizeSubViews to NO and solve their problem but I really advice recreate the controller yourself which is not that much work.
Reset autosizing property of table view nib file.
You can find it inside :
Tool>Attribute Inspector
First take a UITableView in the view using XIB. Then add navigation bar and resize the tableview. You will get what do you actually want.
If you still find any problem then please let me know.
If you can display your code, or take a screenshot of your setup, it would be a lot easier. From my experience, creating UITableViewController instances and hooking them up in Interface Builder will expand to fill the screen.
How are you connecting it to the "More" tab? If it's in two tabs, and you're doing ANYTHING dynamic, check your UITableViewController class viewDidLoad method. You shouldn't have to add / delete / re-add the table unless they're separate instances.
Some places to check:
NSLog your tableHeaderView height and position
NSLog your tableFooterView height and position
Create a backgroundView and assign it to the tableView's backgroundView property to see what it's true dimensions are and where it's being displayed
Check where the UITableViewController's view starting position is.
Wish I could help more. Would like to see your setup / code.