Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UIViewController在调用状态栏中出现问题_Ios_Swift_Statusbar_Modalviewcontroller_In Call - Fatal编程技术网

Ios UIViewController在调用状态栏中出现问题

Ios UIViewController在调用状态栏中出现问题,ios,swift,statusbar,modalviewcontroller,in-call,Ios,Swift,Statusbar,Modalviewcontroller,In Call,问题: Modally presented view controller在调用状态栏消失后不会向上移动,在顶部留下20px的空白/透明空间 正常:无问题 通话中:无问题 呼叫消失后: 在顶部留下一个20px高的空白/透明空间,下面显示橙色视图。但是,状态栏仍然存在于透明区域上。导航栏也为状态栏留出了空间,因为它的位置太低,只有20px 基于iOS 10的 模态显示视图控制器 自定义模态表示法 后面的主视图控制器是橙色的 不使用自动布局 当旋转到横向时,调用栏中的20px会离开

问题:

Modally presented view controller在调用状态栏消失后不会向上移动,在顶部留下20px的空白/透明空间


正常:无问题


通话中:无问题


呼叫消失后:

在顶部留下一个20px高的空白/透明空间,下面显示橙色视图。但是,状态栏仍然存在于透明区域上。导航栏也为状态栏留出了空间,因为它的位置太低,只有20px


  • 基于iOS 10的
  • 模态显示视图控制器
  • 自定义模态表示法
  • 后面的主视图控制器是橙色的
  • 不使用自动布局
  • 当旋转到横向时,调用栏中的20px会离开,并且仍然会留下20px的间隙
  • 我选择退出横向显示状态栏。(即大多数股票应用程序)
我试着听应用程序代表说:

willChangeStatusBarFrame
didChangeStatusBarFrame
还可以查看基于控制器的通知:

UIApplicationWillChangeStatusBarFrame
UIApplicationDidChangeStatusBarFrame
当我为上述四种方法记录显示视图的帧时,该帧始终位于(y:0)原点


更新 查看控制器自定义模式演示文稿

    let storyboard = UIStoryboard(name: "StoryBoard1", bundle: nil)
    self.modalVC = storyboard.instantiateViewController(withIdentifier: "My Modal View Controller") as? MyModalViewController
    self.modalVC!.transitioningDelegate = self
    self.modalVC.modalPresentationStyle = .custom
    self.modalVC.modalPresentationCapturesStatusBarAppearance = true;
    self.present(self.modalVC!, animated: true, completion: nil)


    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView
        let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
        let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
        toViewController!.view.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)

        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.0, options: [.curveEaseOut], animations: { () -> Void in

            toViewController!.view.transform = CGAffineTransform.identity

        }, completion: { (completed) -> Void in

           transitionContext.completeTransition(completed)

        })
 }

我也面临着这个问题,但在我采用这种方法之后,问题就消失了

iOS有其处理状态栏的默认方法
willChangeStatusBarFrame
。请把这个方法放进去检查一下

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
    })
}
希望这件事对你有帮助。

谢谢

我对人事经理修改状态栏也有同样的问题。 解决方案是注册到系统通知以更改状态栏框架,这将允许您更新布局,并应修复可能存在的任何布局问题。 我的解决方案应该与您的解决方案完全相同:

  • 在视图控制器中,在
    视图中将出现
    中的
    引用
    UIApplicationIDChangeStatusBarFrameNotification

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(myControllerName.handleFrameResize(_:)), name: UIApplicationDidChangeStatusBarFrameNotification, object: nil)
    
  • 创建选择器方法

    func handleFrameResize(notification: NSNotification) {
    self.view.layoutIfNeeded() }
    
  • 视图中的通知中心删除控制器将消失

        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIApplicationDidChangeStatusBarFrameNotification, object: nil)
    
  • 您还需要您的模态来负责状态栏,因此您应该设置


    destVC.modalPresentationCapturesStatusBarAppearance=true
    
    在陈述观点之前


您可以在状态栏上容易发生更改的每个控制器上实现此功能,也可以创建另一个类来为每个控制器实现此功能,例如将self传递给一个方法,保留引用以更改布局,并使用一个方法删除self。你知道,为了重用代码。

我认为这是UIKit中的一个bug。当状态栏恢复到正常大小时,包含使用自定义转换显示的控制器视图的
containerView
似乎不会完全向后移动。(您可以在关闭in call状态栏后检查视图层次结构)

要解决此问题,您可以在演示时提供自定义演示控制器。然后,如果您不需要演示控制器的视图保留在视图层次结构中,您只需返回演示控制器的
true
for
shouldRemovePresenterView
属性即可

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
    }
}
或者,如果需要保留显示控制器的视图,则可以观察状态栏帧的变化,并手动调整
containerView
使其与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
            })
        }
    }
}
类PresentationController:UIPresentationController{
重写初始化(presentedViewController:UIViewController,presentingViewController:UIViewController?){
super.init(presentedViewController:presentedViewController,presenting:presentingViewController)
NotificationCenter.default.addObserver(self,
选择器:#选择器(self.onStatusBarChanged),
名称:.UIApplicationWillChangeStatusBarFrame,
对象:无)
}
@objc func onStatusBarChanged(注:NSNotification){
//我找不到办法向系统询问这些常数的值,也许你可以

如果UIApplication.shared.statusBarFrame.height我一直在寻找这个问题的解决方案。事实上,我发布了一个与此类似的新问题。这里:

相信我,我已经解决这个问题好几天了,由于iOS的状态栏在通话、热点和位置上的变化,你的屏幕被弄乱了,这真的很烦人

我已经尝试过实现莫迪的答案,我把这段代码放在AppDelegate中,并对其进行了一些修改,但运气不好。我相信iOS会自动实现这一点,所以你不必自己实现

在我发现问题的原因之前,我尝试了这个特定问题的所有解决方案。无需实现AppDelegate的方法
willChangeStatusBar…
或添加通知来观察状态栏的更改

我还通过编程方式重做了一些屏幕(我使用的是故事板),重做了我项目的一些流程。我做了一些实验,然后检查了我以前和当前的其他项目,为什么他们能正确地进行调整:)

底线是:我用UITabBarController以错误的方式显示我的主屏幕

请始终注意
modalPresentationStyle
。由于Noah的评论,我想查看我的代码

样本:

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)
    }
}

我已经找了3天的解决方案。我不喜欢这个解决方案,但没有找到更好的方法来解决它

当rootViewController视图的高度比window高20点时,当我收到状态栏高度更新的通知时,我手动设置正确的值

将方法添加到AppDelegate.sw
func application(_ application: UIApplication, didChangeStatusBarFrame oldStatusBarFrame: CGRect) {
        if let window = application.keyWindow {
            window.rootViewController?.view.frame = window.frame
        }
    }
tabBar.autoresizingMask = (UIViewAutoResizingFlexibleWidth | UIViewAutoResizingFlexibleTopMargin);
self.tabBarController?.tabBar.autoresizingMask = 
  UIViewAutoresizing(rawValue: UIViewAutoresizing.RawValue(UInt8(UIViewAutoresizing.flexibleWidth.rawValue) | UInt8(UIViewAutoresizing.flexibleTopMargin.rawValue)))`
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    let f = self.view.frame

    if f.origin.y != 0 {
        self.view.frame = CGRect(x: f.origin.x, y: 0, width: f.width, height: f.height)
        self.view.layoutIfNeeded()
        self.view.updateConstraintsIfNeeded()
    }
}