IOS不使用 AutoLayout如何自适应

这是很久以前写的一篇文章,现在把它搬到这儿,统一管理~~~

1 .传统布局的纠结

自己简单封装了个布局框架。以此来分享一下,与大家一起来探讨一下iOS开发。此框架主要有两方面的重要作用:

1. 通过本框架布局,能够清晰的看到iOS控件元素的相互关系,不必要每次都要计算控件的位置,减少脑细胞死亡量。

2. 通过本框架,只需要改动一行代码,就能够轻松实现手机横竖屏完美展现。

3. 其他还有很多好处,自己在使用的过程种可以慢慢体会,可以把你使用的经验分享在下面的评论里。

刚接触ios开发时,看看我们页面布局代码是怎么写的:

[objc]view plaincopy

```

- (void)viewDidLoad {

[superviewDidLoad];

self.view.backgroundColor= [UIColorclearColor];

UIView*view1= [[UIViewalloc]initWithFrame:CGRectMake(5,20, kDeviceWidth/2, kDeviceWidth/3)];

view1.backgroundColor= [UIColorwhiteColor];

[self.viewaddSubview:view1];

UIImageView*imageView1= [[UIImageViewalloc]initWithFrame:CGRectMake(kDeviceWidth/4-22, kDeviceWidth/6-22,44,44)];

[view1addSubview:imageView1];

imageView1.image= [UIImageimageNamed:@"my_04@2x.png"];

UILabel*viewllable = [[UILabelalloc]initWithFrame:CGRectMake(kDeviceWidth/4-60, kDeviceWidth/6-22+44,120,20)];

[view1addSubview:viewllable];

viewllable.text=@"我是:View1";

viewllable.textAlignment= NSTextAlignmentCenter;

}

```

运行的结果如下图所示:

(图1)

让我一起来简单的分析一下上面的代码:

[objc]view plaincopy

```UIView*view1= [[UIViewalloc]initWithFrame:CGRectMake(5,20, kDeviceWidth/2, kDeviceWidth/3)];```

[objc]view plaincopy

```UIImageView*imageView1= [[UIImageViewalloc]initWithFrame:CGRectMake(kDeviceWidth/4-22, kDeviceWidth/6-22,44,44)];```

[objc]view plaincopy

```UILabel*viewllable = [[UILabelalloc]initWithFrame:CGRectMake(kDeviceWidth/4-60, kDeviceWidth/6-22+44,120,20)];```

我们总共添加了三个控件view1(白色的长方形)   imageView1(立方体图片)    viewllable(显示文字的控件),每个控件我都是通过CGRectMake( , , , );里面的四个参数搞定,这里面的四个参数后面两个参数搞定了控件的大小,前面的两个参数搞定了控件的位置。使用起来确实很方便。可是用着用着我就开始纠结了,在说出我的苦恼之前,我们再看一个图:

(图2)

我们回头在分析一下上面那三行代码

看 CGRectMake里面的参数。里面的参数都是根据屏幕大小,或者根据它的父控件,或者是它相邻控件的位置计算的,就拿imageView1 CGRectMake里面的四个参数来说:CGRectMake(kDeviceWidth/4-22, kDeviceWidth/6-22, 44, 44)

第一个参数:kDeviceWith/2  是view1的宽度,那么kDeviceWidth/4 就是view1宽度的一半 22 其实是44/2 就是imageView1宽度的一半,kDeviceWidth/4-22 就是相当于把imageView1水平方向上居中显示再view1里面,

第二个参数就是显示垂直显示在view1中。

那么我的纠结问题来了:

1 如果我不告诉你, 你知道KDeviceWidth/4-22 ,kDeviceWith/6-22 是什么意思么?纠结的问题:不知道的外人很难理解参数含义。估计时间长了,我自己都忘了是啥意思了。

2 纠结问题二 :如果实现图二的界面,还这样写?光算控件所在位置我得算到猴年马月啊,而且一不留神就容易写错。面对复杂页面:计算量大,易出错。

