How to create App Store Style Navigation Bar - ios

I'm trying to recreate the App Store navigation bar animation. What I'm currently doing is adjusting the alpha of the navigation bar based on the scroll position.
The issue is that when you slide back the navigation bar does not appear in the previous view so I set the alpha back to one in viewWillDissapear (which doesn't work the best as seen in the gif).
With regards to the back button, if you change the alpha of the navigation bar the back button is also affected. Apple has a different back button (the circle with the arrow) when the navigation bar is not visible and this button disappears with an animation as the navigation bar appears and the default back button appears. I'm not sure if they're just overlaying a new one.
This question has been asked before but the accepted answer was to make the navigation bar transparent then change it's opacity as you scroll. This doesn't create the same effect as the default navigation bar isn't white but translucent and you also lose the border line at the bottom.
Swift 5
override func viewWillDisappear(_ animated: Bool) {
navigationController?.navigationBar.alpha = 1
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let currentVerticalOffset = scrollView.contentOffset.y
var percentageVerticalOffset = CGFloat() //currentVerticalOffset / maximumVerticalOffset
if currentVerticalOffset > collectionView.frame.size.height {
percentageVerticalOffset = currentVerticalOffset / currentVerticalOffset
self.title = "The Barn Owl"
//self.navigationItem.setHidesBackButton(false, animated: true)
} else {
percentageVerticalOffset = currentVerticalOffset / collectionView.frame.size.height
//self.navigationItem.setHidesBackButton(true, animated: true)
self.title = ""
}
// let color = UIColor.init(red: 255/255.0, green: 255/255.0, blue: 255/255.0, alpha: percentageVerticalOffset)
// navigationController?.navigationBar.backgroundColor = color
navigationController?.navigationBar.alpha = percentageVerticalOffset
}

Related

UINavigationBar Background Color Animation

I am trying to implement Apple's detail screen from their Podcast, Music, and App Store Apps. The navigation bar starts off transparent then increases the alpha the further down you scroll.
I have the desired effect working changing the alpha value of the navigationBar itself. However, this also affects the buttons within the navigationBar.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
var offset = scrollView.contentOffset.y / 350
if offset > 1 {
offset = 1
self.navigationController?.navigationBar.alpha = offset
self.navigationItem.setHidesBackButton(false, animated: false)
} else {
self.navigationController?.navigationBar.alpha = offset
self.navigationItem.setHidesBackButton(true, animated: false)
}
}
I believe I need to change either
The Navigation Bar's backgroundColor
The Navigation Bar's barTintColor
Upon implimenting each of these and replacing:
self.navigationController?.navigationBar.alpha = offset
with
self.navigationController?.navigationBar.barTintColor = Color.background?.withAlphaComponent(offset)
or
self.navigationController?.navigationBar.backgroundColor = Color.background?.withAlphaComponent(offset)
The animation does not transition, it simply goes from transparent to opaque.
I am setting up my Navigation Bar on this controller using iOS 13 methods
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
self.navigationController?.navigationBar.standardAppearance = appearance
Any help with this much appreciated.

How to animate Navigationbar like AppStore App Detail Page?

Navigationbar like AppStore
Transparent Navigation bar first and when app scroll up Navigation bar become visible.
Please check the effect in Gif File added with this question
First setup the navigation bar transparent like below
// Makes the navigation bar transparent
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.isTranslucent = true
navigationController?.view.backgroundColor = UIColor.clear
Now uses the UIScrollViewDelegate method scrollViewDidScroll to detect the percentage of the the scroll view and based on that change the alpha
// MARK: UIScrollViewDelegate
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
super.scrollViewDidScroll(scrollView)
let maximumVerticalOffset = scrollView.contentSize.height - scrollView.frame.height
let currentVerticalOffset = scrollView.contentOffset.y
let percentageVerticalOffset = currentVerticalOffset / maximumVerticalOffset
let color = UIColor.init(red: 255/255.0, green: 255/255.0, blue: 255/255.0, alpha: percentageVerticalOffset)
navigationController?.navigationBar.backgroundColor = color
}
Hope it is helpful to you
If you wants to make Navigation bar same like App Store I suggest you to remove the default navigation bar & create a custom Topbar by taking UIView & set up its frame as a Topbar.
The main reason is the default navigation bar is not look wise & behaviour wise looks good on iPhone X & such phones.
Another most important thing is may be you will be able to achieve it by default Navigation bar but Apple always keeps modifying the navigation system & due to that you can see deprecated methods specially in navigation.
So I better suggest if you create custom navigation it will be easily controllable & there will be no chances of the deprecated methods & all.
Hope this helps to you.

Navigation bar + Search controller + Large title: Hairline during scrolling

Context:
UINavigationController with a UITableViewController
UISearchController in the navigation bar
Navigation bar translucent with black style, it uses large title, tintColor, barTintColor (so no background image).
Issue:
I have a strange animation glitch that shows a hairline above the search bar. The hairline appears only during the scroll.
I have already tried many solutions concerning similar problems, but they have not helped.
Tested with an iPhone 7 with iOS 12.1.3
You can fix hairline issue using this
searchController.searchBar.layer.borderColor = UIColor(red: 242/255.0, green: 82/255.0, blue: 46/255.0, alpha: 1).CGColor
searchController.searchBar.layer.borderWidth = 1
if the above didn’t work. you can remove the hairline completely
extension UINavigationBar {
func hideBottomHairline() {
self.hairlineImageView?.isHidden = true
}
func showBottomHairline() {
self.hairlineImageView?.isHidden = false
}
}
extension UIView {
fileprivate var hairlineImageView: UIImageView? {
return hairlineImageView(in: self)
}
fileprivate func hairlineImageView(in view: UIView) -> UIImageView? {
if let imageView = view as? UIImageView, imageView.bounds.height <= 1.0 {
return imageView
}
for subview in view.subviews {
if let imageView = self.hairlineImageView(in: subview) { return imageView }
}
return nil
}
}

