简介

MyLayout是一套iOS界面视图布局框架。其内核是基于对UIView的layoutSubviews方法的重载以及对子视图的bounds和center属性的设置而实现的。MyLayout功能强大而且简单易用,它集成了iOS Autolayout和Size Classes、android的5大布局体系、HTML/CSS的浮动定位技术以及flex-box和bootstrap框架等市面上主流的平台的界面布局功能,同时提供了一套非常简单和完备的多屏幕尺寸适配的解决方案。MyLayout还提供了Swift版本TangramKit

MyLayout的优势

  • MyLayout的实现内核是基于frame的设置,而不是对AutoLayout的封装。因此在使用上不会受到任何操作系统版本的限制。
  • 有文章表明用frame进行布局的性能要高于用AutoLayout进行布局的性能,尤其是当界面内视图数量增加时效果更加明显。
  • AutoLayout的思想是通过视图之间的约束依赖来完成布局,但是约束依赖的结果是造成视图之间的耦合性高而增大了界面更新的成本。而MyLayout则除了提供约束依赖外,还提供了根据视图添加顺序自动建立约束的功能,从而减少了这种显示依赖关系建立的问题,最终的结果是简化了布局的代码量,以及减少了布局更新时的代码修改量。
  • AutoLayout只是一种相对约束的布局,而MyLayout除了同时提供具有和AutoLayout相同能力的相对布局外、还提供了线性布局、框架布局、表格布局、流式布局、浮动布局、路径布局7大布局体系,你完全可以根据你的界面需求来选择一种最简易的布局容器来实现你的功能,同时MyLayout还支持Size classes的机制,以及提供了一些实现屏幕尺寸完美适配的方法。
  • MyLayout主要是一种通过代码进行布局的解决方案,但是框架一样可以支持和XIB以及SB结合布局的方式。并提供了视图隐藏和显示时会自动激发布局、布局视图的高度自适应(UITableviewCell动态高度)、标签云实现、左右内容宽度自适应、按比例分配尺寸和间距、整体停靠控制等等各种强大的功能。

AutoLayout和frame布局的性能比较

 

 

参考的文章地址:http://floriankugler.com/2013/04/22/auto-layout-performance-on-ios/

应用场景

举例下面一个应用场景:

  • 有一个容器视图S的宽度是100而高度则是由四个从上到下依次排列的子视图A,B,C,D的高度总和。
  • 视图A的左边距占用父视图宽度的20%,而右边距则占用父视图宽度的30%,高度则等于自身的宽度。
  • 视图B的左边距是40,宽度则占用父视图的剩余宽度,高度是40。
  • 视图C的宽度占用父视图的所有宽度,高度是40。
  • 视图D的右边距是20,宽度是父视图宽度的50%,高度是40。

最终的效果图如下:

 MyLinearLayout *S = [MyLinearLayout linearLayoutWithOrientation:MyLayoutViewOrientation_Vert];
S.subviewMargin = ;
S.myWidth = ; UIView *A = UIView.new;
A.leftPos.equalTo(@0.2);
A.rightPos.equalTo(@0.3);
A.heightDime.equalTo(A.widthDime);
[S addSubview:A]; UIView *B = UIView.new;
B.leftPos.equalTo(@);
B.widthDime.equalTo(@);
B.heightDime.equalTo(@);
[S addSubview:B]; UIView *C = UIView.new;
C.widthDime.equalTo(S.widthDime);
C.heightDime.equalTo(@);
[S addSubview:C]; UIView *D = UIView.new;
D.rightPos.equalTo(@);
D.widthDime.equalTo(S.widthDime).multiply(0.5);
D.heightDime.equalTo(@);
[S addSubview:D];

系统结构

布局位置类MyLayoutPos

MyLayoutPos类是用来描述一个视图所在的位置的类。UIView中扩展出了leftPos,topPos,bottomPos,rightPos,centerXPos,centerYPos这六个变量来实现视图的定位操作。您可以用这些变量的equalTo方法来设置视图之间的边距和间距。 equalTo 方法可以设置NSNumber, MyLayoutPos, NSArray<MyLayoutPos*>这几种值,分别用于不同的场景。同时系统提供了6个简单的变量myLeftMargin, myTopMargin, myBottomMargin, myRightMargin, myCenterXOffset, mYCenterYOffset来设置NSNumber类型的值,比如 A.leftPos.equalTo(@10); 等价于 A.myLeftMargin = 10;.

布局尺寸类MyLayoutSize

MyLayoutSize类是用来描述一个视图的尺寸的类。UIView中扩展出了widthDime,heightDime这两个变量来实现视图的宽度和高度尺寸的设置。您可以用其中的equalTo方法来设置视图的宽度和高度。equalTo方法可以设置NSNumber, MyLayoutSize, NSArray<MyLayoutSize*>这几种值,分别用于不同的场景。同时系统提供了2个简单的变量myWidth,myHeight来设置NSNumber类型的值,比如A.widthDime.equalTo(@10); 等价于A.myWidth = 10;.

线性布局MyLinearLayout

等价于iOS的UIStackView和android的LinearLayout布局。

线性布局是一种里面的子视图按添加的顺序从上到下或者从左到右依次排列的单列(单行)布局视图,因此里面的子视图是通过添加的顺序建立约束和依赖关系的。 子视图从上到下依次排列的线性布局视图称为垂直线性布局视图,而子视图从左到右依次排列的线性布局视图则称为水平线性布局。

示例代码:

-(void)loadView
{
[super loadView]; MyLinearLayout *S = [MyLinearLayout linearLayoutWithOrientation:MyLayoutViewOrientation_Vert];
S.myWidth = ;
S.subviewMargin = ; UIView *A = [UIView new];
A.myLeftMargin = A.myRightMargin = ;
A.myHeight = ;
[S addSubview:A]; UIView *B = [UIView new];
B.myLeftMargin = ;
B.myWidth = B.myHeight = ;
[S addSubview:B]; UIView *C = [UIView new];
C.myRightMargin = ;
C.myWidth = ;
C.myHeight = ;
[S addSubview:C]; UIView *D = [UIView new];
D.myLeftMargin = D.myRightMargin = ;
D.myHeight = ;
[S addSubview:D]; [self.view addSubview:S];
S.backgroundColor = [UIColor redColor];
A.backgroundColor = [UIColor greenColor];
B.backgroundColor = [UIColor blueColor];
C.backgroundColor = [UIColor orangeColor];
D.backgroundColor = [UIColor cyanColor];
}

相对布局MyRelativeLayout

等价于iOS的AutoLayout 和 Android的RelativeLayout布局。

相对布局是一种里面的子视图通过相互之间的约束和依赖来进行布局和定位的布局视图。相对布局里面的子视图的布局位置和添加的顺序无关,而是通过设置子视图的相对依赖关系来进行定位和布局的。

示例代码:

-(void)loadView
{
[super loadView]; MyRelativeLayout *S = [MyRelativeLayout new];
S.widthDime.equalTo(@);
S.heightDime.equalTo(@); UIView *A = [UIView new];
A.leftPos.equalTo(@);
A.topPos.equalTo(@);
A.widthDime.equalTo(@);
A.heightDime.equalTo(A.widthDime);
[S addSubview:A]; UIView *B = [UIView new];
B.leftPos.equalTo(A.centerXPos);
B.topPos.equalTo(A.bottomPos).offset();
B.widthDime.equalTo(@);
B.heightDime.equalTo(A.heightDime);
[S addSubview:B]; UIView *C = [UIView new];
C.leftPos.equalTo(B.rightPos).offset();
C.bottomPos.equalTo(B.bottomPos);
C.widthDime.equalTo(@);
C.heightDime.equalTo(B.heightDime).multiply(0.5);
[S addSubview:C]; UIView *D = [UIView new];
D.bottomPos.equalTo(C.topPos).offset();
D.rightPos.equalTo(@);
D.heightDime.equalTo(A.heightDime);
D.widthDime.equalTo(D.heightDime);
[S addSubview:D]; UIView *E = [UIView new];
E.centerYPos.equalTo(@);
E.centerXPos.equalTo(@);
E.heightDime.equalTo(@);
E.widthDime.equalTo(S.widthDime).add(-);
[S addSubview:E];
//.. F, G [self.view addSubview:S];
S.backgroundColor = [UIColor redColor];
A.backgroundColor = [UIColor greenColor];
B.backgroundColor = [UIColor blueColor];
C.backgroundColor = [UIColor orangeColor];
D.backgroundColor = [UIColor cyanColor];
E.backgroundColor = [UIColor magentaColor];
}

框架布局MyFrameLayout

等价于Android的FrameLayout布局。

框架布局是一种里面的子视图停靠在父视图特定方位并且可以重叠的布局视图。框架布局里面的子视图的布局位置和添加的顺序无关,只跟父视图建立布局约束依赖关系。框架布局将垂直方向上分为上、中、下三个方位,而水平方向上则分为左、中、右三个方位,任何一个子视图都只能定位在垂直方向和水平方向上的一个方位上。

