使用 iOS 7 中的动态类型,我如何考虑更高级的布局问题,例如标签/视图之间的间距?
Posted
技术标签:
【中文标题】使用 iOS 7 中的动态类型,我如何考虑更高级的布局问题,例如标签/视图之间的间距?【英文标题】:With Dynamic Type in iOS 7, how do I factor in more advanced layout issues, such as spacing between labels/views? 【发布时间】:2013-10-31 02:27:29 【问题描述】:我正在更新我的应用程序以支持 ios 7 中的动态类型。使文本根据系统设置调整其大小相对容易,但因为我在 UITableView 和单元格的上下文中使用它其中有多个 UILabel,文本大小并不是我唯一需要担心的事情。如果文本增加,单元格的高度也应该如此,如果文本缩小,单元格的高度也应该如此。
此外,如果它变小,与最大尺寸的类型相比,它的项目之间的间距显然应该更小(因为在小尺寸时,它们之间的空间会很大)。
当用户更改其动态类型大小时,我如何更改更高级的布局问题?
现在,我正在做一些非常丑陋但几乎无法正常工作的事情。我查看我的一个标签的高度,并用它的大小缩放我的常数。但它非常不精确,因为当前文本大小的 UILabel 高度的 110% 被用作元素之间的填充不一定是普遍适用的。
这就是我在该示例中所做的:
CGRect articleTitleRect = [article.title boundingRectWithSize:CGSizeMake(CGRectGetWidth(self.contentView.bounds) - 29, MAXFLOAT)
options:NSStringDrawingUsesFontLeading
attributes:@ NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]
context:nil];
self.urlConstant.constant = articleTitleRect.size.height / 5;
self.previewConstant.constant = articleTitleRect.size.height / 5;
(基本上找出标签的高度是多少,然后使用其中的百分比来推断间距。同样,非常不精确并且不能普遍适用。)
我考虑做的另一件事是检查当前preferredFontForTextStyle:
等于点大小,并为特定值硬编码界面调整/间距。这工作得更好一点,但它似乎仍然不是 Apple 所想的最佳选择,因为它不是非常动态的(例如,如果他们添加另一种类型大小,它会中断)而且你几乎在嗅探他们没有的值' t 让你一发不可收拾(这让它看起来很老套)。
那么,诸如 Tweetbot 3(现在使用 Dynamic Type 设置其 UITableViewCell 元素)之类的应用程序如何使它们的 UI 在不同的 Dynamic Type 大小上看起来如此出色?这样做的最佳方法是什么?老实说,似乎没有关于该主题的教程。
【问题讨论】:
您能否展示一些 Tweetbot 3 如何根据动态类型更改文本元素之间的间距的屏幕截图? 【参考方案1】:这是您必须自己完成的事情,但 iOS 已经为您提供了 TextKit 所需的工具。 Test Programming Guide里其实有很多文档。
例如,在 Working with Font Objects 部分中,UIContentSizeDidChangeNotification 会通知您的应用动态类型值已更改,并带有带有新值的 userInfo
字典。这是您要进行哪些更改的入口点。比如新值为UIContentSizeCategoryAccessibilityMedium
,则两个标签之间的距离为10个点,但如果新值为UIContentSizeCategoryAccessibilityLarge
,则可以设置为15。当然我只是在编数值,算了最有效的方法是您必须通过反复试验来完成。但是,一旦确定了正确的距离,确保一切正常运行的代码不会超过十几行。
还可以查看UIFontDescriptor
,尤其是该引用底部的常量。它们让您可以访问几乎所有可以想象的字体属性和特征。您可以使用它通过自定义属性“构建”您自己的字体。如果您想这样做,则需要更多代码,但 TextKit 在屏幕上显示文本时为您提供了许多不同的 API。
【讨论】:
【参考方案2】:我还没有使用动态类型。但我认为您可以使用的一种方法是使用自动布局来布局您的单元格内容,并让自动布局引擎确定您所需的单元格高度。然后,当动态类型大小更新时,您只需要求 tableview 重新加载或重新计算(通过 beginUpdates/endUpdates)。
我用如何使用自动布局来计算任何给定单元格的表格视图单元格高度的示例回答了一个问题,这里:
How to resize superview to fit all subviews with autolayout?
编辑
根据您的评论:
高度不是这里真正的问题,我可以计算一下 容易地。 我的问题是如何处理更难的事情,比如 例如,标签之间的空间,随着标签变大 它们的间距也应该略有增长。也只是基本上 学习如何最好地调整受动态类型影响的布局
一旦创建并注册了约束,当您需要在运行时调整约束时,您可以通过调整约束的constant
属性来实现。因此,如果您想根据其他一些属性(例如文本大小)调整两个项目之间的间距,您必须通过调整管理这两个项目间距的约束常量来手动执行此操作。如果约束是在 Interface Builder 中创建的,则需要将其绑定到某处的 IBOutlet,以便您可以在代码中引用它。
约束也有一个乘数属性,您可以使用它来根据其他视图的计算属性值动态调整一个约束。我不认为你可以在 Interface Builder 中操作它,但如果你在代码中创建你的约束,你可以。使用乘数,您应该能够设置一个间距约束,根据其他元素的高度调整更大或更小。
在更复杂的场景中,除了调整简单的间距约束之外,您可能希望在某些属性更改(例如文本大小)的情况下大幅更改布局。在这种情况下,我会推荐以下任一方法:
1) 完全在代码中创建和管理您的约束。当您确定需要更改布局时,拆除并建立正确的约束集。
2) 创建多个 nib 以通过 Interface Builder 定义的约束来管理多个 UI 布局。当您确定需要更改布局时,动态加载/重新加载正确的笔尖。这样做可能不受欢迎的副作用是您的所有视图/控件都将被重新创建。
【讨论】:
高度不是这里真正的问题,我可以很容易地计算出来。我的问题是如何处理更难的事情,例如标签之间的空间,随着标签变大,它们的间距也应该略有增长。也只是基本上学习如何最好地调整受动态类型影响的布局。 我了解如何更改常量,但是将它们更改为什么值是这里令人困惑的部分。我怎么知道要使用什么乘数?仅仅通过查看其他 UI 元素的增长来进行猜测是一种相当不准确的方式。以上是关于使用 iOS 7 中的动态类型,我如何考虑更高级的布局问题,例如标签/视图之间的间距?的主要内容,如果未能解决你的问题,请参考以下文章
iOS UICollectionView 动态切换单元格NIB
Kibana:如何使用 Kibana 时间偏移高级公式和动态颜色 - 7.14