V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
Hamniba
V2EX  ›  iDev

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

  •  
  •   Hamniba · 2015-12-21 21:55:46 +08:00 · 3996 次点击
    这是一个创建于 3295 天前的主题,其中的信息可能已经有所发展或是发生改变。
    下面用一个 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 并未找到有好的解决方案。
    所以请教一下,正确的实现方式是什么?
    15 条回复    2015-12-23 09:07:28 +08:00
    tigerZhang
        1
    tigerZhang  
       2015-12-21 22:22:42 +08:00
    这个就要看你的页面对控件的布局要求,是全部等比放大还是部分等比放大。
    anguslg
        2
    anguslg  
       2015-12-21 22:37:11 +08:00
    你第二种的约束条件再加一个比例约束就可以了
    SeanChense
        3
    SeanChense  
       2015-12-21 22:47:14 +08:00 via iPad
    算好控件相对屏幕宽度的比例 k , k 为 0 到 1 之间的系数,然后指定 width
    SeanChense
        4
    SeanChense  
       2015-12-21 22:49:25 +08:00 via iPad
    sorry 没仔细看楼主的正文。
    不过还有一个关于 content 的 priority 的属性,不知道能不能满足。
    banxi1988
        5
    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
        6
    xi_lin  
       2015-12-22 01:28:31 +08:00 via iPhone
    类似楼上的,我有个全局宏做缩放用
    Hamniba
        7
    Hamniba  
    OP
       2015-12-22 09:26:56 +08:00
    @tigerZhang
    @anguslg
    @SeanChense
    @banxi1988
    @xi_lin

    Thanks all,


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

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

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

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

    好像目前也就只能是这样处理。
    Hamniba
        11
    Hamniba  
    OP
       2015-12-22 19:27:01 +08:00 via iPhone
    @Hamniba
    纠正:是 5.5 尺寸的屏幕 : )
    xi_lin
        12
    xi_lin  
       2015-12-22 19:48:22 +08:00 via iPhone
    @Hamniba 一般用 750 的屏幕为基准,往上往下都比较方便
    tigerZhang
        13
    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
        14
    Madeline  
       2015-12-22 22:52:51 +08:00
    我一直都感觉类似 width 这样的属性如果需要根据比例调整大小的话,其实 autolayout 意义就不大了。用代码来基于传统 frame 来布局更快。前提是只做 iphone app 的话,如果是 universal app 那另说。

    autolayout 的目的就取代 frame 。
    Hamniba
        15
    Hamniba  
    OP
       2015-12-23 09:07:28 +08:00
    @tigerZhang 我也用的这种方法, by the way 可以用 for ... in 哦 : )
    @Madeline 如果不直接限制 Width Height 的话 frame 就要变形了 如图二
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2476 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 15:43 · PVG 23:43 · LAX 07:43 · JFK 10:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.