How to change background color of page indicator in UIPageViewController

I use a UIPageViewController in storyboard, and write a class inherit from UIPageViewController.
After I finished code, I found the background color of page indicator is black, which I don't know how to change.
I search the internet, and found many people will use UIViewController+UIPageControl to do custom page indicator.
Is it possible to change the background color in UIPageViewController?
Thanks!
by adding:
let pageControl = UIPageControl.init(frame: CGRectMake(0, UIScreen.mainScreen().bounds.size.height*14/15, UIScreen.mainScreen().bounds.size.width, UIScreen.mainScreen().bounds.size.height))
pageControl.backgroundColor = UIColor.init(red: 0, green: 147/255, blue: 229/255, alpha: 1)
view.addSubview(pageControl)
I've changed the color successfully.
But I've another question.
Although I've set the imageView to fill the full screen, the page control will cover the button of the image, how could I avoid page control cover the image, and only show the dots?
I struggled with this for over two hours. Here's what I did in Swift 4
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
for view in self.view.subviews{
if view is UIPageControl{
(view as! UIPageControl).currentPageIndicatorTintColor = .yellow
}
}
}
Once you have the UIPageControl in this block, you should be able to customize its indicator colours

UINavigationBar that changes transparency when scrolling

I am trying to implement UINavigationBar that changes its transparency when scrolling UITableView. At the beginning, the navigation bar should have transparent background, so the content below it should be visible (there will be an image displayed, for the example I am using solid color):
When user scrolls table view, transparency should be replaced with solid color:
Table view will contain section headers, that should act like when using non-translucent navigation bar. The header views should "stick" to navigation bar once they "touch" it from the bottom:
I have no luck with trying to implement this flow in iOS app.
For the initial state, I am setting UINavigationBar translucent property to YES, and both backgroundColor and barTintColor to clear color, which gives me what I want.
Then, when user scrolls table view, I am updating the backgroundColor and barTintColor to a color with given alpha component, computed basing on current scroll offset. I am using scrollViewDidScroll: from UIScrollViewDelegate protocol to do so. However, it changes only the background of navigation bar, leaving status bar background transparent, which is not what I want.
I can't find another way of making UINavigationBar transparent without setting translucent property to YES. Unfortunately, this changes how the section headers acts when scrolling. As navigation bar is translucent, section header views hides below it when they should "stick" to the bar like on third screenshot above.
I would appreciate any help and hints how to achieve navigation bar that acts like described or similar in Objective-C or Swift.
Assuming that you have a reference to the view above the tableView and that you don't want to interact anything in it:
var overlayView:UIView!
var offsetDenominator:CGFloat!
let TARGER_COLOR = UIColor.blackColor()
override func viewDidLoad() {
super.viewDidLoad()
if let navCtrl = self.navigationController {
self.offsetDenominator = headerView.frame.size.height - navCtrl.navigationBar.frame.height
let targetCIColor = CIColor(CGColor: self.TARGER_COLOR.CGColor)
let overlayColor = UIColor(red: targetCIColor.red, green: targetCIColor.green, blue: targetCIColor.blue, alpha: 0.0)
self.overlayView = UIView(frame: self.headerView.frame)
self.overlayView.backgroundColor = overlayColor
self.view.addSubview(self.overlayView)
}
...
override func scrollViewDidScroll(scrollView: UIScrollView) {
if let navCtrl = self.navigationController, let breakpoint = offsetDenominator {
let alpha = scrollView.contentOffset.y / breakpoint
if alpha >= 1.0 {
navCtrl.navigationBar.backgroundColor = self.TARGER_COLOR
} else {
let targetCIColor = CIColor(CGColor: self.TARGER_COLOR.CGColor)
let overlayColor = UIColor(red: targetCIColor.red, green: targetCIColor.green, blue: targetCIColor.blue, alpha: alpha)
self.overlayView.backgroundColor = overlayColor
navCtrl.navigationBar.backgroundColor = UIColor.clearColor()
}
}
}
My approach is:
override func viewDidLoad() {
super.viewDidLoad()
...
self.setNavbarTransculent()
}
private func setNavbarTransculent() {
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let denominator: CGFloat = 50 //your offset treshold
let alpha = min(1, scrollView.contentOffset.y / denominator)
self.setNavbar(backgroundColorAlpha: alpha)
}
private func setNavbar(backgroundColorAlpha alpha: CGFloat) {
let newColor = UIColor(red: 1, green: 1, blue: 1, alpha: alpha) //your color
self.navigationController?.navigationBar.backgroundColor = newColor
UIApplication.shared.statusView?.backgroundColor = newColor
}
extension UIApplication {
var statusView: UIView? {
return value(forKey: "statusBar") as? UIView
}
}
Swift3
var navAlpha = // Your appropriate calculation
self.navigationController!.navigationBar.backgroundColor = UIColor.red.withAlphaComponent(navAlpha)

Resources