请教使用 AutoLayout 适配 Frame 大小的正确方式 - V2EX
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 4349 次点击
    这是一个创建于 3606 天前的主题,其中的信息可能已经有所发展或是发生改变。
    下面用一个 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     Solana     3517 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 04:21 PVG 12:21 LAX 20:21 JFK 23:21
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86