Interface Builder:UIView 的 Layout iOS 6/7 Delta 有啥用?

Posted

技术标签:

【中文标题】Interface Builder:UIView 的 Layout iOS 6/7 Delta 有啥用?【英文标题】:Interface Builder: What are the UIView's Layout iOS 6/7 Deltas for?Interface Builder:UIView 的 Layout iOS 6/7 Delta 有什么用? 【发布时间】:2013-07-22 17:46:33 【问题描述】:

我刚刚注意到 UIView 的结构布局下的 ios 6/7 Delta 属性。

这是做什么用的,为什么 AutoLayout 中缺少它?

【问题讨论】:

【参考方案1】:

注意:我不久前注意到了这个问题,但我现在才发布我的答案,因为 NDA 已被取消

为什么 AutoLayout 不显示?

您可能已经注意到,iOS 7 带来了全新的外观。 UI 元素的外观发生了变化,但它们的一些大小(或一般指标)也发生了变化。这会使同时适应 iOS 7 和它的前辈的界面设计有点痛苦。

Apple 的官方说法是使用 AutoLayout 来解决这个问题;这应该可以省去为您布置 UI 元素的麻烦。有时很难做到这一点,特别是如果您出于业务原因仍必须支持 iOS 5,或者您的界面以一种难以实现 AutoLayout 的方式进行管理。因此,如果你属于这个利基类别,Apple 似乎提供了一种让你的工作更轻松的方法,他们称之为 iOS 6/7 Deltas。

好的,那它有什么作用呢?

虽然 Interface Builder 中的标签对于“Delta”在此上下文中的含义有些不清楚,但与此功能对应的 .xib 文件中包含的代码更加清晰:

<inset key="insetFor6xAndEarlier" minX="-50" minY="-100" maxX="-50" maxY="300"/>

键名insetFor6xAndEarlier 明确说明了它的作用;在 iOS 7 的前辈上运行时,您可以为 UI 元素提供替代插图。例如,上面定义了以下增量变化:

x: 50
y: 100
width: -100
height: 200

虽然 .xib 中存储的值与引用的值不直接对应,但它们之间存在相关性。

x: -minX
y: -minY
width: minX + maxX
height: minY + maxY

下图直观地展示了这一变化。这是一个相当极端的例子,但它是为了展示它的能力。我只希望在实践中只有几个像素的增量变化。

您可能会注意到这些值与 iOS 6 视图相反;这是因为增量与您正在使用的视图类型相关。如果您正在为 iOS 6 进行编辑,则存在的增量是为了为 iOS 7 正确转换元素(与上面的示例相反)。

为了查看不同的样式,您可以根据运行的操作系统更改 Interface Builder 呈现它的方式。这包含在 File Inspector->Interface Builder Document(右侧栏的第一个选项卡)中,如下所示:

如果我喜欢手动编写界面,这是否存在?

不是直接的,但您可以通过在代码中对操作系统版本进行条件检查并相应地设置正确的位置/大小来轻松实现相同的效果。 Interface Builder 中存在 delta 功能,因为没有代码就没有直接的方法来进行条件定位,而 Interface Builder 的重点是尽可能多地为 UI 消除代码。

总体...

Apple 强烈建议您使用 AutoLayout,它在大多数情况下会让您的生活更轻松。如果您不能使用它(由于上述原因),增量为您提供了根据当前操作系统的指标适当地定位 UI 元素的灵活性,而无需在代码中手动重新定位它们。一个很好的例子是调整缺少状态栏,但还有很多其他用例。

当然,如果你只是为 iOS7 及以上开发,你不需要知道这个功能/不会发现它。只有当您需要在使用 iOS7 SDK 构建且没有自动布局的情况下让 iOS6 设备运行您的应用程序时,您才需要增量。

在撰写本文时(8 月 21 日),我找不到有关此功能的任何文档,也找不到 WWDC 材料中的任何提及。我玩过,经过一番研究,这就是我的发现。

【讨论】:

非常感谢WDUK 目前没有房产,这就是我需要知道的【参考方案2】:

这实际上是指从iOS6到iOS7的布局位置之间的Delta。

