Hans Brende
Hans Brende

Reputation: 8647

Odd Navigation Bar/Status Bar behavior in Swift

I'm displaying a UITableViewController embedded in a UINavigationController. I've also created an animation to slide the navigation bar off the screen when the user scrolls upwards, matching the user's finger motion (I mention this because removing this animation also removes my bug, but I'm not sure why). When the user selects a row of the table, a new (blank) UIViewController is presented in which the status bar is hidden. When this second controller is dismissed with a tap, we return to the first controller.

After the second controller is dismissed, some very strange behavior may occur depending on whether or not the first controller's tableview was scrolled all the way to the top of the table or not when the table row was first selected.

Scenario 1: If the table was scrolled to the very top when the row was selected, the navigation bar appears to clip itself to its bounds after the second view controller is dismissed. In other words, the status bar no longer has the same background color as the navigation bar, but is transparent: the rows of the table view are now visible under the status bar.

Scenario 2: If the table was NOT scrolled to the very top when the row was selected, the navigation bar/status bar behavior is perfectly normal after the second controller is dismissed, and any lingering odd behavior is corrected.

scenarios

Here is my (condensed) code:

import UIKit

class ViewControllerTest: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController!.navigationBar.barTintColor = UIColor.grayColor()
        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Add, target: nil, action: nil)
    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        presentViewController(OtherViewControllerWithNoStatusBar(), animated: false, completion: nil)
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 100
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        cell.textLabel!.text = "item \(indexPath.row)"
        return cell
    }

    var previousScrollViewYOffset : CGFloat = 0

    override func scrollViewDidScroll(scrollView: UIScrollView) {
        //for navBar hiding
        let navBar = navigationController!.navigationBar
        var f = navBar.frame;
        let size = f.size.height - 21;
        let framePercentageHidden = ((20 - f.origin.y) / (f.size.height - 1));
        let scrollOffset = scrollView.contentOffset.y;
        let scrollDiff = scrollOffset - self.previousScrollViewYOffset;
        let scrollHeight = scrollView.frame.size.height;
        let scrollContentSizeHeight = scrollView.contentSize.height + scrollView.contentInset.bottom;

        if scrollOffset <= -scrollView.contentInset.top {
            f.origin.y = 20
        } else if (scrollOffset + scrollHeight) >= scrollContentSizeHeight {
            f.origin.y = -size
        } else {
            f.origin.y = min(20, max(-size, f.origin.y - scrollDiff))
        }

        navBar.frame = f
        navBar.tintColor = navBar.tintColor.colorWithAlphaComponent(1 - framePercentageHidden)
        self.previousScrollViewYOffset = scrollOffset
    }
}

class OtherViewControllerWithNoStatusBar : UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.greenColor()
        let label = UILabel(frame: view.bounds)
        label.text = "Tap to dismiss!"
        view.addSubview(label)
        view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "dismiss"))
    }

    override func prefersStatusBarHidden() -> Bool {
        return true
    }

    func dismiss() {
        presentingViewController!.dismissViewControllerAnimated(false, completion: nil)
    }

}

What I want to know is: (1) why is the behavior in Scenario 1 occurring, and (2) how do I fix it?

I'm using Xcode 7.1, and I've tested this on iPhone 5 & 6 and iOS 9.1.

Upvotes: 0

Views: 1471

Answers (1)

Anbu.Karthik
Anbu.Karthik

Reputation: 82766

This is my small Suggestion, why your are not tried the simple/Native answer use use default navigation bar and set animation like to show/hide

on Swipe Event

navigationController?.hidesBarsOnSwipe = true

or

on Select/Tap Event

   // setting hidesBarsOnTap to true
    navigationController?.hidesBarsOnTap = true

additional Information.

else use simple/Native function for show and hide animation like

self.navigationController?.setNavigationBarHidden(true, animated: true)
 UIApplication.sharedApplication().statusBarHidden=true

Upvotes: 2

Related Questions