3 问题三:写过之后,就不想再回头看了,太乱太复杂了。代码后期不易维护。

其实以前,我就是这么天天算,算了天昏地暗啊,脑细胞死的实在太多了,最后就烦了。俗话说:叫什么水复疑无路,柳岸花明又一村(

不好意思:语文老师死的早。。。)

,正在山穷水尽之时,突然脑洞大开。于是就憋出了下面这个框架。

2 纠结之后憋出的新框架

嘿嘿 ,其实很简单,几行代码就搞定了,你可能觉得这太简单了啊,呵呵 ,我就愿意写简单而又别人不愿意写的东西。好了,我们来看一些整个框架的主要方法如下:

[objc]view plaincopy

```

#import 

@interfaceUIView (UIViewCategory)

-(void)layout_width:(float)width;//视图高度

-(void)layout_heigth:(float)heigth;//视图宽度

-(void)layout_verticalCenter;//相对于父视图垂直居中

-(void)layout_horizontalCenter;//相对于父视图水平居中

//相对父视图的位置关系

-(void)margin_top:(float)toppix;//距离父视图的上边距

-(void)margin_left:(float)leftpix;//距离父视图的左边距

-(void)margin_bottom:(float)bottompix;//距离父视图的下边距

-(void)margin_rigth:(float)rigthpix;//距离父视图的右边距

//同级相对位置关系

-(void)toleftView:(UIView*)viewofPix:(float)sizepix;//距离某视图的左部边缘距离

-(void)totopView:(UIView*)viewofPix:(float)sizepix;//距离某视图的上部边缘距离

-(void)torigthView:(UIView*)viewofPix:(float)sizepix;//距离某视图的右部边缘距离

-(void)tobottomView:(UIView*)viewofPix:(float)sizepix;//距离某视图的下部边缘距离

//同级对齐方式

-(void)aligntopwithview:(UIView*)view;//与某视图的上部边缘对齐

-(void)aligbottomnwithview:(UIView*)view;//与某视图的下部边缘对齐

-(void)alignleftwithview:(UIView*)view;//与某视图的左部边缘对齐

-(void)alignrigthwithview:(UIView*)view;//与某视图的右部边缘对齐

@end

```

解释具体作用就不用了吧,注释已经很详细了。实现文件我就不贴了,文章最后我会给出源代码下载路径。下面让我们一起来看看用此框架去实现图二的界面吧,代码如下:

[objc]view plaincopy

