请教使用 AutoLayout 适配 Frame 大小的正确方式

2015-12-21 21:55:46 +08:00
 Hamniba
下面用一个 Button 举例:
同一个 Button ,需要在不同大小的屏幕上适配 Button 的尺寸,使它在 4.0 尺寸上看起来要比在 4.7 或 5.5 尺寸上要小一些。

1. 使用 AutoLayout 分别设置约束 Leading, Top, Width, Height ,由于约束都是一个固定值,所以 Button 的大小在不同屏幕上都是一样。


2. 使用 AutoLayout 分别设置约束 Leading, Top, Bottom, Trailing, 由于约束都是一个固定值,所以这种情况在不同的屏幕上 Button 的大小被拉伸了,并不是我想要的效果。


有一种解决方案是,可以按屏幕的比例等比设置对应控件的约束值,但是这样实现起来比较麻烦。每一个控件的约束值都要单独计算,那么一个 View 上有很多个需要适配的控件就更麻烦了。

Google 关键词: view autolayout resize frame 并未找到有好的解决方案。
所以请教一下,正确的实现方式是什么?
3986 次点击
所在节点    iDev
15 条回复
tigerZhang
2015-12-21 22:22:42 +08:00
这个就要看你的页面对控件的布局要求,是全部等比放大还是部分等比放大。
anguslg
2015-12-21 22:37:11 +08:00
你第二种的约束条件再加一个比例约束就可以了
SeanChense
2015-12-21 22:47:14 +08:00
算好控件相对屏幕宽度的比例 k , k 为 0 到 1 之间的系数,然后指定 width
SeanChense
2015-12-21 22:49:25 +08:00
sorry 没仔细看楼主的正文。
不过还有一个关于 content 的 priority 的属性,不知道能不能满足。
banxi1988
2015-12-21 23:04:06 +08:00
top,leading,width,aspectRatio
只需要 width 根据屏幕变化就可以了。
也并不复杂,其实就写的时候加一个函数调用。
比如我有一个 dp2dp 用来转换。
原来需要设置 120
那我设置的时候使用 dp2dp(120)就可以了。
下面是我的实现代码:

```swift
let designBaseWidth :CGFloat = 375 // 一般以 iPhone 6 来设计,其宽度为 750 -> 375 point
func dp2dp(dp:CGFloat) -> CGFloat{ // Design Pointer to Devices Pointer
let coefficent = screenWidth / designBaseWidth
return floor(dp * coefficent)
}
```
使用:

` iconImageView.pinTop(dp2dp(36))`
xi_lin
2015-12-22 01:28:31 +08:00
类似楼上的,我有个全局宏做缩放用
Hamniba
2015-12-22 09:26:56 +08:00
@tigerZhang
@anguslg
@SeanChense
@banxi1988
@xi_lin

Thanks all,


@tigerZhang 如果是某个页面要全部等比放大,有一次性设置的办法吗?

你们单独写一个方法出来计算尺寸的这种方案其实跟我最后提到的解决方案是差不多的,不管是计算约束还是直接计算控件的 frame ,都是要*手动计算*控件的尺寸,如果一个页面上有多个需要调整的控件,那就得每个控件都计算一次,工作量还是蛮大的。

我想寻求的是有没有一种比较简单的方法不用去做这种重复的工作?
AutoLayout 在某些情况下也不是那么方便。
MarineLv
2015-12-22 17:11:40 +08:00
需要等比放大的话,可以以一种屏幕为基准,设好 frame 以后,固定按钮的长宽和屏幕宽度的比值。
一般来说,屏幕适配的原则是更大的屏幕显示更多的内容,所以固定大小和固定与周围元素间距两种办法足以应对大多数适配需求了。
MarineLv
2015-12-22 17:16:23 +08:00
用 snapkit 来描述,就是 make.width.equalTo(self.view.snp_width).dividedBy(0.3)
Hamniba
2015-12-22 19:24:38 +08:00
@MarineLv
Thanks!

我一般是以 5.7 的屏幕为基准,对于在小屏幕上控件超出屏幕的情况我就只能同时按比例缩放 frame 大小和与周围元素的约束值了。

好像目前也就只能是这样处理。
Hamniba
2015-12-22 19:27:01 +08:00
@Hamniba
纠正:是 5.5 尺寸的屏幕 : )
xi_lin
2015-12-22 19:48:22 +08:00
@Hamniba 一般用 750 的屏幕为基准,往上往下都比较方便
tigerZhang
2015-12-22 22:19:21 +08:00
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *spaceContraints;

- (void) awakeFromNib
{
// 遍历你的间距约束,等比例缩放
for (int i = 0; i < [self.spaceContraints count]; i++) {
NSLayoutConstraint* constraint = (NSLayoutConstraint*)[self.spaceContraints objectAtIndex:i];
constraint.constant *= 缩放系数;
}
// 如果需要 label 的文字 或者图片根据比例变化, 也可以在这里进行遍历缩放
}
Madeline
2015-12-22 22:52:51 +08:00
我一直都感觉类似 width 这样的属性如果需要根据比例调整大小的话,其实 autolayout 意义就不大了。用代码来基于传统 frame 来布局更快。前提是只做 iphone app 的话,如果是 universal app 那另说。

autolayout 的目的就取代 frame 。
Hamniba
2015-12-23 09:07:28 +08:00
@tigerZhang 我也用的这种方法, by the way 可以用 for ... in 哦 : )
@Madeline 如果不直接限制 Width Height 的话 frame 就要变形了 如图二

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/245192

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX