【问题标题】:How to set constraints for iPhone 5s or iPhone SE only using storyboard in autolayout?如何仅在自动布局中使用情节提要为 iPhone 5s 或 iPhone SE 设置约束?
【发布时间】:2017-09-17 04:13:50
【问题描述】:

我正在尝试使用故事板为特定的 iPhone SE 或 5s 使用 AutoLayout 设置约束。

您能否建议一些使用情节提要的屏幕截图来处理仅针对不同 iPhone 的约束?

【问题讨论】:

    标签: ios iphone autolayout storyboard


    【解决方案1】:

    iPhone SE 和 iPhone 6/7 具有相同的尺寸等级。因此,您为 SE 创建的所有约束也将应用于 6。 但是您可以从代码中操作它们。检查 UIScreen.main.bounds 并在必要时更新代码中的约束。

    【讨论】:

    • 你能编辑你的答案并提出一些例子来操纵约束吗?
    【解决方案2】:

    您可以使用变体对 defrance Device 设置约束。但是已经使用了 Xcode 8.0,这是一个新选项 Vary for Traits。

    例如,您需要一个在 iPhone 和 iPad 中具有不同宽度的按钮,然后它可以轻松完成并同时查看,而不是早期的 Size 类,其中检查每个布局,我们必须打开预览并选择设备。

    我添加了一个固定宽度为 135 的按钮。

    如果我们现在选择一个 iPad 屏幕,它会显示为

    现在,如果我们要更改 iPad 的尺寸,请单击右下角的“Vary for Traits”按钮。现在您可以根据需要选择横向或纵向。同时选择高度和宽度复选框。

    我现在将宽度常量更改为 500。

    然后作为确认,我们需要点击“完成变化”按钮。之后屏幕看起来像

    现在,当您返回任何 iPhone 设备时,宽度限制将与之前在 iPhone 设备中设置的相同。

    这就是“Vary Traits”的全部内容。我确实接受在使用“Traits”时在不同的 iPhone/iPad + Orientaion 组合之间进行更改时会出现一些约束丢失的错误。

    所以为了安全起见,我要求牢记各种屏幕布局的 Size 类值,如

    如果您有任何疑问,请告诉我。

    【讨论】:

    • 如果我想为 iPhone 5s 或 iPhone 6s 设置不同的约束怎么办?有可能吗?
    • iPhone 8 和 iPhone SE 是紧凑宽度和常规高度。如何为这两个设备设置约束?请帮帮我。
    • 这些特征非常粗略,仅在针对 iPhone 与 iPad 或纵向与横向时才有帮助(您也可以针对色域,但您需要多久使用一次?)。对于我们大多数人来说,自动布局是最好的策略。对于一次性(例如偶尔的 iPhone SE UI 故障),只需更改代码即可。
    【解决方案3】:

    Storyboard 内部 iPhoneSE 和 iPhone6/7 之间的区别是我期待已久的。但不幸的是,我不得不意识到它们具有相同的大小等级,因此(据我所知)不可能为两个内部 Storyboard 设置约束差异。 (如果我错了 - 请告诉我!!)。

    但是,您可以在代码中完成。

    您可以使用AnchorPointsLayoutAnchors 在代码中设置约束。但通常,对于我的大多数情况,以下操作:

    我在 UIDevice-ModelNames 周围使用 Switch-case,并将 iPhoneSE 的 Layout-Constraints 设置为与 iPhone6/7(或我想要区分的任何设备)不同。

    话虽如此,完全在代码中创建视图(及其约束)通常是一个好主意,而无需故事板。但我认为,对于简单的项目,快速提出 Storybard-Layout 及其约束设置有时仍然很有用。然后我做以下区分设备:

    // create the constraint-outlet by CTRL-drag
    // one of your defined Constraint-lines from
    // Storyboard directly to your Code
    
    @IBOutlet weak var bannerWidthConstraint: NSLayoutConstraint!
    
    // then for example inside viewDidLoad, set the outlet's constant to the value needed...
    // Distinguish manually between UIDevices...
    override func viewDidLoad() {    
    
        switch UIDevice.current.modelName {
        case Devices.IPhone5, Devices.IPhone5S, Devices.IPhone5C: 
             //, Devices.Simulator:
             self.bannerWidthConstraint.constant = 73
        case Devices.IPhone6, Devices.IPhone6S, Devices.IPhone7, Devices.IPhone8:
            //, Devices.Simulator:
            self.bannerWidthConstraint.constant = 96
        case Devices.IPhone6Plus, Devices.IPhone6SPlus, Devices.IPhone7Plus, Devices.IPhone8Plus:
            //, Devices.Simulator:
            self.bannerWidthConstraint.constant = 110
        case Devices.IPhoneX:
            //, Devices.Simulator:
            self.bannerWidthConstraint.constant = 96
        default:
            self.bannerWidthConstraint.constant = 73
        }
    }
    

    备注:使用模拟器请注意!模拟器有自己的 UIDevice-modelName ,因此您需要取消注释您正在运行模拟器的设备大小中的 Devices.Simulator 注释(即根据您的模拟器运行的目标!)。 --> 注意每个 switch-case 都可以是 Simulator-Device !!

    并且不要忘记在代码库中的某处定义您的设备: (--> 当然,当新的 Apple 设备出现时,您需要更新这些...)

    public enum Devices: String {
        case IPodTouch5
        case IPodTouch6
        case IPhone4
        case IPhone4S
        case IPhone5
        case IPhone5C
        case IPhone5S
        case IPhone6
        case IPhone6Plus
        case IPhone6S
        case IPhone6SPlus
        case IPhone7
        case IPhone7Plus
        case IPhoneSE
        case IPhone8
        case IPhone8Plus
        case IPhoneX
        case IPad2
        case IPad3
        case IPad4
        case IPad5
        case IPadAir
        case IPadAir2
        case IPadMini
        case IPadMini2
        case IPadMini3
        case IPadMini4
        case IPadPro_9_7
        case IPadPro_12_9
        case IPadPro_12_9_2ndGen
        case IPadPro_10_5
        case AppleTV_5_3
        case AppleTV_6_2
        case HomePod
        case Simulator
        case Other
    }
    

    还有……

    public extension UIDevice {
    
        public var modelName: Devices {
            var systemInfo = utsname()
            uname(&systemInfo)
            let machineMirror = Mirror(reflecting: systemInfo.machine)
            let identifier = machineMirror.children.reduce("") { identifier, element in
                guard let value = element.value as? Int8 , value != 0 else { return identifier }
                return identifier + String(UnicodeScalar(UInt8(value)))
            }
    
            switch identifier {
            case "iPod5,1":                                 return Devices.IPodTouch5
            case "iPod7,1":                                 return Devices.IPodTouch6
            case "iPhone3,1", "iPhone3,2", "iPhone3,3":     return Devices.IPhone4
            case "iPhone4,1":                               return Devices.IPhone4S
            case "iPhone5,1", "iPhone5,2":                  return Devices.IPhone5
            case "iPhone5,3", "iPhone5,4":                  return Devices.IPhone5C
            case "iPhone6,1", "iPhone6,2":                  return Devices.IPhone5S
            case "iPhone7,2":                               return Devices.IPhone6
            case "iPhone7,1":                               return Devices.IPhone6Plus
            case "iPhone8,1":                               return Devices.IPhone6S
            case "iPhone8,2":                               return Devices.IPhone6SPlus
            case "iPhone9,1", "iPhone9,3":                  return Devices.IPhone7
            case "iPhone9,2", "iPhone9,4":                  return Devices.IPhone7Plus
            case "iPhone8,4":                               return Devices.IPhoneSE
            case "iPhone10,1", "iPhone10,4":                return Devices.IPhone8
            case "iPhone10,2", "iPhone10,5":                return Devices.IPhone8Plus
            case "iPhone10,3", "iPhone10,6":                return Devices.IPhoneX
            case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return Devices.IPad2
            case "iPad3,1", "iPad3,2", "iPad3,3":           return Devices.IPad3
            case "iPad3,4", "iPad3,5", "iPad3,6":           return Devices.IPad4
            case "iPad4,1", "iPad4,2", "iPad4,3":           return Devices.IPadAir
            case "iPad5,3", "iPad5,4":                      return Devices.IPadAir2
            case "iPad6,11", "iPad6,12":                    return Devices.IPad5
            case "iPad2,5", "iPad2,6", "iPad2,7":           return Devices.IPadMini
            case "iPad4,4", "iPad4,5", "iPad4,6":           return Devices.IPadMini2
            case "iPad4,7", "iPad4,8", "iPad4,9":           return Devices.IPadMini3
            case "iPad5,1", "iPad5,2":                      return Devices.IPadMini4
            case "iPad6,3", "iPad6,4":                      return Devices.IPadPro_9_7
            case "iPad6,7", "iPad6,8":                      return Devices.IPadPro_12_9
            case "iPad7,1", "iPad7,2":                      return Devices.IPadPro_12_9_2ndGen
            case "iPad7,3", "iPad7,4":                      return Devices.IPadPro_10_5
            case "AppleTV5,3":                              return Devices.AppleTV_5_3
            case "AppleTV6,2":                              return Devices.AppleTV_6_2
            case "AudioAccessory1,1":                       return Devices.HomePod
            case "i386", "x86_64":                          return Devices.Simulator
            default:                                        return Devices.Other
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      这不是很好,但至少比用代码做所有事情要容易一些。

      所以,例如如果你想为 LoginViewController 设置不同的约束,你可以创建两个 xib:LoginViewControllerSE.xib(用于 SE)和 LoginViewController.xib(用于其他手机),然后创建初始化程序:

      init() {
          if UIDevice.current.modelName == Devices.IPhoneSE {
              super.init(nibName: "LoginViewControllerSE", bundle: nil)
          } else {
              super.init(nibName: nil, bundle: nil)
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-05-02
        • 2019-09-28
        • 2015-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-24
        相关资源
        最近更新 更多