```

#import "ViewController.h"

#import "UIView+UIViewCategory.h"

#define kDeviceWidth [UIScreen mainScreen].bounds.size.width

#define KDeviceHeight [UIScreen mainScreen].bounds.size.height

@interfaceViewController ()

@end

@implementationViewController

- (void)viewDidLoad {

[superviewDidLoad];

self.view.backgroundColor= [UIColorclearColor];

UIView*view1= [[UIViewalloc]init];

[view1layout_width:kDeviceWidth/2];//view1的宽度

[view1layout_heigth:KDeviceHeight/3];//view1的高度

[view1margin_top:20.0f];//距离父边距上部20像素

[view1margin_left:5.0f];//距离父边距左边5像素

view1.backgroundColor= [UIColorwhiteColor];

[self.viewaddSubview:view1];

UIImageView*imageView1= [[UIImageViewalloc]init];

[view1addSubview:imageView1];

[imageView1layout_width:44];

[imageView1layout_heigth:44];

[imageView1layout_horizontalCenter];//在其父视图中水平居中 相对于CGRectMake(kDeviceWidth/4-22, kDeviceWidth/6-22, 44, 44) 是不是好理解的多啊

[imageView1layout_verticalCenter];//在其父视图中垂直居中

imageView1.image= [UIImageimageNamed:@"my_04@2x.png"];

UILabel*viewllable = [[UILabelalloc]init];

[view1addSubview:viewllable];

[viewllablelayout_heigth:20];

[viewllablelayout_width:120];

[viewllablelayout_horizontalCenter];//在父视图中水平居中 相对于CGRectMake(kDeviceWidth/4-60, kDeviceWidth/6-22+44, 120, 20) 是不是更直观啊

[viewllabletobottomView:imageView1ofPix:5.0];//左边距离imageView1 5像素,  如果用CGRectMake()你又该怎么去实现??

viewllable.text=@"我是:View1";

viewllable.textAlignment= NSTextAlignmentCenter;

UILabel*lableview1= [[UILabelalloc]init];

[self.viewaddSubview:lableview1];

[lableview1layout_width:kDeviceWidth/2-15];

[lableview1layout_heigth:KDeviceHeight/6-5];

[lableview1aligntopwithview:view1];//上边缘与view1的上边缘对齐

[lableview1torigthView:view1ofPix:5.0];//距离view1右边5像素  那么跟上面合起来就是:与view1水平对齐并且在view1的右边5像素处

lableview1.text=@"我是lable1   我与View1顶部对齐,并距离View1右边距5个像素";

lableview1.font= [UIFontboldSystemFontOfSize:15.0];

lableview1.numberOfLines=0;

lableview1.textAlignment= NSTextAlignmentCenter;

lableview1.backgroundColor= [UIColoryellowColor];

UILabel*lableview2= [[UILabelalloc]init];

[self.viewaddSubview:lableview2];

[lableview2layout_width:kDeviceWidth/2-15];

[lableview2layout_heigth:KDeviceHeight/6];

[lableview2alignleftwithview:lableview1];

[lableview2tobottomView:lableview1ofPix:5.0];

lableview2.text=@"我是lable2 我左边与lable1对齐,并距离lable1下边缘5个像素";

lableview2.font= [UIFontboldSystemFontOfSize:15.0];

lableview2.numberOfLines=0;

lableview2.textAlignment= NSTextAlignmentCenter;

lableview2.backgroundColor= [UIColoryellowColor];

UILabel*lableview3= [[UILabelalloc]init];

[self.viewaddSubview:lableview3];

[lableview3layout_heigth:KDeviceHeight/3*2];

[lableview3layout_width:kDeviceWidth-10];

[lableview3tobottomView:view1ofPix:5.0];

[lableview3margin_left:5.0];

lableview3.text=@"我是lableview3 ,他妹的.就这一行代码:[lableview3 tobottomView:view ofPix:5.0]  就把我准确的放在了View1的下面5像素的位置";

lableview3.font= [UIFontsystemFontOfSize:15.0];

lableview3.textAlignment= NSTextAlignmentCenter;

lableview3.numberOfLines=0;

lableview3.backgroundColor= [UIColororangeColor];

}

@end

```

注意看上面有两个最长的注释,我进行了对比,下面我们再尝试一下:改一下view1的上边距和左边距也就是下面两行代码,你会看到什么?:整个页面其他元素的位置都会跟着移动了。不知道这是不是改变了你曾经遇到到:改变一个控件,其他控件根本不动的情况。

[view1margin_top:20.0f];//距离父边距上部20像素

[view1margin_left:5.0f];//距离父边距左边5像素

下面让我们再看一下手机横屏下的展示效果

3  横竖屏转换下的展示效果

代码不变让我们看一下横屏显示的效果图:

( 图3 )

我擦,怎么回事,这显示的是什么东西,不对啊,页面没变啊,这是怎么回事。别着急,小小的杠杆就能撬动大大的地球,请看第三节。

3 小杠杆撬动大地球

上面我们看到那个问题了,那么该如何找到这个小杠杆呢。其实我们只要将

[objc]view plaincopy

```

#define kDeviceWidth [UIScreen mainScreen].bounds.size.width

#define KDeviceHeight [UIScreen mainScreen].bounds.size.height

```

这两个宏定义调换一下位置就行了如下:

[objc]view plaincopy

```

#define kDeviceHeight [UIScreen mainScreen].bounds.size.width

#define KDeviceWidth  [UIScreen mainScreen].bounds.size.height

```

