子视图控制器中的topLayoutGuide

2020/11/25 18:32 · ios ·  · 0评论

我有一个UIPageViewController带有半透明状态栏和导航栏。topLayoutGuide如预期的那样,是64像素。

但是,即使子视图控制器显示在状态栏和导航栏下,它们的子视图控制器也会UIPageViewController报告topLayoutGuide0像素。

这是预期的行为吗?如果是这样,将子视图控制器的视图放置在real下的最佳方法是topLayoutGuide什么?

(没有使用parentViewController.topLayoutGuide,我认为这是一个hack)

尽管这个答案可能是正确的,但我仍然发现自己必须向上移动包含树以找到正确的父视图控制器并获得您所描述的“真实topLayoutGuide”。这样我可以手动实现automaticallyAdjustsScrollViewInsets

这就是我的做法:

在我的表视图控制器(UIViewController实际上是其子类)中,我有以下内容:

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    _tableView.frame = self.view.bounds;

    const UIEdgeInsets insets = (self.automaticallyAdjustsScrollViewInsets) ? UIEdgeInsetsMake(self.ms_navigationBarTopLayoutGuide.length,
                                                                                               0.0,
                                                                                               self.ms_navigationBarBottomLayoutGuide.length,
                                                                                               0.0) : UIEdgeInsetsZero;
    _tableView.contentInset = _tableView.scrollIndicatorInsets = insets;
}

请注意中的category方法UIViewController,这是我实现它们的方式:

@implementation UIViewController (MSLayoutSupport)

- (id<UILayoutSupport>)ms_navigationBarTopLayoutGuide {
    if (self.parentViewController &&
        ![self.parentViewController isKindOfClass:UINavigationController.class]) {
        return self.parentViewController.ms_navigationBarTopLayoutGuide;
    } else {
        return self.topLayoutGuide;
    }
}

- (id<UILayoutSupport>)ms_navigationBarBottomLayoutGuide {
    if (self.parentViewController &&
        ![self.parentViewController isKindOfClass:UINavigationController.class]) {
        return self.parentViewController.ms_navigationBarBottomLayoutGuide;
    } else {
        return self.bottomLayoutGuide;
    }
}

@end

希望这可以帮助 :)

我可能是错的,但我认为这种行为是正确的。容器视图控制器可以使用topLayout值来布局其视图的子视图。

参考资料说:

要在不使用约束的情况下使用顶部布局参考线,请获取该参考线相对于包含视图的顶部边界的位置

在父级中,相对于包含视图,该值为64。

在子级中,相对于包含视图(父级),该值为0。

在容器View Controller中,您可以通过以下方式使用属性:

- (void) viewWillLayoutSubviews {

    CGRect viewBounds = self.view.bounds;
    CGFloat topBarOffset = self.topLayoutGuide.length;

    for (UIView *view in [self.view subviews]){
        view.frame = CGRectMake(viewBounds.origin.x, viewBounds.origin.y+topBarOffset, viewBounds.size.width, viewBounds.size.height-topBarOffset);
    }
}

子视图控制器不需要知道有导航栏和状态栏:考虑到它的父视图,子视图控制器已经布局好了子视图。

如果我创建一个基于页面的新项目,将其嵌入到导航控制器中,然后将此代码添加到父视图控制器中,则看起来工作正常:

在此处输入图片说明

您可以在情节提要中添加约束,并在viewWillLayoutSubviews中进行更改

像这样的东西:

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    self.topGuideConstraint.constant = [self.parentViewController.topLayoutGuide length];
}

该文档说,如果使用UIViewController子类,则在viewDidLayoutSubviews中使用topLayoutGuide;如果使用UIView子类,则在layoutSubviews中使用。

如果在这些方法中使用它,则应该获得适当的非零值。

文档链接:https :
//developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instp/UIViewController/topLayoutGuide

如果您有UIPageViewController像OP这样的功能,并且您有例如集合视图控制器作为子级。事实证明,内容插入的修复很简单,并且可以在iOS 8上运行:

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    UIEdgeInsets insets = self.collectionView.contentInset;
    insets.top = self.parentViewController.topLayoutGuide.length;
    self.collectionView.contentInset = insets;
    self.collectionView.scrollIndicatorInsets = insets;
}

