【问题标题】:iOS Autolayout - How to set two different distances between views, depends on the screen heightiOS Autolayout - 如何在视图之间设置两个不同的距离,取决于屏幕高度
【发布时间】:2013-03-22 13:51:12
【问题描述】:

我知道我遗漏了一些东西,因为这必须是容易实现的。

我的问题是我的“加载屏幕”(即在启动画面之后出现的那个)中有一个 UIImageView,其中包含两个不同的图像,分别用于 3.5 英寸和 4 英寸大小的屏幕。在该图像的某个位置,我放置了一个 UIActivityIndi​​cator,以告诉用户应用程序正在后台加载某些内容。两个图像的那个位置并不相同,因为其中一个明显高于另一个,所以我想设置一个自动布局约束,允许我将该活动指示器放在不同的高度,这取决于应用程序是否在iPhone 5 与否。

如果没有自动布局,我会将视图的 frame.origin.y 设置为 300(例如),然后在 ViewController 的 viewDidLoad 方法中,我会询问应用程序是否在 iPhone 5 中运行,所以我会将值更改为例如 350。我不知道如何使用 Autolayout 来做到这一点,我认为它必须非常简单。

【问题讨论】:

  • 你能再澄清一点(或粘贴代码)并告诉你缺少什么吗?
  • 我没有使用任何代码来实现这一点,但我正在使用 Interface Builder 来实现。我将编辑问题以添加示例。
  • 只使用情节提要的解决方案:stackoverflow.com/a/37411321/2477632

标签: iphone ios ios6 autolayout


【解决方案1】:

您可以在视图控制器上创建一个NSLayoutConstraint 插座,并将插座连接到您的xib 或情节提要中活动指示器的Y 约束。然后,将updateViewContraints 方法添加到您的视图控制器并根据屏幕大小更新约束的常量。

这是updateViewConstraints 的示例:

- (void)updateViewConstraints {
    [super updateViewConstraints];
    self.activityIndicatorYConstraint.constant =
        [UIScreen mainScreen].bounds.size.height > 480.0f ? 200 : 100;
}

当然,您需要输入适当的值,而不是 200100。您可能想要定义一些命名常量。另外,别忘了致电[super updateViewConstraints]

【讨论】:

  • 如果你还没有看过WWDC 2012的自动排版视频,你应该找时间看看。涵盖了这一点,以及许多其他有用的提示。 (在该页面上搜索“自动布局”,而不是“自动布局”。)
  • 你用什么工具制作了很棒的 GIF?
  • 我使用 ScreenFlow 录制屏幕并编辑和裁剪录制内容。我使用 Photoshop 将电影变成了 GIF。
  • @robmayoff - 确实很好的解释,也许您知道如何在不更新运行时约束的情况下获得相同的结果?当我在 3.5 和 4 英寸外形尺寸之间切换时,如果 Interface Builder 可以向我显示更新的布局,那就太好了。否则,我不得不为一种屏幕尺寸准备 UI,并在运行时使用 hack 将视图的位置调整为实际屏幕尺寸。
  • f 后缀使它成为float 常量而不是double 常量。这让编译器可以生成 float 比较而不是 double 比较,这在 32 位 iOS 设备上应该更快。
【解决方案2】:

@Rob 答案的问题是您应该为每个约束编写大量代码。 所以要解决这个问题,只需将ConstraintLayout 类添加到您的代码中并修改您在 IB 中所需设备的约束常量值:

//
//  LayoutConstraint.swift
//  MyConstraintLayout
//
//  Created by Hamza Ghazouani on 19/05/2016.
//  Copyright © 2016 Hamza Ghazouani. All rights reserved.
//

import UIKit

@IBDesignable
class LayoutConstraint: NSLayoutConstraint {

    @IBInspectable
    var ?3¨5_insh: CGFloat = 0 {
        didSet {
            if UIScreen.main.bounds.maxY == 480 {
                constant = ?3¨5_insh
            }
        }
    }