注意:此处在UIView+UIViewCategory.m(该文件在源代码里面)的两个定义也需要调换一下。具体原因,自己慢慢思考吧。下面再看一下运行结果如下图:

(图4 横屏显示)

4 总结

框架总体思想:其实总体的框架,就是相对布局思想。

总共有两种情况下的相对布局:

1 :父视图与子视图之间的相对布局 ,主要有以下函数:

[objc]view plaincopy

```

-(void)layout_verticalCenter;//相对于父视图垂直居中

-(void)layout_horizontalCenter;//相对于父视图水平居中

//相对父视图的位置关系

-(void)margin_top:(float)toppix;//距离父视图的上边距

-(void)margin_left:(float)leftpix;//距离父视图的左边距

-(void)margin_bottom:(float)bottompix;//距离父视图的下边距

-(void)margin_rigth:(float)rigthpix;//距离父视图的右边距

```

注意:1 在布局子视图相对于父视图的位置时,要尽量用上面的方法,并且有一点要注意,要先调用  addSubView:  把子视图添加到父视图中,然后才调用上面的方法。不然的话,鬼知道你的父类视图是谁呀。

2 :同级关系的相对布局,主要有以下函数:

[objc]view plaincopy

```

//同级相对位置关系

-(void)toleftView:(UIView*)viewofPix:(float)sizepix;//距离某视图的左部边缘距离

-(void)totopView:(UIView*)viewofPix:(float)sizepix;//距离某视图的上部边缘距离

-(void)torigthView:(UIView*)viewofPix:(float)sizepix;//距离某视图的右部边缘距离

-(void)tobottomView:(UIView*)viewofPix:(float)sizepix;//距离某视图的下部边缘距离

//同级对齐方式

-(void)aligntopwithview:(UIView*)view;//与某视图的上部边缘对齐

-(void)aligbottomnwithview:(UIView*)view;//与某视图的下部边缘对齐

-(void)alignleftwithview:(UIView*)view;//与某视图的左部边缘对齐

-(void)alignrigthwithview:(UIView*)view;//与某视图的右部边缘对齐

```

注意:1 上面4个函数,分别定义了上 下 左 右 相对于同级视图的边距,其中view是同级视图,sizepix是距离同级视图的边距数。

2 下面4个函数,定义了上 下 左 右 与同级视图的对齐方式,上对齐:就是本视图的上边框,与同级视图的上边框对齐,其它的以此类推。

3 一般来说,使用上面八个函数,每两个组合就能轻松实现视图的精确定位。视图是由水平和垂直两个方向决定的,一般使用一个水平也就是左右的函数 和一个垂直的也就是上下的函数组合就能实现视图定位。

4 一个视图要么基与父视图定位,要么基于同级视图定位,不要交叉使用,不要一个视图又基于父视图定位,又基于统计视图定位,及这八个函数不要与上面那个父视图关系的四个函数同时在同一个视图上混合使用。

项目已经托管在github上了。

项目源代码地址 github:https://github.com/lerpo/ios_EasyLayout

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • 转载:http://www.cocoachina.com/swift/20161201/18198.html 前言...
    F麦子阅读 4,262评论 2 8
  • 一、初始化方法 1、- initWithFrame: UIView *view = [[UIView alloc]...
    默默_David阅读 2,458评论 1 3
  • 初识iOS APP开发#### 在iOS APP开发中, main函数仍是程序的入口和出口, 但main函数不需要...
    DeanYan阅读 6,075评论 0 3
  • 这几天一直在想一些东西 总感觉自己是直线思维 对直线思维最简单的解释就是: 爱咋的咋的 不会拐弯 不懂变通 就像线...
    大城市的小蚂蚁阅读 562评论 0 1
  • 在冬天,北方的雪应该是很常见的,可是近些年,雪却成了人们久盼不来的稀物。当天公作美,一片一片雪花翩然而至时,欣喜来...
    珠语阅读 857评论 4 4