解释iOS7中的AutomaticAdjustsScrollViewInsets,extendedLayoutIncludesOpaqueBars,edgesForExtendedLayout之间的区别


250

我已经阅读了很多有关iOS7 UI过渡的文章。

我不能够得到什么这三个属性automaticallyAdjustsScrollViewInsetsextendedLayoutIncludesOpaqueBarsedgesForExtendedLayout

例如,我试图使我的视图控制器在状态栏下方启动,但我无法实现。


5
问题是为什么它没有按预期的那样工作,因为我不太了解它!..这就是原因
user1010819 2013年

1
哦,我误会了你在那说的话。我并不想听起来很光顾,只是当有些人问这样的问题并且是新来的站点时,他们错过了显而易见的解决方案。
erdekhayser 2013年

8
在您的viewDidLoad方法中,添加if([[self responsesToSelector:@selector(edgesForExtendedLayout)])self.edgesForExtendedLayout = UIRectEdgeNone; 这将迫使您的视图从状态栏下方开始。
Nandha

Answers:


629

从iOS7开始,视图控制器默认使用全屏布局。同时,您可以更好地控制其布局视图的方式,并且可以通过以下属性来实现:

edgeForExtendedLayout

基本上,使用此属性可以设置可以扩展视图的哪一部分以覆盖整个屏幕。想象一下,您将a推UIViewControllerUINavigationController。当布局该视图控制器的视图时,它将在导航栏结束的地方开始,但是此属性将设置可以扩展视图的哪一侧(顶部,左侧,底部,右侧)以填充整个屏幕。

让我们看一个例子:

UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.backgroundColor = [UIColor redColor];
UINavigationController *mainNavigationController = [[UINavigationController alloc] initWithRootViewController:viewController];

在这里,您未设置的值edgesForExtendedLayout,因此采用默认值(UIRectEdgeAll),因此视图将扩展其布局以填充整个屏幕。

结果如下:

没有用于扩展布局的边缘,视图占据了整个屏幕

如您所见,红色背景在导航栏和状态栏的后面延伸。

现在,您要将该值设置为UIRectEdgeNone,这样就告诉视图控制器不要将视图扩展为覆盖屏幕:

UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.backgroundColor = [UIColor redColor];
viewController.edgesForExtendedLayout = UIRectEdgeNone;
UINavigationController *mainNavigationController = [[UINavigationController alloc] initWithRootViewController:viewController];

结果:

设置了edgesForExtendedLayout后,视图就位于导航下方


自动调整ScrollViewInsets

当视图为UIScrollView或类似视图(例如)时,将使用此属性UITableView。您希望表格从导航栏结束处开始,因为如果没有,您将看不到整个内容,但是同时您希望表格在滚动时覆盖整个屏幕。在这种情况下,设置edgesForExtendedLayout为“无”将不起作用,因为您的表格将在滚动条结束处开始滚动并且不会在表格后面滚动。

这是此属性派上用场的地方,如果让视图控制器自动调整插图(将此属性设置为YES,也是默认值),它将在表格顶部添加插图,因此表格将在导航位置开始条结束,但滚动条将覆盖整个屏幕。

这是设置为“否”的时间:

该表格将在整个屏幕上滚动,但一开始会被部分覆盖

和是(默认情况下):

该表格将滚动到整个屏幕,并从导航下方开始

在这两种情况下,表格都在导航栏后面滚动,但在第二种情况下(YES),它将从导航栏下面开始。


extendedLayoutIncludesOpaqueBars

该值只是先前值的附加值。默认情况下,此参数设置为NO。如果状态栏是不透明的,该意见将不会被扩展到包括状态栏,即使您扩展视图来覆盖它(edgesForExtendedLayoutUIRectEdgeAll)。

如果将值设置为YES,这将允许视图再次进入状态栏下方。

如果不清楚,请写评论,我会回答。

iOS如何知道要使用的UIScrollView?

iOS会在ViewController的视图中获取第一个子视图,该子视图位于索引0处,如果它是的子类,UIScrollView则将说明的属性应用于它。

当然,这意味着UITableViewController默认情况下可以工作(因为UITableView是第一个视图)。


仅在显示默认导航栏时才需要设置此属性,而在其自定义导航栏时才需要设置此属性,对吗?
Hemang

1
否,如果您使用iOS导航栏,但您有自己的设计,则需要使用相同的属性。如果只是从头开始创建导航栏,则这些属性将不起作用。
Antonio MG

我不明白为什么在整个视图上都有一个小的黑色层?请帮忙?:/
aZtraL-EnForceR 2013年

24
此说明比《 iOS 7 UI过渡指南》更好。这应该只是替换指南,对我而言这毫无意义。
2014年

2
我认为,extendedLayoutIncludesOpaqueBars默认情况下应为YES而不是NO。更改视图颜色(半透明)不应影响布局。
弗拉基米尔·斯拉维克

15

不确定是否使用情节提要,但如果要使用情节提要,请确保状态控制器在状态栏下方(和底部栏上方)启动:

在IB中选择视图控制器,在属性检查器中,取消选择“延伸边缘-顶部栏下方”和“延伸边缘-底部栏下方”。


好。然后,我认为Nandha上面建议的内容将以编程方式实现相同的结果。如果在viewDidLoad下不起作用,则可能需要将其移至viewDidLayoutSubviews。
Ali Beadle13年

指示扩展的布局是否包括不透明的条。@property(非原子,分配)BOOL extendedLayoutIncludesOpaqueBars讨论默认值为NO。
阿卜杜勒·雅辛

+1,您给了我一个提示,请您检查故事板。我解决了我一半的问题。
selva 2014年

10

我正在使用情节提要,并使用上述建议有效,但是我不确定如何实现它。下面是一个简短的示例,它通过将推荐的解决方案放入ViewController中来迅速解决了问题。

import Foundation
import UIKit

// This ViewController is connected to a view on a storyboard that 
// has a scrolling sub view.
class TheViewController: UIViewController {

  // Prepares the view prior to loading.  Putting it in viewDidAppear didn't work.
  override func viewWillAppear(animated: Bool) {

    // this method is an extension of the UIViewController 
    // so using self works as you might expect.
    self.automaticallyAdjustsScrollViewInsets = false

    // Default is "true" so this sets it to false tells it to use 
    // the storyboard as you have it placed
    // and not how it thinks it should place it.
  }

}

我的问题:默认情况下,“自动调整”设置为true,导致情节提要和模拟器之间存在差异 默认情况下,“自动调整”设置为true,导致情节提要设计和模拟器之间存在差异

解决:应用以上代码,关闭自动调整功能。 应用上面的代码,关闭自动调整功能。


5
如果将autoAdjustsScrollViewInsets设置为YES,则应将顶部约束设置为superview而不是topGuideLayout。
xmkevinchen 2015年

5

我通过添加此行解决了此问题,但我的问题与而UIView不是UIScrollView

self.navigationController.navigationBar.translucent = NO;

2

只需记住, automaticallyAdjustsScrollViewInsets 仅当某种滚动视图(表视图,集合视图等)是

  • VC的视图,或
  • 此视图的第一个子视图

其他建议,即使它是第一个子视图也不起作用,但是视图层次结构中还有其他滚动视图。

编辑(扩展名DIY)

如果即使您不满足这些条件,也想要类似的行为(例如,滚动视图下方有背景图像),则可以手动调整滚动视图插图。但是请不要将其设置为常数,例如44或64,甚至不要像许多SO建议的那样设置为20。您永远都不知道大小。可以有incall / gps / audio通知,导航栏不一定总是44 pts等。

我认为最好的解决方案是在didLayoutSubviews length中使用layoutGuide:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    scrollView.contentInset = UIEdgeInsets(top: topLayoutGuide.length, left: 0, bottom: 0, right: 0)
    scrollView.scrollIndicatorInsets = scrollView.contentInset
}

您可以以相同方式使用bottomLayoutGuide。


显然,导航栏是半透明的。
Vojta Rujbr
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.