    @IBInspectable
    var ?4¨0_insh: CGFloat = 0 {
        didSet {
            if UIScreen.main.bounds.maxY == 568 {
                constant = ?4¨0_insh
            }
        }
    }

    @IBInspectable
    var ?4¨7_insh: CGFloat = 0 {
        didSet {
            if UIScreen.main.bounds.maxY == 667 {
                constant = ?4¨7_insh
            }
        }
    }

    @IBInspectable
    var ?5¨5_insh: CGFloat = 0 {
        didSet {
            if UIScreen.main.bounds.maxY == 736 {
                constant = ?5¨5_insh
            }
        }
    }
}

别忘了从ConstraintLayout 继承你的类约束 我会尽快添加objective-c版本

【讨论】:

  • 这对我来说是新事物。您能否指出有关扩展 NSLayoutConstraint 以及如何将它们与界面构建器一起使用的更多信息?
  • 能否请您检查一下这个答案,如果您不清楚,我可以上传一个带有演示的示例项目:) stackoverflow.com/questions/37411320/…
  • 我明白了!您将其子类化并更改 IB 中的约束类。那是我缺少的东西!
  • 感谢 @remy 将代码更新为 swift 3。对于 swift 2,您可以使用屏幕截图中的代码 :)
  • 感谢@HamzaGhazouani,这解决了我的问题,我花了 4 小时努力寻找一种无需大量代码的方法。
【解决方案3】:

自动布局中管理 UI 对象位置的基本工具是约束。约束描述了两个视图之间的几何关系。例如,您可能有一个约束: “进度条的右边缘连接到标签的左边缘,它们之间有 40 个空白点。”

这意味着使用 AutoLayout 您不能根据 UIDevice 的模式进行有条件的位置设置,而是可以创建一个可以修改自身的视图布局,例如。应用程序根据约束在 3.5' 全屏 (IPhone4) 或 4' 全屏 (IPhone5) 上运行。

所以使用约束解决您的问题的选项:

1) 在您的布局上找到一个视图,该视图可用于创建约束以相对定位进度条。 (使用 CMD 按钮选择视图和进度条,然后使用 Editor/Pin/Vertical Spacing 菜单项在 2 个对象之间创建垂直约束)

2) 创建一个绝对约束,将进度条的位置固定到屏幕边缘(保持空间)或居中

我发现这个关于 AutoLayout 的教程很有帮助,它也可能对你有益: http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

请注意:自动布局仅适用于 IOS 6。

【讨论】:

  • 如果您允许编码而不仅仅是使用 Interface Builder(如您所说),您可以考虑使用 @Rob 提到的约束,当然只需根据 [[UIScreen mainScreen] 在 vi​​ewDidLoad 中调整进度条的框架bounds ].size.height 参数(480->IPhone4 或以下,568->IPhone5)
  • 我确实允许编码,我的意思是在那之前我只使用 IB 来设置约束,我不知道 updateViewConstraints 方法。无论如何,谢谢。
【解决方案4】:

我通常总是尝试留在 Interface Builder 中来设置约束。例如,如果您在 iPhone 4 和 6 上的布局完全不同,那么深入研究代码以获得更多控制通常很有用。

如前所述,您不能在 Interface Builder 中使用条件,这时将约束链接到您的视图控制器真的很方便。

以下是针对不同屏幕尺寸解决自动布局问题的 3 种方法的简短说明:http://candycode.io/how-to-set-up-different-auto-layout-constraints-for-different-screen-sizes/

【讨论】:

  • 我们可以更改 IB 中的值 :)
  • @HamzaGhazouani 是的,你可以。但是你不能在那里有条件(如果宽度
【解决方案5】:

新方式,不写一行!

无需像这样编写基于设备的条件:-

if device == iPhoneSE { 
   constant = 44 
} else if device == iPhone6 {
   constant = 52
}

我创建了一个库 Layout Helper,所以现在您无需编写任何代码即可更新每个设备的约束条件。

第一步

将 NSLayoutHelper 分配给您的约束

第 2 步

为你想要的设备更新约束

第三步

运行应用程序并查看 MAGIC

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多