这已在iOS 8中解决。

如何为子视图控制器设置topLayoutGuide位置

本质上,容器视图控制器应该(top|bottom|left|right)LayoutGuide像其他任何视图一样约束子视图控制器(在iOS 7中,它已经完全按照所需的优先级进行了约束,因此无法正常工作。)

我认为这些指南绝对是为嵌套子控制器设置的。例如,假设您有:

  • 100x50的屏幕,顶部有20像素状态栏。
  • 覆盖整个窗口的顶级视图控制器。其topLayoutGuide为20。
  • 顶视图内的嵌套视图控制器覆盖底部95个像素,例如。从屏幕顶部向下5个像素。此视图的topLayoutGuide应该为15,因为状态栏覆盖了它的前15个像素。

那将是有道理的:这意味着嵌套视图控制器可以设置约束以防止不必要的重叠,就像顶级控制器一样。不必担心它是嵌套的,也不用担心它的父对象在屏幕上的显示位置,并且父视图控制器不需要知道孩子如何与状态栏进行交互。

这似乎也是文档(或至少某些文档)所说的:

顶部布局指南以点为单位指示视图控制器视图的顶部与覆盖该视图的最底部栏的底部之间的距离(以磅为单位)

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UILayoutSupport_Protocol/Reference/Reference.html

但这并没有说明仅适用于顶级视图控制器。

但是,我不知道这是否真的发生。我肯定已经看到了非零topLayoutGuides的子视图控制器,但是我仍然在弄怪。(在我的情况下,最高指南应该为零,因为视图不在屏幕顶部,这就是我目前正在用头顶撞的地方……)

这是已知导向长度的方法。创建约束,而不是对辅助线,而是使用固定常数(假定辅助线距离将是)来约束视图的顶部。

@NachoSoto的快速实现答案:

extension UIViewController {

    func navigationBarTopLayoutGuide() -> UILayoutSupport {
        if let parentViewController = self.parentViewController {
            if !parentViewController.isKindOfClass(UINavigationController) {
                return parentViewController.navigationBarTopLayoutGuide()
            }
        }

        return self.topLayoutGuide
    }

    func navigationBarBottomLayoutGuide() -> UILayoutSupport {
        if let parentViewController = self.parentViewController {
            if !parentViewController.isKindOfClass(UINavigationController) {
                return parentViewController.navigationBarBottomLayoutGuide()
            }
        }

        return self.bottomLayoutGuide
    }
}

就像我几分钟前一样,不确定是否有人仍然对此有疑问。

我的问题是
这样的(来自https://knuspermagier.de/2014-fixing-uipageviewcontrollers-top-layout-guide-problems.html的gif源)。

简而言之,我的pageViewController有3个子ViewController。第一个viewcontroller很好,但是当我滑动到下一个时,整个视图会错误地偏移到顶部(我猜是20像素左右),但是当手指离开屏幕时它将恢复正常。

我整夜熬夜寻找解决方案,但是仍然找不到运气。然后突然我想到了这个疯狂的主意:

[pageViewController setViewControllers:@[listViewControllers[1]] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:^(BOOL finished) {

}];

[pageViewController setViewControllers:@[listViewControllers[0]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished) {

}];

我的listViewControllers有3个子ViewController。索引0处的那个有问题,因此我首先将其设置为pageviewcontroller的根,然后立即将其设置回第一个视图控制器(正如我预期的那样)。瞧,行得通!

希望能帮助到你!

这是一种不幸的行为,似乎已在iOS 11中通过安全区域API改正得到纠正。也就是说,您将始终从根视图控制器获得正确的值。例如,如果要在iOS 11之前的安全区域上限高度:

斯威夫特4

let root = UIApplication.shared.keyWindow!.rootViewController!
let topLayoutGuideLength = root.topLayoutGuide.length
本文地址:http://ios.askforanswer.com/zishitukongzhiqizhongdetoplayoutguide.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!