示例代码:

 -(void)loadView
{
[super loadView]; MyFrameLayout *S = [MyFrameLayout new];
S.mySize = CGSizeMake(,); UIView *A = [UIView new];
A.mySize = CGSizeMake(,);
[S addSubview:A]; UIView *B = [UIView new];
B.mySize = CGSizeMake(,);
B.myRightMargin = ;
[S addSubview:B]; UIView *C = [UIView new];
C.mySize = CGSizeMake(,);
C.myCenterYOffset = ;
[S addSubview:C]; UIView *D = [UIView new];
D.mySize = CGSizeMake(,);
D.myCenterOffset = CGPointZero;
[S addSubview:D]; //..E,F,G [self.view addSubview:S];
S.backgroundColor = [UIColor redColor];
A.backgroundColor = [UIColor greenColor];
B.backgroundColor = [UIColor blueColor];
C.backgroundColor = [UIColor orangeColor];
D.backgroundColor = [UIColor cyanColor];
}

表格布局MyTableLayout

等价于Android的TableLayout布局和HTML的table元素。

表格布局是一种里面的子视图可以像表格一样多行多列排列的布局视图。子视图添加到表格布局视图前必须先要建立并添加行视图,然后再将子视图添加到行视图里面。如果行视图在表格布局里面是从上到下排列的则表格布局为垂直表格布局,垂直表格布局里面的子视图在行视图里面是从左到右排列的;如果行视图在表格布局里面是从左到右排列的则表格布局为水平表格布局,水平表格布局里面的子视图在行视图里面是从上到下排列的。

示例代码:

-(void)loadView
{
[super loadView]; MyTableLayout *S = [MyTableLayout tableLayoutWithOrientation:MyLayoutViewOrientation_Vert];
S.wrapContentWidth = YES;
S.rowSpacing = ;
S.colSpacing = ; [S addRow:MTLSIZE_WRAPCONTENT colSize:MTLSIZE_WRAPCONTENT]; UIView *A = [UIView new];
A.mySize = CGSizeMake(,);
[S addSubview:A]; UIView *B = [UIView new];
B.mySize = CGSizeMake(,);
[S addSubview:B]; UIView *C = [UIView new];
C.mySize = CGSizeMake(,);
[S addSubview:C]; [S addRow:MTLSIZE_WRAPCONTENT colSize:MTLSIZE_WRAPCONTENT]; UIView *D = [UIView new];
D.mySize = CGSizeMake(,);
[S addSubview:D]; //...E,F [self.view addSubview:S];
S.backgroundColor = [UIColor redColor];
A.backgroundColor = [UIColor greenColor];
B.backgroundColor = [UIColor blueColor];
C.backgroundColor = [UIColor orangeColor];
D.backgroundColor = [UIColor cyanColor];
}

流式布局MyFlowLayout

等价于CSS3的flex-box。

流式布局是一种里面的子视图按照添加的顺序依次排列,当遇到某种约束限制后会另起一行再重新排列的多行展示的布局视图。这里的约束限制主要有数量约束限制和内容尺寸约束限制两种,而换行的方向又分为垂直和水平方向,因此流式布局一共有垂直数量约束流式布局、垂直内容约束流式布局、水平数量约束流式布局、水平内容约束流式布局。流式布局主要应用于那些子视图有规律排列的场景,在某种程度上可以作为UICollectionView的替代品。

示例代码:

-(void)loadView
{
[super loadView]; MyFlowLayout *S = [MyFlowLayout flowLayoutWithOrientation:MyLayoutViewOrientation_Vert arrangedCount:];
S.wrapContentHeight = YES;
S.myWidth = ;
S.padding = UIEdgeInsetsMake(, , , );
S.gravity = MyMarginGravity_Horz_Fill;
S.subviewMargin = ; for (int i = ; i < ; i++)
{
UIView *A = [UIView new];
A.heightDime.equalTo(A.widthDime);
[S addSubview:A]; A.backgroundColor = [UIColor greenColor]; } [self.view addSubview:S];
S.backgroundColor = [UIColor redColor];
}

浮动布局MyFloatLayout

等价于css中的float定位。

浮动布局是一种里面的子视图按照约定的方向浮动停靠,当尺寸不足以被容纳时会自动寻找最佳的位置进行浮动停靠的布局视图。浮动布局的理念源于HTML/CSS中的浮动定位技术,因此浮动布局可以专门用来实现那些不规则布局或者图文环绕的布局。根据浮动的方向不同,浮动布局可以分为左右浮动布局和上下浮动布局。

示例代码:

-(void)loadView
{
[super loadView]; MyFloatLayout *S = [MyFloatLayout floatLayoutWithOrientation:MyLayoutViewOrientation_Vert];
S.wrapContentHeight = YES;
S.padding = UIEdgeInsetsMake(, , , );
S.subviewMargin = ;
S.myWidth = ; UIView *A = [UIView new];
A.mySize = CGSizeMake(,);
[S addSubview:A]; UIView *B = [UIView new];
B.mySize = CGSizeMake(,);
[S addSubview:B]; UIView *C = [UIView new];
C.mySize = CGSizeMake(,);
[S addSubview:C]; UIView *D = [UIView new];
D.mySize = CGSizeMake(,);
[S addSubview:D]; UIView *E = [UIView new];
E.mySize = CGSizeMake(,);
E.reverseFloat = YES;
[S addSubview:E]; UIView *F = [UIView new];
F.mySize = CGSizeMake(,);
[S addSubview:F]; [self.view addSubview:S];
S.backgroundColor = [UIColor redColor];
A.backgroundColor = [UIColor greenColor];
B.backgroundColor = [UIColor blueColor];
C.backgroundColor = [UIColor orangeColor];
D.backgroundColor = [UIColor cyanColor];
E.backgroundColor = [UIColor blackColor];
F.backgroundColor = [UIColor whiteColor];
}

路径布局MyPathLayout

布局库独有

路径布局是一种里面的子视图根据您提供的一条特定的曲线函数形成的路径来进行布局的布局视图。您需要提供一个实现曲线路径的函数、一个特定的坐标体系、一种特定的子视图在曲线上的距离设置这三个要素来实现界面布局。当曲线路径形成后,子视图将按相等的距离依次环绕着曲线进行布局。路径布局主要应用于那些具有特定规律的不规则排列,而且效果很酷炫的的界面布局。

示例代码:

 -(void)loadView
{
[super loadView]; MyPathLayout *S = [MyPathLayout new];
S.mySize = CGSizeMake(,);
S.coordinateSetting.isReverse = YES;
S.coordinateSetting.origin = CGPointMake(0.5, 0.2); S.polarEquation = ^(CGFloat angle)
{
return * ( + cos(angle));
}; for (int i = ; i < ; i++)
{
UIView *A = [UIView new];
A.mySize = CGSizeMake(,);
[S addSubview:A]; A.backgroundColor = [UIColor greenColor];
} [self.view addSubview:S];
S.backgroundColor = [UIColor redColor];
}

Size Classes的支持

等价于iOS的Size Classes

MyLayout布局体系为了实现对不同屏幕尺寸的设备进行适配,提供了对Size Classes的支持。您可以将Size Classes和上述的6种布局搭配使用,以便实现各种设备界面的完美适配。系统提供2个UIView的扩展方法:

-(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass;
-(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass copyFrom:(MySizeClass)srcSizeClass;
 

来实现对Size Classes的支持。比如下面的例子:

//默认所有设备的设置。
MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyLayoutViewOrientation_Vert];
rootLayout.padding = UIEdgeInsetsMake(, , , );
rootLayout.wrapContentHeight = NO;
rootLayout.gravity = MyMarginGravity_Horz_Fill; //MySizeClass_wAny | MySizeClass_hCompact 表明的是iPhone设备的横屏.
MyLinearLayout *lsc = [rootLayout fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact copyFrom:MySizeClass_wAny | MySizeClass_hAny]; lsc.orientation = MyLayoutViewOrientation_Horz;
lsc.wrapContentWidth = NO;
lsc.gravity = MyMarginGravity_Vert_Fill;

使用方法

直接拷贝

  1. 将github工程中的Lib文件夹下的所有文件复制到您的工程中。
  2. #import "MyLayout.h" 头文件放入到您的pch文件中,或者在需要使用界面布局的源代码位置。

CocoaPods安装

如果您还没有安装cocoapods则请先执行如下命令:

$ gem install cocoapods

为了用CocoaPods整合MyLayout到您的Xcode工程, 请建立如下的Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '7.0' pod 'MyLayout', '~> 1.3.4'

然后运行如下命令:

$ pod install

演示效果图

 

链接:

欢迎大家访问我的github站点,并关注@欧阳大哥

iOS下的界面布局利器-MyLayout布局框架的更多相关文章

  1. iOS学习——布局利器Masonry框架源码深度剖析

    iOS开发过程中很大一部分内容就是界面布局和跳转,iOS的布局方式也经历了 显式坐标定位方式 --> autoresizingMask --> iOS 6.0推出的自动布局(Auto La ...

  2. IOS开发之绝对布局和相对布局(屏幕适配)

    之前如果做过Web前端页面的小伙伴们,看到绝对定位和相对定位并不陌生,并且使用起来也挺方便.在IOS的UI设计中也有绝对定位和相对定位,和我们的web前端的绝对定位和相对定位有所不同但又有相似之处.下 ...

  3. Flex:CSS3布局利器

    实习以来做了三个小控件,都是用的CSS2.1里传统的DIV+CSS布局方式,综合使用position.margin.float.BFC等属性或特性将元素放到指定的位置上.然而面对日益复杂的界面,这些来 ...

  4. 十. 图形界面(GUI)设计5.布局设计

    在界面设计中,一个容器要放置许多组件,为了美观,为组件安排在容器中的位置,这就是布局设计.java.awt中定义了多种布局类,每种布局类对应一种布局的策略.常用的有以下布局类: FlowLayout, ...

  5. Qt编写数据可视化大屏界面电子看板5-恢复布局

    一.前言 恢复布局这个功能在整个数据可视化大屏界面电子看板系统中非常有用,很多时候不小心把现有布局拖动乱了,(当然如果不想布局被拖动改动,可以修改配置文件中的MoveEnable参数来控制,默认为真表 ...

  6. Qt编写数据可视化大屏界面电子看板3-新建布局

    一.前言 能够新建布局,也是数据可视化大屏界面电子看板系统中的必备功能之一,新建布局这样的功能一般做到右键菜单中,单击新建布局菜单,弹出输入框要求输入新的布局的名称,为了更符合国情,直接支持中文名称, ...

  7. 三十三、Java图形化界面设计——布局管理器之null布局(空布局)

    摘自http://blog.csdn.net/liujun13579/article/details/7774267 三十三.Java图形化界面设计--布局管理器之null布局(空布局) 一般容器都有 ...

  8. 表格布局扩展/DW设计界面中快速整体布局页面的操作

    DW设计界面中快速整体布局页面的操作流程: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &q ...

  9. iOS系列译文:自定义Collection View布局

    原文出处: Ole Begemann   译文出处: 黄爱武(@answer-huang).欢迎加入技术翻译小组. UICollectionView在iOS6中第一次被介绍,也是UIKit视图类中的一 ...

随机推荐

  1. 解剖 Elasticsearch 集群 - 之三

    解剖 Elasticsearch 集群 - 之三 本篇文章是一系列涵盖 Elasticsearch 底层架构和原型示例的其中一篇.在本篇文章中,我们会讨论 Elasticsearch 如何提供准实时搜 ...

  2. 我用Cocos2d-x模拟《Love Live!学院偶像祭》的Live场景(三)

    [前言和思路整理] 千呼万唤Shi出来啊(好像也没人呼唤),最近公司项目紧,闲暇时间少更得慢,请见谅. 上一章我们分析并实现了打击物件类BeatObject,和它的父节点BeatObjectColum ...

  3. ThinkPHP--IS_AJAX

    增加IS_GET,IS_POST,IS_PUT,IS_DELETE,IS_AJAX常量,方便除控制器外的地方判断方法,Action类的isGet isPost等方法暂时保留,但不建议使用.

  4. Bootstrap入门(五)表单

    Bootstrap入门(五)表单   先引入本地的CSS文件  <link href="css/bootstrap.min.css" rel="stylesheet ...

  5. SpringMVC+RestFul详细示例实战教程

    一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于SpringMVC的配置 <!--conf ...

  6. 不要怂,就是GAN (生成式对抗网络) (四):训练和测试 GAN

    在 /home/your_name/TensorFlow/DCGAN/ 下新建文件 train.py,同时新建文件夹 logs 和文件夹 samples,前者用来保存训练过程中的日志和模型,后者用来保 ...

  7. Vue框架Element的事件传递broadcast和dispatch方法分析

    前言 最近在学习饿了么的Vue前端框架Element,发现其源码中大量使用了$broadcast和$dispatch方法,而Element使用的是Vue2.0版本,众所周知在Vue 1.0升级到2.0 ...

  8. PHP标准库(SPL)- SplDoublyLinkedList类(双向链表)

    class SplDoublyLinkedList implements Iterator, Traversable, Countable, ArrayAccess { const IT_MODE_L ...

  9. 时间处理之strtotime

    strtotime (PHP 4, PHP 5, PHP 7)strtotime - 将任何英文文本的日期时间描述解析为 Unix 时间戳说明 int strtotime ( string $time ...

  10. DOM遍历

    前面的话 DOM遍历模块定义了用于辅助完成顺序遍历DOM结构的类型:Nodeiterator和TreeWalker,它们能够基于给定的起点对DOM结构执行深度优先(depth-first)的遍历操作. ...