为iPhone和iPad编程时,以编程方式布局UI的最佳实践

7

我正在寻找一种干净的解决方案来以编程方式布局UI,并使其在每个设备上看起来正确。 我尝试通过扩展CGFloat来根据设备比例缩放数字,但效果不佳。

extension CGFloat {
    func scale() {
        // Modifies self by multiplies by the ratio between the initial screen size and the desired screen size
    }
}

// usage
view.widthAnchor.constraint(equalToConstant: 20.scale())

我也尝试过为iPhone和iPad创建两组不同的约束条件,并根据应用程序在哪种设备上运行来激活它们,但这似乎是冗长的。如何布局我的UI以便在所有设备上都能正常工作而不需要hacky的解决方案。是否应避免某些类型的约束条件?(例如,将宽度/高度常量设置为屏幕(或其他视图)的宽度/高度的倍数,而不是固定值?)编辑:我不想过度解释自己的情况,让我重新问问题。在为iPhone和iPad设计的应用程序中设置约束条件的一些最佳实践是什么?只检查设备是否为iPad并且如果是,则仅为iPad设置约束条件,如果不是,则只为iPhone设置约束条件是不好的做法吗?
3个回答

4

您提出的问题无法直接回答...

你的应用程序是做什么的?如果它是一个照片幻灯片,将imageView约束到全屏并设置其内容模式为scale-fit。哇!它在所有设备上“看起来不错”!

如果您的应用程序比那更复杂,您可能需要使用所有类型的约束:元素相对于彼此;相等;相对/相等带有常量调整;相对/相等带有乘数调整等等。如果您希望根据设备+方向获得不同的布局(不仅仅是不同的大小),则还可以利用size-class-variations。

此外,使一个应用程序在每个设备上显示正确涉及到远远不止应用约束这一步。

  • 该应用程序应该使用标签栏吗?
  • 导航栏?
  • 两者结合?
  • 都不用?
  • 该使用文本按钮或图像按钮?
  • 应该适应辅助功能和动态字体吗?
  • 甚至在小屏幕和大屏幕上运行时可能具有不同的功能?

总的来说,您应该首先手绘您期望拥有的每个屏幕和UI元素-包括活动“流”-并具有不同大小和方向的变化,以便您从一开始就设计出最佳的UI / UX。此时,您开始实际UI构建。

请注意,有些人可能无法制作出“Hello World”应用程序,但可以作为“应用程序设计师”赚取相当不错的收入

尽管如此,您确信几乎肯定不应采用的一种方法是:

view.widthAnchor.constraint(equalToConstant: 20.scale())

编辑

这是一个快速示例 - 基于此文章:https://www.raywenderlich.com/1343912-adaptive-layout-tutorial-in-ios-12-getting-started

一个简单的天气应用程序 - 设置约束以使其在所有iPhone和iPad型号上看起来相似:

输入图像描述

输入图像描述

但是,当您旋转手机时会发生什么?

输入图像描述

小小的云看起来不太好。添加trait-variations / size-classes,我们可以得到:

输入图像描述


并且,为了尝试回答您编辑后的问题:“仅检查设备是否为iPad是否是不好的做法?”

是的。建议设计trait-variations / size-classes,以便您的应用程序在所有配置中看起来如您所愿(希望也能够适用于下一个设备)。


我的答案仍然是一样的。如果你想让你的应用程序在所有设备上“好看” - 包括方向和iPad多任务处理 - 你必须设计你的应用程序以适应不同的尺寸,并且然后开始布局你的用户界面并约束你的元素。 - DonMag
应用程序已经完全设计好了。我有iPad和iPhone的屏幕,但它们除了一些尺寸之外看起来是相同的。我应该为iPhone和iPad创建两个完全不同的约束集,还是一个适合两者的约束集? - Gabe Spound
您的应用程序是否仅限于竖屏方向? - DonMag
这是仅支持横屏显示的。 - Gabe Spound
我如何在没有故事板的情况下设置尺寸类别特征变化? - Gabe Spound
你可能会创建约束数组,然后根据 traitCollectionDidChange 的响应情况激活/停用它们。 - DonMag

3
仅仅检查设备是否为iPad,如果是的话就针对iPad进行约束,否则就针对iPhone进行约束,这种做法是不好的。如果你计划支持Split-View,那肯定不行。实现和处理这个功能的代码总是稍微有些冗长的。在-[UIViewController viewDidLoad]方法中,您需要使用控制器视图的基础特质集设置视图。这是你的起点。当应用程序的窗口由操作系统调整大小时(比如从全屏横向模式到占据屏幕三分之一的分割大小应用程序),会在您的View Controller上调用-[UIViewController traitCollectionDidChange:]方法。这是您更新布局约束的地方。您可以并且应该将您的布局逻辑封装在一个单独的方法中,并从-[UIViewController viewDidLoad]以及-[UIViewController traitCollectionDidChange:]中调用它。在这样的方法中,我不建议检查主机设备是否为iPad。您需要具体查看活动特质集中的horizontalSizeClassverticalSizeClass属性,以确定您布局约束的值。要了解更多信息,请参阅以下文档: 1. https://developer.apple.com/documentation/uikit/uitraitcollection?language=objc 2. https://developer.apple.com/documentation/uikit/uitraitenvironment/1623516-traitcollectiondidchange?language=objc 。第二个链接有一个简单的示例,说明如何检查是否需要更新您的约束条件。

0

我通常先获取屏幕的尺寸,然后使用宽度/高度的百分比来设置框架。

height = view.bounds.height
width = view.bounds.width
mybutton.frame = CGRect(x: width * 0.05, y: height * 0.02, width: width * 0.3, height: height * 0.1)

2
我觉得使用固定框架而不是自动布局来设置框架在稳定性和持久性方面都不是一个好主意。 - Gabe Spound

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接