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

时间:2013-09-14 05:52:48

标签: ios objective-c xcode uiviewcontroller ios7

我一直在阅读有关iOS7 UI过渡的很多内容。

我无法获得这三个属性automaticallyAdjustsScrollViewInsetsextendedLayoutIncludesOpaqueBarsedgesForExtendedLayout ??

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

5 个答案:

答案 0 :(得分:600)

从iOS7开始,视图控制器默认使用全屏布局。与此同时,您可以更好地控制它的视图布局,并使用这些属性完成:

<强> edgesForExtendedLayout

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

让我们看一个例子:

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

此处您没有设置edgesForExtendedLayout的值,因此默认值为UIRectEdgeAll),因此视图会扩展其布局以填充整个屏幕。

结果如下:

without edges for extended layout, the view fills the whole screen

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

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

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

结果:

with edgesForExtendedLayout set, the view is just under the navigation

<强> automaticallyAdjustsScrollViewInsets

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

这里是这个属性派上用场的地方,如果让视图控制器自动调整insets(将此属性设置为YES,也是默认值),它会将insets添加到表的顶部,这样表就会启动导航栏结束的位置,但滚动将覆盖整个屏幕。

这是设置为NO时的时间:

the table will scroll over the whole screen, but starts out partially covered

和(默认情况下):

the table scrolls over the whole screen, and starts just under the navigation

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

<强> extendedLayoutIncludesOpaqueBars

这个值只是对以前的值的补充。默认情况下,此参数设置为NO。如果状态栏不透明,则视图不会扩展为包含状态栏,即使您将视图扩展为覆盖它(edgesForExtendedLayoutUIRectEdgeAll)。

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

如果问题不明确,请写一条评论,我会回答。

iOS如何知道要使用的UIScrollView?

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

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

答案 1 :(得分:15)

不确定您是否正在使用故事板,但如果您正在使用,请使视图控制器从状态栏下方(并在底部栏上方)开始:

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

答案 2 :(得分: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会导致故事板设计和模拟器之间出现差异 Auto Adjust set to true by default causing a difference between storyboard design and simulator

解决: 上面的代码适用,关闭自动调整。 Code above applied, turning off the auto-adjust.

答案 3 :(得分:5)

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

self.navigationController.navigationBar.translucent = NO;

答案 4 :(得分:2)

请记住这一点 automaticallyAdjustsScrollViewInsets 仅当某种滚动视图(表视图,集合视图,...)是

时,属性才有效
  • VC的观点,或
  • 此观点的第一个子视图

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

编辑(扩展DIY)

如果您想要类似的行为,即使您无法满足这些条件(例如,滚动视图下方有背景图像),您也可以手动调整滚动视图插图。但请不要把它设置为常数,如44或64甚至20,就像很多人建议的那样。你无法知道大小。可以有incall / gps / audio通知,导航栏不一定总是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。