解释iOS7中自动调整滚动视图集,extendedLayoutIncludesOpaqueBars,edgesForExtendedLayout之间的区别

我一直在阅读很多关于iOS7 UI转换。

我无法automaticallyAdjustsScrollViewInsets获得这三个属性edgesForExtendedLayoutextendedLayoutIncludesOpaqueBarsedgesForExtendedLayout ??

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

从iOS7开始,视图控制器默认使用全屏布局。 与此同时,您对于如何阐述自己的观点拥有更多的控制权,并且这些属性已经完成:

edgesForExtendedLayout

基本上,通过此属性,您可以设置视图的哪一侧可以覆盖整个屏幕。 想象一下,你推UIViewController到一个UINavigationController 。 当该视图控制器的视图被布置时,它将在导航栏结束的位置开始,但是该属性将设置视图的哪一侧(顶部,左侧,底部,右侧)可以被扩展以填充整个屏幕。

让我们看一个例子:

 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设置,视图正好在导航下

automaticallyAdjustsScrollViewInsets

当你的视图是一个UIScrollView或类似的UITableView时,这个属性被使用。 你希望你的桌子在导航栏结束的时候开始,因为如果没有,你不会看到整个内容,但同时你希望你的桌子在滚动时覆盖整个屏幕。 在这种情况下,将edgesForExtendedLayout设置为None将不起作用,因为您的表格将在导航栏结束处开始滚动,并且不会在其后面移动。

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

这是什么时候设置为NO:

桌子将在整个屏幕上滚动,但开始部分覆盖

和YES(默认):

表格在整个屏幕上滚动,并在导航下开始

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

extendedLayoutIncludesOpaqueBars

这个值只是以前的值。 默认情况下,该参数设置为NO。 如果状态栏是不透明的,即使扩展视图来覆盖视图( edgesForExtendedLayoutUIRectEdgeAll ),视图也不会扩展到包含状态栏。

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

如果有什么不清楚的地方,写一个评论,我会回答。

iOS如何知道使用什么UIScrollView?

iOS抓取ViewController视图中的第一个子视图,索引为0的视图,如果它是UIScrollView的子类,则将解释的属性应用于该视图。

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

不知道你是否使用故事板,但如果你是,让你的视图控制器在状态栏下方(和底部栏上方)开始:

在IB中select视图控制器,在属性检查器中,取消select“延伸边缘 – 顶部条”和“延伸边 – 底部条”。

我正在使用故事板,并使用上述build议工作,但我不完全确定如何实现它。 下面是一个简单的示例,它是如何通过将推荐的解决scheme放入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默认导致故事板devise和模拟器之间的差异 “自动调整”默认设置为true,导致故事板设计和模拟器之间存在差异

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

我通过添加这一行来解决这个问题,但是我的问题与UIView相关,而不是UIScrollView

 self.navigationController.navigationBar.translucent = NO; 

请记住,只有某种滚动视图(表视图,集合视图…)是automaticallyAdjustsScrollViewInsets滚动视图集属性

  • VC的观点,还是
  • 这个观点的第一个子视图

其他人build议,即使它是第一个子视图,它仍然工作,但在视图层次结构中还有其他滚动视图。

编辑(扩展DIY)

如果即使不能满足这些条件(例如,在滚动视图下方有一个背景图像),也需要类似的行为,可以手动调整滚动视图的插图。 但是请不要把它设置成像44或64甚至20那样不变,就像许多人所说的那样。 你永远无法知道尺寸。 可以有incall / gps / audio通知,导航栏不一定总是44点等

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

 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() scrollView.contentInset = UIEdgeInsets(top: topLayoutGuide.length, left: 0, bottom: 0, right: 0) scrollView.scrollIndicatorInsets = scrollView.contentInset } 

你可以用同样的方式使用bottomLayoutGuide。