专栏首页進无尽的文章浅汇-iOS UI布局

浅汇-iOS UI布局

  iOS中UI的布局是很重要的,而在前期开发中就要选定好布局的方法,因为这对整个工程乃至于后期的版本维护都有很重要的影响。本文从比较老的Frame到新生AutoLayout都进行了浅显的总结,希望对大家的UI布局学习有所帮助


Frame

父试图是使用的AutoLayout  ,如果子试图的Frame  = supeView.Frame  就会无法获得足够的宽度。如果父试图使用的是 Frame  , 子试图使用 AutoLayout  不会有问题,

使用Frame 来布局UI是开始的做法,现在也有很多人仍然钟情与这种方法,这种方法很直观,使用起来也很简单,但是他的简单决定了他在屏幕适配和内容自适应上的局限性(横竖屏时不设置的话无法使用,因为横屏的时候,之前设置的Frame属性 还是竖屏的Frame)`,当然可以使用Fram的方法达到屏幕适配和自动布局,但是中间的过程是复杂而且工作量巨大的,写起来也是痛苦的。通常使用这种方法布局是通过比例放缩来达到的,比如使用如下的宏来替换掉系统的CGRectMake(x , y , width , height) 布局来达到屏幕适配的效果。

#define NEWX                        [UIScreen mainScreen].bounds.size.width/384    #define NEWY                         [UIScreen mainScreen].bounds.size.height/512 #define NEWY                        NEWX #define RECT(a,b,c,d)            CGRectMake(a*NEWX, b, c*NEWX, d)  这里我们以宽度缩放比为整体缩放比,就可以完美适配更种机型,不管苹果以后出什么机型,这样设置后就可以保证在各种机型的屏幕上不出现变形的情况(尤其是iphoneX这样修长的机型上)。

但是因为系统的layoutSubviews 方法是默认不执行任何布局的,需要使用者在页面内容确定后再次对空间的Frame进行重置,牵一发而动全身的重置是痛苦而繁琐的。

AutoLayout(动画中使用是个弱点)

     使用SDAutoLayout  不光是为了横竖屏的适配(通过判断屏幕方向,重置 Frame  也可以做到),是为了TablevIew中cell  因为内容的不同而动态完美布局的效果。使用了这么久,       对于父试图是  Button / UITextFeild等非UIView的直接子类,布局其子视图时,这里面的约束是不生效的。而且同层级的试图  无法达到重合布局,两个试图重合的话只有是  父/子视图的关系。

Autolayout简单来说就是一套 `适配iPhone机型`并且`兼容横竖屏`的UI布局系统,Auto Layout 是一个系统,可以让你通过创建元素之间关系的数学描述来布局应用程序的用户界面,是一种基于约束的,描述性的布局系统。这中页面布局方式的思维模式跟Frame完全不同,使用时应跳出Frame的坐标布局思维模式,站在关系依赖布局的思维方式上才可以达到娴熟正确的使用。

我们可以在XIB、StoryBoard中通过拉线的形式给控件视图添加布局约束,通过苹果强大的可视化界 IB(Interface Builder)我们能够轻松的使用AutoLayout完成界面视图的布局。另外一种方式就是通过纯代码的形式使用AutoLayout,即NSLayoutConstraint。

IB

原生的AutoLayout

原生的iOS布局,要添加`一个约束`是这样的:

 NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:view //第一个view attribute:NSLayoutAttribute //约束属性, 比如上下左右宽高等间距  relatedBy:NSLayoutRelationEqual //相等,或者大于等于,小于等于 toItem:secondView //第二个view,也就是第一个view是要参照第二个view的 attribute:NSLayoutAttribute //参照第二个view的属性  multiplier:multiplier  //比例0--1  constant:0]; //约束值

就这样随便加一个约束就如此的繁琐,更何况一个view最起码有上边距,左边距和宽高,也就是所谓的x、y、width、height四个基本属性。就相当于以上那复杂的代码就要最少写四次。

所以对IOS的AutoLayout进行封装就显得很有必要了。本次推荐使用的是一个第三方的AutoLayout库这个库实现了对普通空间的自动布局,也实现了对ScrollView及UITableView的自动布局,操作简单,功能强大(SDAutoLayout)

SDAutoLayout

主要的功能是:

1、实现Label高度固定,宽度自适应(超出后不显示),宽度固定,高度自适应。

2、实现了UIView内子视图的自动布局;

3、实现了UIScrollView内容高度根据内部子视图的内容高度动态设置;

4、实现了一个UITableView有多个不同Cell的时候,所有cell高度自适应;

实现Label高度固定,宽度自适应(超出后不显示),宽度固定,高度自适应。

/** 设置单行文本label宽度自适应,超出了这个最大宽度则不显示,否则会根据文字多少自动调整宽度 */  - (void)setSingleLineAutoResizeWithMaxWidth:(CGFloat)maxWidth;  /** 自适应高度,传入高宽比值,label可以传0实现文字高度自适应 */   @property (nonatomic, copy, readonly) AutoHeight autoHeightRatio;  

当父试图的高度没有定义的时候,需要使用一下方法来自动布局,并且这个时候不可以再以父试图的底为标准来设置其内部子视图,这是一种【从里到外】的布局思路,cell的自适应高度也是这种思路;平时我们的思路都是一种【从外到里】的思路,先确定外面的再使其自动布局里面的。

有一个需要注意的地方,cell中所有的子视图都需要加载在 self.contentView上才行,不可加载在self.contentView的子视图上,否则按下面的这个方法设置也会出问题。 [self setupAutoHeightWithBottomView:_timeLabel bottomMargin:margin + 5];//第一个参数是指 底部试图,第二个参数是指底部的留出来的空白区域的高度。

实现了UIScrollView可滚动高度根据内部子视图的内容高度动态设置

/** 设置scrollview内容自适应,第一个参数为作为底部的子视图,第二个参数为到sc底部的间距。 */ - (void)setupAutoContentSizeWithBottomView:(UIView *)bottomView bottomMargin:(CGFloat)bottomMargin;

这面这一个协议中设置即可,关键是cell中的设置,cell中的设置需要满足两点:第一个是子视图的相对位置关系的设置,第二个是设置[self setupAutoHeightWithBottomView:_view3 bottomMargin:10]即可,这个方法在 子视图初始化的最后设置可以在 Model赋值后设置也可以

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath    {        /* model 为模型实例, keyPath 为 model 的属性名,通过 kvc 统一赋值接口 */   return [self cellHeightForIndexPath:indexPath cellContentViewWidth:[UIScreen mainScreen].bounds.size.width tableView:tableView];    }

使用SDAutoLayout来布局UIImageView的时候,遇到圆角的问题,headHeadImageV.layer.cornerRadius=40;是不会起作用的。

UIImageView *imageV = [UIImageView new]; [self.view addSubview:imageV]; imageV.image = [UIImage imageNamed:@"loginLogo"]; imageV.sd_layout.leftSpaceToView(self.view,20).topSpaceToView(self.view,80).widthIs(80).heightIs(80);  [imageV setSd_cornerRadius:@40];

方法名中带有“SpaceToView”的方法表示到某个参照view的间距,需要传递2个参数:(UIView)参照view 和 (CGFloat)间距数值  `当这个参照View是他的父试图时,leftSpaceToView就表示当前这个试图的左边到父试图左边的距离,当这个试图是同一层级的参照的话,就表示当前试图的左边到参照试图右边的距离,依次类推,传入的这个CGFloat值需要是一起的值才行,如果这个值是组合值的话就要加()如:leftSpaceToView(self.sc,(passWordBgView.width+5))。各种设置彼此之间是彼此独立的,后面的设置效果会覆盖前面设置的效果。考虑到完美适配的问题  引入一下两个宏:

#define Scale_X(a)(a*NEWX) #define Scale_Y(a)(a*NEWY) eg:.heightIs((Scale_Y(45))); .topSpaceToView(leftView,Scale_Y((yValue+60*i+3))), 注意:,Scale_Y((yValue+60*i+3))当内层参数是组合参数时,需要双层(),否则无法把组合参数作为一个整体,从而在屏幕尺寸适配上出问题。而且要先加载到父试图上才能使用 layout 语句,否则约束不回起作用(针对 SDAutoLayout)。

动画中试图的自动布局刷新(SDAutoLayout在动画中并不友好)

[UIView animateWithDuration:0.8 animations:^{ self.view0.sd_layout .widthRatioToView(self.view, _widthRatio); [self.view layoutSubviews]; [self.view0 layoutSubviews]; }]; //刷新试图达到自动布局其子试图的功能`


小结

 iOS关于UI布局的知识还有很多,至此我列举了一些需要注意的地方,使用的时候是先初始化`new`比较方便,先加载到父视图上后设置相关的属性,然后再进行布局方面的设置,若后加到父试图上,会设置无效或者是默认的布置设置。 所以当我们要创造一个待加载的试图(只是创建,而不加载)就无法使用SDLayout  来布局了,就只能使用Frame来布局了。否则里面的子试图会布局的很乱。这大概就是SDLayout 的使用禁区了,SDLayout需要先加载到父视图上才有效果。 使用 NEWX、NEWY 做宽高比例放缩 ,加上 SDLayout的相对布局就实现了所谓的完美适配。

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!
本文分享自作者个人站点/博客:https://www.jianshu.com/u/aef519a9dde7复制
如有侵权,请联系 cloudcommunity@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • 浅汇-iOS 动画

            在iOS开发中,制作动画效果是最让开发者享受的环节之一。一个设计严谨、精细的动画效果能给用户耳目一新的效果,吸引他们的眼光 —— 这对于app而...

    進无尽
  • React Native 学习资源精选仓库

    React Native Awesome汇集了各类react-native学习资料、工具、组件、开源App、资源下载、以及相关新闻等,只求精不求全。 如果你是...

    CrazyCodeBoy
  • 受益互联网出海 汇量科技业绩重回高增长

    ““2025年中国出海数字营销行业规模有望达到502亿美元,全球程序化广告支出在数字广告的渗透率将达到85%。”中信证券近期发布研报指出,程序化广告大势所趋,后...

    定向
  • Reveal使用教程(iOS CrackMe练习)

    在对iOS app进行安全分析时,为了了解app的整体框架,需要在app启动后,查看app的整体UI布局。以方便确定app是原生或者H5页面开发,使用的框架、控...

    用户4682003
  • Flutter UI原理

    Widgets是Flutter App用户交互的基础构成,每个widget代表的是用户交互的一部分(不可变的),不像其他frameworks会分开views,v...

    Helloted
  • D-News | 谷歌放出AR/VR开源库; 谷歌和苹果正合作

    大数据文摘
  • Web前端开发推荐阅读书籍、学习课程下载

    学校里没有前端的课程,那如何学习JavaScript,又如何使自己成为一个合格的前端工程师呢?

    慕白
  • 【热点盘点】iOS 8增强的自动布局功能

    自动布局是iOS6开始引进的新功能,而iOS 8则在原有自动布局的基础上增加了SizeClass的概念,从而增强了自动布局功能。

    博文视点Broadview
  • 自学iOS开发,从新手小白到高级工程师正确的打开方式

    自己目前大四汪一枚,自学iOS开发一年左右,先后学习了swift和Objective-C。由于是自学(而且全院貌似就我一个人在学),深知自学之痛。所以在此分享一...

    企鹅号小编
  • Flutter 简介

    Flutter是Google开发的一套全新的跨平台、开源UI框架,支持iOS、Android系统开发,

    Yif
  • 开发 | 掌握这 7 个要点,iOS 开发者也能快速入门小程序

    知晓君
  • React Native 性能优化指南

    2020 年谈 React Native,在日新月异的前端圈,可能算比较另类了。文章动笔之前我也犹豫过,但是想到写技术文章又不是赶时髦,啥新潮写啥,所以还是动笔...

    卤代烃
  • Facebook iOS UI 工具ComponentKit简介

    在 iOS 上面开发界面,需要创建视图、配置界面、视图分层等等很多步骤,也就不可避免的需要书写 N 多的代码。这还仅仅是界面设计,除此之外,完成 control...

    xiangzhihong
  • 【译】Flutter架构综述

    Flutter是一个跨平台的UI工具包,它的设计目的是允许跨iOS和Android等操作系统的代码重用,同时也允许应用程序直接与底层平台服务对接。其目标是让开发...

    用户1907613
  • 从Hybrid到React-Native: JS在移动端的南征北战史

    其实写这篇文章的时候,我就知道,肯定有人问我:为什么不写flutter?抱歉了,flutter的大名我当然知道,可我只是一个写JS的,同时了解一些Java的知识...

    啦啦啦321
  • CSS 布局的本质是什么

    自从图形界面操作系统问世以来,之上的应用软件基本都会绘制界面,这也是用户使用软件的接口,叫做 UI (user interface)。涉及到用户体验、设计、具体...

    公众号@魔术师卡颂
  • iOS 面试策略之系统框架-UIKit

    本章节主要从视图、网络、设计模式几个方面考察开发者的开发水准,这是任何一个合格的 iOS 开发者都应该具备的基本素养。

    会写bug的程序员

扫码关注腾讯云开发者

领取腾讯云代金券