在 iOS7 中,某些视图可以隐藏状态栏或使其透明,实际上,它覆盖在您的视图之上。因此,如果您在 iOS6 上将 UI 元素放在 (0.0, 0.0) 处,它将出现在状态栏下方,但在 iOS7 上,它会部分显示在状态栏下方。因此,在这种情况下,您需要一个与状态栏高度(20.0 点)匹配的增量,以便布局在 iOS6 和 iOS7 中看起来相同。

如果您使用自动布局,我相信这不是必需的,但是当然,您会失去对 iPad1 的支持,我们中的许多人目前都不愿意承认这一点。

【讨论】:

对我来说,我发现它是从 iOS 7 到 iOS 6 的增量。我将元素降低了 20 个点,然后为 Delta Y 设置了 -20。 这对于 UIProgressView 尤其有用,它在 iOS 7 中更纤薄【参考方案3】:

我知道这个问题已经得到解答,只是添加了一个小变体,希望它也可以帮助那些不使用自动布局但仍希望支持 iOS 6.1 及更早版本的人。

阅读此Apple's Transition Guide - Supporting earlier version

选择“查看方式”为“iOS 7.0 及更高版本”

iOS 7 的基本 UI。对于 iOS 6,请提供合适的 delta 值。使用预览查看这将如何在 iOS 7 和 iOS 6 设备中呈现。

快速步骤:

分别选择根视图的每个直接子视图,并将 20px 添加到其“Y”值。

然后,集体选择所有直系子代,并将 delta Y 设为 -20px。您也可以批量或单独执行此操作。

【讨论】:

【参考方案4】:

AutoLayout 至少需要 iOS 6.0。如果你想支持 iOS 5.0,你就不能使用 AutoLayout。

这些增量用于帮助您在不同的 iOS 版本(主要是 iOS 7 和低于 7 的 iOS 版本)上调整视图位置。

我使用这些价值来帮助我喜欢这张照片。

【讨论】:

当我改变这些时,什么都没有发生,是否涉及另一个步骤? @RecycledSteel 在这里查看我的答案:link【参考方案5】:

要查看 iOS 6/7 Delta 的实际效果,我将使用在 iOS 6 和 iOS 7 设备上都正确显示的 SegmentedControl 进行演示。

首先,在 Storyboard 中选择您的 .Xib 或 ViewController。取消选中Use Autolayout并选择“View as iOS 7 and later

在 Interface Builder 画布中,放置 SegmentedControl,使其 origin.y 为 20。在 iOS 6/7 Delta 中,为 DeltaY 选择 -20

这将使您的 SegmentedControl 位于 iOS 6 和 iOS 7 设备的状态栏下方

来自Developer’s Guide to the iOS 7 Status Bar的另一个有用的报价

可以为每个视图单独设置增量并按您的方式工作 预计。如果您的情节提要或笔尖设置为以 iOS 6 方式查看,则 设置增量将导致该视图被移动和/或调整大小 在 iOS 7 中运行时按设置的增量量。或者,如果您的 故事板或笔尖设置为在 iOS 7 中查看,那么增量将是 在 iOS 6 中运行时应用

【讨论】:

【参考方案6】:

如果您使用的是 AutoLayout,则 Delta 不可用。 试试这个(在运行 iOS6 的 iPhone 4s 上测试):

- (void) viewWillLayoutSubviews 

//iOS 6 workaround offset
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7) 

    self.view.clipsToBounds = YES;
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGFloat screenHeight = 0.0;
    screenHeight = screenRect.size.width;
    CGRect screenFrame = CGRectMake(0, -20, self.view.frame.size.width,self.view.frame.size.height+10);

    self.view.frame = screenFrame;


【讨论】:

以上是关于Interface Builder:UIView 的 Layout iOS 6/7 Delta 有啥用?的主要内容,如果未能解决你的问题,请参考以下文章

通过 Interface Builder 更改 UIView 属性

Interface Builder:为啥我的 UIView 是透明的?

在 Interface Builder 中构建 UIView

在 Interface Builder 中更新 UIView 类

来自 Interface Builder 的自定义 UIView

UIView 转换仅在 UIView 是通过 Interface Builder 创建时才有效