UIViewController In-Call Status Bar Issue

前端 未结 8 916
误落风尘
误落风尘 2020-12-01 12:24

Issue:

Modally presented view controller does not move back up after in-call status bar disappears, leaving 20px empty/transparent space at the top.<

相关标签:
8条回答
  • 2020-12-01 13:04

    I solve this issue by using one line of code

    In Objective C

    tabBar.autoresizingMask = (UIViewAutoResizingFlexibleWidth | UIViewAutoResizingFlexibleTopMargin);
    

    In Swift

    self.tabBarController?.tabBar.autoresizingMask = 
      UIViewAutoresizing(rawValue: UIViewAutoresizing.RawValue(UInt8(UIViewAutoresizing.flexibleWidth.rawValue) | UInt8(UIViewAutoresizing.flexibleTopMargin.rawValue)))`
    

    You just need to make autoresizingMask of tabBar flexible from top.

    0 讨论(0)
  • 2020-12-01 13:10

    Be sure to set the frame of the view controller's view you are presenting to the bounds of the container view, after it has been added to the container view. This solved the issue for me.

    containerView.addSubview(toViewController.view)
    toViewController.view.frame = containerView.bounds
    
    0 讨论(0)
  • 2020-12-01 13:19

    I faced this problem too but after I put this method, problem is gone.

    iOS has its default method willChangeStatusBarFrame for handling status bar. Please put this method and check it .

    func application(_ application: UIApplication, willChangeStatusBarFrame newStatusBarFrame: CGRect) {
        UIView.animate(withDuration: 0.35, animations: {() -> Void in
            let windowFrame: CGRect? = ((window?.rootViewController? as? UITabBarController)?.viewControllers[0] as? UINavigationController)?.view?.frame
            if newStatusBarFrame.size.height > 20 {
                windowFrame?.origin?.y = newStatusBarFrame.size.height - 20
                // old status bar frame is 20
            }
            else {
                windowFrame?.origin?.y = 0.0
            }
            ((window?.rootViewController? as? UITabBarController)?.viewControllers[0] as? UINavigationController)?.view?.frame = windowFrame
        })
    }
    

    Hope this thing will help you.
    Thank you

    0 讨论(0)
  • 2020-12-01 13:20

    I've been looking for a solution for 3 days. I don't like this solution but didn't found better way how to fix it.

    I'he got situation when rootViewController view has bigger height for 20 points than window, when I've got notification about status bar height updates I manually setup correct value.

    Add method to the AppDelegate.swift

    func application(_ application: UIApplication, didChangeStatusBarFrame oldStatusBarFrame: CGRect) {
            if let window = application.keyWindow {
                window.rootViewController?.view.frame = window.frame
            }
        }
    

    After that it works as expected (even after orientation changes). Hope it will help someone, because I spent too much time on this.

    P.S. It blinks a little bit, but works.

    0 讨论(0)
  • 2020-12-01 13:20

    I think this is a bug in UIKit. The containerView that contains a presented controller's view which was presented using a custom transition does not seem to move back completely when the status bar returns to normal size. (You can check the view hierarchy after closing the in call status bar)

    To solve it you can provide a custom presentation controller when presenting. And then if you don't need the presenting controller's view to remain in the view hierarchy, you can just return true for shouldRemovePresentersView property of the presentation controller, and that's it.

    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        return PresentationController(presentedViewController: presented, presenting: presenting)
    }
    
    class PresentationController: UIPresentationController {
        override var shouldRemovePresentersView: Bool {
            return true
        }
    }
    

    or if you need the presenting controller's view to remain, you can observe status bar frame change and manually adjust containerView to be the same size as its superview

    class PresentationController: UIPresentationController {
        override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
            super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
            NotificationCenter.default.addObserver(self,
                                                   selector: #selector(self.onStatusBarChanged),
                                                   name: .UIApplicationWillChangeStatusBarFrame,
                                                   object: nil)
        }
    
        @objc func onStatusBarChanged(note: NSNotification) {
            //I can't find a way to ask the system for the values of these constants, maybe you can
            if UIApplication.shared.statusBarFrame.height <= 20,
                let superView = containerView?.superview {
                UIView.animate(withDuration: 0.4, animations: {
                    self.containerView?.frame = superView.bounds
                })
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-01 13:24

    I've been looking for a solution to this problem. In fact, I posted a new question similar to this one. Here: How To Avoid iOS Blue Location NavigationBar Messing Up My StatusBar?

    Believe me, I've been solving this for a couple of days now and it's really annoying having your screen messed up because of the iOS's status bar changes by in-call, hotspot, and location.

    I've tried implementing Modi's answer, I put that piece of code in my AppDelegate and modified it a bit, but no luck. and I believe iOS is doing that automatically so you do not have to implement that by yourself.

    Before I discovered the culprit of the problem, I did try every solution in this particular question. No need to implement AppDelegate's method willChangeStatusBar... or add a notification to observe statusBar changes.

    I also did redoing some of the flows of my project, by doing some screens programmatically (I'm using storyboards). And I experimented a bit, then inspected my previous and other current projects why they are doing the adjustment properly :)

    Bottom line is: I am presenting my main screen with UITabBarController in such a wrong way.

    Please always take note of the modalPresentationStyle. I got the idea to check out my code because of Noah's comment.

    Sample:

    func presentDashboard() {
        if let tabBarController = R.storyboard.root.baseTabBarController() {
            tabBarController.selectedIndex = 1
            tabBarController.modalPresentationStyle = .fullScreen
            tabBarController.modalTransitionStyle = .crossDissolve
    
            self.baseTabBarController = tabBarController
            self.navigationController?.present(tabBarController, animated: true, completion: nil)
        }
    }
    
    0 讨论(0)
提交回复
热议问题