解释iOS7中automyadjustsscrollviewinsets, extendedlayoutinclesopaquebars, edgesForExtendedLayout之间的区别

我读了很多关于iOS7用户界面转换的文章。

我不能得到这三个属性automaticallyAdjustsScrollViewInsetsextendedLayoutIncludesOpaqueBarsedgesForExtendedLayout??

例如,我试图让我的视图控制器开始低于状态栏,但我无法实现它。

83946 次浏览

不确定你是否在使用故事板,但如果你是,让你的视图控制器从状态栏下面开始(并且在底部栏上面):

在IB中选择视图控制器, 在属性检查器中,取消选择“扩展边缘-顶部条下”和“扩展边缘-底部条下”

从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];

结果是:

with edgesForExtendedLayout set,视图就在导航 . quot


automaticallyAdjustsScrollViewInsets

当您的视图是UIScrollView或类似类型时,如UITableView,则使用此属性。你想让你的表格从导航栏结束的地方开始,因为如果不是,你不会看到整个内容,但同时你想让你的表格在滚动时覆盖整个屏幕。在这种情况下,将edgesForExtendedLayout设置为None将不起作用,因为您的表格将在导航栏结束的地方开始滚动,而不会转到导航栏后面。

这就是这个属性很方便的地方,如果你让视图控制器自动调整insets(设置这个属性为YES,也是默认值),它将添加insets到表的顶部,所以表将从导航栏结束的地方开始,但滚动将覆盖整个屏幕。

这是当设置为NO时:

表格将滚动整个屏幕,但开始部分覆盖

和YES(默认):

表格在整个屏幕上滚动,并在导航 . quot

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


extendedLayoutIncludesOpaqueBars

这个值只是对前一个值的补充。缺省情况下,该参数为NO。如果状态栏是不透明的,视图不会被扩展到包含状态栏,即使你扩展了视图来覆盖它(edgesForExtendedLayoutUIRectEdgeAll)。

如果您将该值设置为YES,这将允许视图再次转到状态栏下面。

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

iOS如何知道使用哪个UIScrollView ?

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

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

我使用故事板和使用上述建议工作,但我不确定如何实现它。下面是一个简短的例子,它是如何通过将建议的解决方案放入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.
}


}
< p >我的问题: 自动调整默认设置为true,导致故事板设计和模拟器之间的差异 自动调整设置为true默认导致故事板设计和模拟器之间的差异

< p >解决: 以上代码适用,关闭自动调整。 以上代码适用,关闭自动调整。 < / p >

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

self.navigationController.navigationBar.translucent = NO;
只要记住这一点 automaticallyAdjustsScrollViewInsets 只有当某种滚动视图(表视图,集合视图,…)为

时,属性才有效
  • VC的视图,或者
  • 该视图的第一个子视图

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

编辑(扩展DIY)

如果你想要类似的行为,即使你不能满足这些条件(例如,你有一个背景图像在滚动视图下方),你可以手动调整滚动视图嵌入。但请不要像许多人建议的那样,将它设置为44或64,甚至20。你永远不可能知道它的大小。可以有call/gps/音频通知,导航栏不需要总是44分等等。

我认为最好的解决方案是在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。