MyLayout
MyLayout 是一个简单易用的 Objective-C 框架,用于 iOS 视图布局。MyLayout 提供了一些简单的功能来构建各种复杂的界面。它集成了以下功能:iOS 的 Autolayout 和 SizeClass,Android 的五种布局类,float 和 flex-box 以及 HTML/CSS 的 bootstrap。MyLayout 的 Swift 版本名为:TangramKit
简体中文:中文说明
用法
- 有一个容器视图 S,宽度为 100,高度为所有子视图高度的总和。存在四个从上到下排列的子视图 A、B、C、D。
- 子视图 A 的左外边距是 S 宽度的 20%,右外边距是 S 宽度的 30%,高度等于 A 的宽度。
- 子视图 B 的左外边距是 40,宽度填充到 S 的剩余宽度,高度为 40。
- 子视图 C 的宽度填充到 S,高度为 40。
- 子视图 D 的右外边距是 20,宽度是 S 宽度的 50%,高度为 40。
MyLinearLayout *S = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert];
S.subviewSpace = 10;
S.widthSize.equalTo(@100);
UIView *A = UIView.new;
A.leftPos.equalTo(@0.2);
A.rightPos.equalTo(@0.3);
A.heightSize.equalTo(A.widthSize);
[S addSubview:A];
UIView *B = UIView.new;
B.leftPos.equalTo(@40);
B.widthSize.equalTo(@60);
B.heightSize.equalTo(@40);
[S addSubview:B];
UIView *C = UIView.new;
C.leftPos.equalTo(@0);
C.rightPos.equalTo(@0);
C.heightSize.equalTo(@40);
[S addSubview:C];
UIView *D = UIView.new;
D.rightPos.equalTo(@20);
D.widthSize.equalTo(S.widthSize).multiply(0.5);
D.heightSize.equalTo(@40);
[S addSubview:D];
性能比较
创建时间(ms)/每个子视图 | 帧 | MyLayout | AutoLayout | Masonry | UIStackView |
---|---|---|---|---|---|
MyLinearLayout | 0.08 | 0.164 | 0.219 | 0.304 | 0.131 |
MyFrameLayout | 0.05 | 0.149 | 0.209 | 0.273 | 0.131 |
MyRelativeLayout | 0.079 | 0.182 | 0.116 | 0.359 | 0.131 |
MyFlowLayout | 0.08 | 0.107 | 0.198 | 0.258 | 0.131 |
MyFloatLayout | 0.044 | 0.148 | 0.203 | 0.250 | 0.131 |
布局时间(ms)/每个子视图 | 帧 | MyLayout | AutoLayout | Masonry | UIStackView |
---|---|---|---|---|---|
MyLinearLayout | 0 | 0.049 | 0.269 | 0.269 | 0.272 |
MyFrameLayout | 0 | 0.042 | 0.243 | 0.243 | 0.272 |
MyRelativeLayout | 0 | 0.068 | 0.274 | 0.274 | 0.272 |
MyFlowLayout | 0 | 0.036 | 0.279 | 0.279 | 0.272 |
MyFloatLayout | 0 | 0.055 | 0.208 | 0.208 | 0.272 |
架构
MyLayoutPos
MyLayoutPos
表示视图的位置。UIView 提供了六个扩展变量:leftPos,topPos,bottomPos,rightPos,centerXPos,centerYPos,用来设置视图的边距或与其他视图之间的空间距离。你可以使用 equalTo
方法来设置 NSNumber 或 MyLayoutPos 或 NSArrayA.leftPos.equalTo(@10); ==> A.myLeft = 10;
MyLayoutSize
MyLayoutSize
表示视图的大小。UIView 提供了两个扩展变量:widthSize,heightSize 用来设置视图的宽度和高度尺寸。你可以使用 equalTo
方法来设置 NSNumber 或 MyLayoutSize 或 NSArrayA.widthSize.equalTo(@10); ==> A.myWidth = 10;
MyLinearLayout
等同于:iOS 的 UIStackView 和 Android 的 LinearLayout。
线性布局是一个单行布局视图,子视图按照添加的顺序(从上到下或从左到右)进行排列。因此,子视图的原点和大小的约束是通过添加的顺序建立的。以从上到下排列的子视图称为垂直线性布局视图,以从左到右排列的子视图称为水平线性布局。
示例代码
-(void)loadView
{
[super loadView];
MyLinearLayout *S = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert];
S.myWidth = 120;
S.subviewSpace = 10;
UIView *A = [UIView new];
A.myLeft = A.myRight = 5;
A.myHeight = 40;
[S addSubview:A];
UIView *B = [UIView new];
B.myLeft = 20;
B.myWidth = B.myHeight = 40;
[S addSubview:B];
UIView *C = [UIView new];
C.myRight = 40;
C.myWidth = 50;
C.myHeight = 40;
[S addSubview:C];
UIView *D = [UIView new];
D.myLeft = D.myRight = 10;
D.myHeight = 40;
[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中的自动布局和Android中的相对布局。
相对布局是一种通过相互约束对子视图进行布局和定位的布局视图。相对布局中的子视图不依赖于添加的顺序,而是通过设置子视图的约束来实现布局和定位。
示例代码
-(void)loadView
{
[super loadView];
MyRelativeLayout *S = [MyRelativeLayout new];
S.widthSize.equalTo(@170);
S.heightSize.equalTo(@280);
UIView *A = [UIView new];
A.leftPos.equalTo(@20);
A.topPos.equalTo(@20);
A.widthSize.equalTo(@40);
A.heightSize.equalTo(A.widthSize);
[S addSubview:A];
UIView *B = [UIView new];
B.leftPos.equalTo(A.centerXPos);
B.topPos.equalTo(A.bottomPos).offset(10);
B.widthSize.equalTo(@60);
B.heightSize.equalTo(A.heightSize);
[S addSubview:B];
UIView *C = [UIView new];
C.leftPos.equalTo(B.rightPos).offset(10);
C.bottomPos.equalTo(B.bottomPos);
C.widthSize.equalTo(@40);
C.heightSize.equalTo(B.heightSize).multiply(0.5);
[S addSubview:C];
UIView *D = [UIView new];
D.bottomPos.equalTo(C.topPos).offset(10);
D.rightPos.equalTo(@15);
D.heightSize.equalTo(A.heightSize);
D.widthSize.equalTo(D.heightSize);
[S addSubview:D];
UIView *E = [UIView new];
E.centerYPos.equalTo(@0);
E.centerXPos.equalTo(@0);
E.heightSize.equalTo(@40);
E.widthSize.equalTo(S.widthSize).add(-20);
[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。
Frame布局是一种子视图可以在父视图的特定位置重叠并设置重力的布局视图。子视图的布局位置和大小不依赖于添加的顺序,并且通过与父视图建立依赖关系约束。Frame布局将垂直方向分为顶部、垂直居中和底部,而水平方向分为左侧、水平居中和右侧。任何子视图都在垂直方向或水平方向上设置重力。
示例代码
-(void)loadView
{
[super loadView];
MyFrameLayout *S = [MyFrameLayout new];
S.mySize = CGSizeMake(320,500);
UIView *A = [UIView new];
A.mySize = CGSizeMake(40,40);
[S addSubview:A];
UIView *B = [UIView new];
B.mySize = CGSizeMake(40,40);
B.myRight = 0;
[S addSubview:B];
UIView *C = [UIView new];
C.mySize = CGSizeMake(40,40);
C.myCenterY = 0;
[S addSubview:C];
UIView *D = [UIView new];
D.mySize = CGSizeMake(40,40);
D.myCenter = 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中的表格。
表格布局是一种将子视图多行多列排列成表格形式的布局视图。首先必须创建一个行视图并将其添加到表格布局中,然后将子视图添加到行视图中。如果行视图按从上到下的顺序排列,该表格视图称为垂直表格布局,其中子视图从左到右排列;如果行视图按从左到右的顺序排列,该表格视图称为水平表格布局,其中子视图从上到下排列。
示例代码
-(void)loadView
{
[super loadView];
MyTableLayout *S = [MyTableLayout tableLayoutWithOrientation:MyOrientation_Vert];
S.wrapContentWidth = YES;
S.subviewHSpace = 10;
S.subviewVSpace = 10;
[S addRow:MyLayoutSize.wrap colSize:MyLayoutSize.wrap];
UIView *A = [UIView new];
A.mySize = CGSizeMake(50,40);
[S addSubview:A];
UIView *B = [UIView new];
B.mySize = CGSizeMake(100,40);
[S addSubview:B];
UIView *C = [UIView new];
C.mySize = CGSizeMake(30,40);
[S addSubview:C];
[S addRow:MyLayoutSize.wrap colSize:MyLayoutSize.wrap];
UIView *D = [UIView new];
D.mySize = CGSizeMake(200,40);
[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中的flexbox。
流式布局是一种多行布局视图,其中的子视图按添加顺序排列,当遇到排列约束时,将开始新的一行并重新排列。这里提到的约束包括数量约束和大小约束。新行的方向可以是垂直或水平,因此流式布局可以分为:数量约束垂直流式布局、大小约束垂直流式布局、数量约束水平流式布局、大小约束水平流式布局。流式布局常用于子视图规则排列的场景,在某种程度上可以替代UICollectionView。MyFlowLayout几乎实现了HTML/CSS的flex-box功能。
示例代码
-(void)loadView
{
[super loadView];
MyFlowLayout *S = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:4];
S.wrapContentHeight = YES;
S.myWidth = 300;
S.padding = UIEdgeInsetsMake(10, 10, 10, 10);
S.gravity = MyGravity_Horz_Fill;
S.subviewSpace = 10;
for (int i = 0; i < 10; i++)
{
UIView *A = [UIView new];
A.heightSize.equalTo(A.widthSize);
[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:MyOrientation_Vert];
S.wrapContentHeight = YES;
S.padding = UIEdgeInsetsMake(10, 10, 10, 10);
S.subviewSpace = 10;
S.myWidth = 300;
UIView *A = [UIView new];
A.mySize = CGSizeMake(80,70);
[S addSubview:A];
UIView *B = [UIView new];
B.mySize = CGSizeMake(150,40);
[S addSubview:B];
UIView *C = [UIView new];
C.mySize = CGSizeMake(70,40);
[S addSubview:C];
UIView *D = [UIView new];
D.mySize = CGSizeMake(100,140);
[S addSubview:D];
UIView *E = [UIView new];
E.mySize = CGSizeMake(150,40);
E.reverseFloat = YES;
[S addSubview:E];
UIView *F = [UIView new];
F.mySize = CGSizeMake(120,60);
[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
是iOS的一种独特特性布局视图。
路径布局是一种布局视图,其中的子视图根据指定的路径曲线进行布局。您必须提供一种函数方程、坐标和距离设置类型来创建路径曲线,使所有子视图在路径布局中距离相等。路径布局通常用于创建一些不规则且美观的UI布局。
示例代码
-(void)loadView
{
[super loadView];
MyPathLayout *S = [MyPathLayout new];
S.mySize = CGSizeMake(320,320);
S.coordinateSetting.isReverse = YES;
S.coordinateSetting.origin = CGPointMake(0.5, 0.2);
S.polarEquation = ^(CGFloat angle)
{
return 80 * (1 + cos(angle));
};
for (int i = 0; i < 4; i++)
{
UIView *A = [UIView new];
A.mySize = CGSizeMake(40,40);
[S addSubview:A];
A.backgroundColor = [UIColor greenColor];
}
[self.view addSubview:S];
S.backgroundColor = [UIColor redColor];
}
MyGridLayout
是iOS的一种独特特性布局视图。
网格布局是一种视图,根据行或列划分成多个子区域,子区域根据布局需求可以继续递归划分,网格布局内部的子视图将按顺序添加到相应的叶区域中填充布局机制。网格布局通过一套自定义布局系统,添加到网格布局内部的子视图不再需要指定位置和大小,而是由网格布局的网格完成,因此可以非常方便地调整布局结构,从而实现动态布局的能力。
示例代码
-(void)loadView
{
[super loadView];
MyGridLayout *S = [MyGridLayout new];
S.mySize = CGSizeMake(320,320);
S.backgroundColor = [UIColor redColor];
[self.view addSubview:S];
//add grids
[S addRow:50];
id<MyGrid> g2 = [S addRow:MyLayoutSize.fill];
[g2 addCol:0.2];
[g2 addCol:0.2];
id<MyGrid> g23 = [g2 addCol:0.6];
[g23 addRow:0.5];
[g23 addRow:0.5];
//add subviews
UIView *A = [UIView new];
A.backgroundColor = [UIColor greenColor];
[S addSubview:A];
UIView *B = [UIView new];
B.backgroundColor = [UIColor blueColor];
[S addSubview:B];
UIView *C = [UIView new];
C.backgroundColor = [UIColor orangeColor];
[S addSubview:C];
UIView *D = [UIView new];
D.backgroundColor = [UIColor cyanColor];
[S addSubview:D];
UIView *E = [UIView new];
E.backgroundColor = [UIColor blackColor];
[S addSubview:E];
}
MySizeClass
等同于:iOS的大小类别。
MyLayout为适应不同屏幕尺寸提供了对SizeClass的支持。您可以将SizeClass与上述6种布局视图中的任何一种结合,以完美适配所有设备的UI。提供以下两种UIView扩展方法
-(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass;
-(instancetype)fetchLayoutSizeClass:(MySizeClass)sizeClass copyFrom:(MySizeClass)srcSizeClass;
来设置类似以下的SizeClass特性
//default is all Size Classes
MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert];
rootLayout.padding = UIEdgeInsetsMake(10, 10, 10, 10);
rootLayout.wrapContentHeight = NO;
rootLayout.gravity = MyGravity_Horz_Fill;
//MySizeClass_wAny | MySizeClass_hCompact is iPhone landscape orientation.
MyLinearLayout *lsc = [rootLayout fetchLayoutSizeClass:MySizeClass_wAny | MySizeClass_hCompact copyFrom:MySizeClass_wAny | MySizeClass_hAny];
lsc.orientation = MyOrientation_Horz;
lsc.wrapContentWidth = NO;
lsc.gravity = MyGravity_Vert_Fill;
演示示例
如何开始
下载MyLayout并尝试内置的iPad和iPhone示例应用。阅读常见问题解答或下面的文章
http://www.jianshu.com/p/4c1eb0dd676f 关于布局框架和原理的介绍
http://blog.csdn.net/yangtiang/article/details/46483999 线性布局
http://blog.csdn.net/yangtiang/article/details/46795231 相对布局
http://blog.csdn.net/yangtiang/article/details/46492083 表框架布局
http://blog.csdn.net/yangtiang/article/details/48011431 表格布局
http://blog.csdn.net/yangtiang/article/details/50652946 流式布局
http://www.jianshu.com/p/0c075f2fdab2 浮动布局 http://www.jianshu.com/p/4ac229057396 路径布局
因为我英语能力有限,所以只能支持中文文章。希望有人能帮助我将其翻译成英文。
通讯
- 如有需要帮助,请使用Stack Overflow或百度。(标签'mylayout')
- 如想联系我,请使用qq:156355113 或 weibo:欧阳大哥 或 邮箱:[email protected]
- 如果您发现了一个错误,并且能够提供可靠的复制步骤,请打开一个问题。
- 如果您有功能请求,请打开一个问题。
- 如果您想做出贡献,请提交一个拉取请求。
安装
MyLayout 支持在项目中安装库的多种方法。
复制到您的项目
- 将示例项目中的
Lib
文件夹复制到您的项目中 - 将
#import "MyLayout.h"
添加到您项目的 PCH 文件或引用的头部文件中。
CocoaPods 安装
CocoaPods 是 Objective-C 的依赖管理工具,它可以自动化和简化在项目中使用第三方库(如 MyLayout)的过程。您可以使用以下命令安装它
$ gem install cocoapods
要使用 CocoaPods 将 MyLayout 集成到您的 Xcode 项目中,请在您的 Podfile 中指定它
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '7.0'
pod 'MyLayout'
然后,运行以下命令
$ pod install
Carthage
使用-
创建一个
Cartfile
文件。github "youngsoft/MyLinearLayout"
-
运行
carthage update
。 -
在您应用程序目标的“常规”设置选项卡中,在“链接框架和库”部分,将
MyLayout
框架从磁盘上的 Carthage/Build 文件夹拖放到应用目标中。 -
在您应用程序目标的“构建阶段”设置选项卡中,单击“+”图标并选择“新建运行脚本阶段”。在脚本区域下方指定您的 shell(例如 bin/sh),并将以下内容添加到脚本区域下
/usr/local/bin/carthage copy-frameworks
并将路径添加到“输入文件”下,例如
$(SRCROOT)/Carthage/Build/iOS/MyLayout.framework
常见问题解答
- 如果您使用MyLayout运行时出现100% CPU使用率问题并提示出现了约束冲突,请检查子视图的约束集。
- 如果您使用MyLayout,在MyBaseLayout的willMoveToSuperview方法中抛出异常。这无妨,只需在CMD+7中移除异常断点设置即可。
- 在布局视图中设置wrapConentWidth或wrapContentHeight的同时设置widthSize或heightSize可能会导致约束冲突。
- 如果您将布局视图设置为UIViewController的根视图,请将wrapContentWidth和wrapContentHeight设置为NO。
- 只有MyLinearLayout和MyFrameLayout的子视图支持相对外边距。
- 如果子视图添加到布局视图中,使用setFrame方法时不能设置原点位置,只能设置大小。
许可协议
MyLayout使用MIT许可协议发布。有关详细信息,请参阅LICENSE文件。