查找不被 UINavigationBar、UITabBar 等遮挡的 UIViewController 视图的边界

Posted

技术标签:

【中文标题】查找不被 UINavigationBar、UITabBar 等遮挡的 UIViewController 视图的边界【英文标题】:Find bounds of UIViewController's view not obscured by UINavigationBar, UITabBar, (etc) 【发布时间】:2015-01-01 21:02:46 【问题描述】:

我可以配置我的UIViewControlleredgesForExtendedLayout,使其在导航栏或标签栏等内容下方延伸。如果我这样做,有什么方法可以确定没有被遮挡的框架

作为一种可能的替代方法,UIViewController 是否可以确定默认 contentInset 以应用于它包含的 UIScrollView

用例

我有一个包含图像的可缩放 UIScrollView。

当它完全缩小时,我想调整内容插图也让内容保持居中 (details here)。但是,我修改后的插图没有考虑到 UIViewController 自动应用的插图,因此其内容不会被导航栏等遮挡。

我还需要计算内容的最小缩放 - 整个图像将可见且不会被遮挡。为了计算这个,我需要知道内容视图中未被遮挡的部分的大小。

【问题讨论】:

【参考方案1】:

你需要这个

-(CGRect) unobscuredBounds

    CGRect bounds = [self.view bounds];
    return UIEdgeInsetsInsetRect(bounds, [self defaultContentInsets]);


-(UIEdgeInsets) defaultContentInsets

    const CGFloat topOverlay = self.topLayoutGuide.length;
    const CGFloat bottomOverlay = self.bottomLayoutGuide.length;
    return UIEdgeInsetsMake(topOverlay, 0, bottomOverlay, 0);

您可以将其放在category 中以便于重用。

这些方法正确处理视图在旋转后调整大小时发生的变化——UINavigationBar 大小的变化得到正确处理。

内容居中

要将其用于centre content by adjusting insets,您需要执行以下操作:

-(void) scrollViewDidZoom:(UIScrollView *)scrollView

    [self centerContent];


- (void)centerContent

    const CGSize contentSize = self.scrollView.contentSize;
    const CGSize unobscuredBounds = [self unobscuredBounds].size;

    const CGFloat left = MAX(0, (unobscuredBounds.width - contentSize.width)) * 0.5f;
    const CGFloat top = MAX(0, (unobscuredBounds.height - contentSize.height)) * 0.5f;

    self.scrollView.contentInset = UIEdgeInsetsMake(top, left, top, left);

您的内容插图现在将反映他们需要的默认插图(以避免被掩盖),并且还将具有他们需要很好地居中的插图。

处理旋转和缩放

您可能还希望在横向和纵向之间设置动画时执行居中。同时,您可能需要调整最小缩放比例,以便您的内容始终适合。试试这样的:

-(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

    [self centerContent];

    const bool zoomIsAtMinimum = self.scrollView.zoomScale == self.scrollView.minimumZoomScale;

    self.scrollView.minimumZoomScale = [self currentMinimumScale];
    
    if(zoomIsAtMinimum)
    
        self.scrollView.zoomScale = self.scrollView.minimumZoomScale;
    


-(CGFloat) currentMinimumScale

    const CGFloat currentScale = self.scrollView.zoomScale;
    const CGSize scaledContentSize = self.scrollView.contentSize;
    const CGSize scrollViewSize = [self unobscuredBounds].size;

    CGFloat scaleToFitWidth = currentScale * scrollViewSize.width / scaledContentSize.width;
    CGFloat scaleToFitHeight = currentScale * scrollViewSize.height / scaledContentSize.height;

    return MIN(scaleToFitWidth, scaleToFitHeight);

willAnimateRotationToInterfaceOrientation:… 方法在视图动画块中被调用,因此当您从横向切换到纵向时,它所应用的更改将导致平滑的动画更改。

【讨论】:

以上是关于查找不被 UINavigationBar、UITabBar 等遮挡的 UIViewController 视图的边界的主要内容,如果未能解决你的问题,请参考以下文章

自动调整导航栏标题放错位置

UINavigationBar titleview 图像未与 UINavigationBar 对齐

由于奇怪的 UINavigationBar 视图层次结构,自定义 UINavigationBar 不起作用

UINavigationBar

UITableView 滚动 UINavigationBar

UINavigationBar 一个有样式的view