【问题标题】:ContentInset not updated when view is added as subviews将视图添加为子视图时 ContentInset 未更新
【发布时间】:2016-10-24 02:54:16
【问题描述】:

我正在制作一个照片浏览应用程序,用户可以从网络上查看正在查看的照片的详细信息和 cmets。为此,我有一个带有分段控件的 UIViewController (parentVC),用作细节和 cmets 之间的切换,以及两个提供细节和 cmets 的 UITableViewController。 Storyboard of the view controllers in question.

为了在视图之间切换,tableVCs 从 storyboard 实例化并作为 childViewController 添加到 parentVCs,并且它们的视图作为子视图添加。

由于segmentedControl 被放置在navigatorController 的navBar 中,我希望tableViews 也能与parentVC 的navBar 配合使用。其中当第一个 tableview (detailVC) 被实例化时,它的 contentInset 会自动调整。

但是,当从分段控件切换后实例化第二个 tableview (cmetsVC) 时,它的 contentInset 未设置(实际上所有边都为 0),并且 tableview 隐藏在导航栏后面。但是当设备旋转时,tableview 会调整其 insets 并再次正常工作。

现在我怀疑这个问题与 iOS 如何自动调整滚动视图插入有关,因为切换首先出现的 childVC 总是会设置第一个出现的 VC 的 contentInset。我不知道在添加第二个 VC 时是否可以触发任何方法来设置第二个 VC 的 contentInset。

所以问题是,我如何将两个 childVC 的 contentInset 设置为尊重 parentVC 中的导航栏?创建 UIEdgeInset 是一种解决方法,但它不会在设备方向更改时自行更新。一个更小的问题是,当 childVC 以编程方式实例化时,我应该如何处理导航控制器的布局和插图,以便它们像在故事板本身中链接一样工作。

以下是我从 parentVC 实例化 childVC 时的代码。

    if index == 0 { //details

        if detailsVC == nil {
            detailsVC = storyboard?.instantiateViewControllerWithIdentifier("InfoPaneDetailsVC") as! InfoPaneDetailsVC
        }
        if commentsVC != nil {
            commentsVC.view.removeFromSuperview()
            commentsVC.removeFromParentViewController()
        }

        addChildViewController(detailsVC)
        detailsVC.didMoveToParentViewController(self)
        view.addSubview(detailsVC.view)
        view.layoutSubviews()

    } else if index == 1 { //comments

        if commentsVC == nil {
            commentsVC = storyboard?.instantiateViewControllerWithIdentifier("InfoPaneCommentsVC") as! InfoPaneCommentsVC
        }
        if detailsVC != nil {
            detailsVC.view.removeFromSuperview()
            detailsVC.removeFromParentViewController()
        }

        addChildViewController(commentsVC)
        commentsVC.didMoveToParentViewController(self)
        view.addSubview(commentsVC.view)
        view.layoutSubviews()

    }

【问题讨论】:

    标签: swift uitableview layout uinavigationbar ios9


    【解决方案1】:

    tableview 隐藏在导航栏后面。但是当设备旋转时,tableview 会调整它的 insets 并且它 再次正常工作。

    我可以复制你所看到的。我不知道为什么旋转设备会摆脱underlap*。我什至可以横向启动应用程序,TableView 将覆盖 NavigationBar,然后当我旋转到纵向时,覆盖消失。

    一些解决方案对我有用:

    1. edgesForExtendedLayout = .None
    2. navigationController?.navigationBar.translucent = false

    如果 ViewController 的父级是 NavigationController(或 TabBarController),则有两个属性决定下重叠的工作方式:

    1. ViewController 的 edgesForExtendedLayout 属性。
    2. NavigationBar 的 translucent 属性。

    edgesForExtendedLayout 属性的默认值为.All,这意味着 ViewController 的视图将覆盖所有半透明条。

    你可以像这样检查你的 NavigationBar 是否是半透明的:

    import UIKit
    
    class InfoViewController: UIViewController {
    
         override func viewDidLoad() {
            super.viewDidLoad()
    
            if navigationController?.navigationBar.translucent == true {
                print("NavigationBar is translucent.")
            }
    
            if edgesForExtendedLayout == .All {
                print("This ViewController's view will underlap a translucent NavigationBar.")
            }
    

    我明白了:

    NavigationBar is translucent.
    This ViewController's view will underlap a translucent NavigationBar.
    

    UINavigationBar docssay**,

    此外,导航栏默认是半透明的。转动 半透明关闭或打开不会影响按钮,因为它们没有 背景。

    您可以像这样防止重叠:

    import UIKit
    
    class InfoViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            edgesForExtendedLayout = .None
        }
    

    .None 告诉 ViewController 的视图不要覆盖任何半透明条。或者,您可以使用.Bottom,这意味着视图只会覆盖半透明底栏,即不是半透明顶栏。 (要查看可以分配给edgesForExtendedLayout 的各种值或值组合,请查看docs)。

    或者,您可以像这样防止重叠:

    import UIKit
    
    class InfoViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            navigationController?.navigationBar.translucent = false
        }
    

    edgesForExtendedLayout 的值仅适用于半透明条 - 视图不会覆盖不透明条。如果您不想在代码中将 translucent 设置为 false,您可以在 storyboard 中选择 Navigation Bar,然后在 Attributes Inspector 中取消选中 Translucent。


    * 旋转设备后,我打印出edgesForExtendedLayout 和NavBar 的translucent 属性,它们没有改变:

    class InfoViewController: UIViewController {
    
        override func viewWillTransitionToSize(size: CGSize,
            withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
        {
            super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    
            //executes before transition
    
            coordinator.animateAlongsideTransition(//unlabeled first argument:
                { (UIViewControllerTransitionCoordinatorContext) -> Void in
                    //executes during transition
                },
                completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
                    //executes after transition
    
                    print("After rotating:")
                    if self.navigationController?.navigationBar.translucent == true {
                        print("NavigationBar is translucent.")
                    }
    
                    if self.edgesForExtendedLayout == .All {
                        print("This ViewController's view will underlap a translucent NavigationBar.")
                    }
    
                }
            )
        }
    
    --output:--
    NavigationBar is translucent.
    This ViewController's view will underlap a translucent NavigationBar.
    After rotating:
    NavigationBar is translucent.
    This ViewController's view will underlap a translucent NavigationBar.
    

    ** 如果 NavigationBar 有背景图像,则 NavigationBar 的 translucent 属性的值将根据图像的 alpha 设置为 true 或 false。请参阅UINavigationBar docs 中的Translucency 部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-25
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多