iOS OC swift MyLayout早期自动布局框架(不是Masonry)
一、简介
1、 MyLayout
是一套iOS界面视图布局框架。MyLayout
的内核是基于frame
的设置,对UIView
的layoutSubviews
方法的重载以及对子视图的bounds
和center
属性的设置而实现的。MyLayout
功能强大而且简单易用,它集成了:iOS Autolayout
和SizeClass
、android的5大布局体系、HTML/CSS的浮动定位技术以及flex-box和bootstrap框架等市面上主流的平台的界面布局功能,同时提供了一套非常简单和完备的多屏幕尺寸适配的解决方案
二、详解
(一)、线性布局(MyLinearLayout)
1、支持垂直布局(从上到下)和水平布局(从左到右)
2、可以通过调整间距和边距来调整子视图位置
3、可以通过equalizeSubviews
方法均分视图(不)居中
4、可以通过equalizeSubviewsSpace
方法均分间距(不)居中
5、可以通过setSubviewsSize
方法实现固定宽度浮动间距效果
6、可以通过gravity
控制布局视图里面的子视图停靠方向和子视图填充方式
(二)、框架布局(MyFrameLayout)
1、框架布局中的子视图可以层叠显示
2、框架布局里面的所有子视图的布局位置都只跟框架布局相关
(三)、相对布局(MyRelativeLayout)
1、子视图整体水平居中,通过为centerXPos等于一个数组值,子视图的间距通过offset来定义,如下
v1.centerXPos.equalTo(@[v2.centerXPos.offset(20)]);//关键字centerXPos
2、子视图整体垂直居中,通过为centerYPos等于一个数组值,子视图的间距通过offset来定义,如下
v1.centerYPos.equalTo(@[v2.centerYPos.offset(20)]);//关键字centerYPos
3、子视图宽度均分,通过widthSize等于一个数组值,如果子视图间有间距,需要add(-sapce),如下
a、v1、v2、v3均分父视图
v1.widthSize.equalTo(@[v2.widthSize.add(-10), v3.widthSize.add(-10)]).add(-10);
b、按比例均分的话, v7,v8,v9按照2:3:5的比例均分父视图。
v7.widthSize.equalTo(@[v8.widthSize.multiply(0.3).add(-10),v9.widthSize.multiply(0.5).add(-10)]).multiply(0.2).add(-10);
c、v4固定宽度,v5、v6均分
v5.widthSize.equalTo(@[v4.widthSize.add(-10), v6.widthSize.add(-10)]).add(-10);
noLayout
属性配合frame
来实现a、当
noLayout=YES
,布局约束失效,设置frame实现停靠b、当
noLayout=NO
,布局约束生效,frame属性失效,实现滚动- (void)scrollViewDidScroll:(UIScrollView *)scrollView { //testTopDockView的上面视图是testView1。所以这里如果偏移超过testView1的最大则开始固定testTopDockView了 if (scrollView.contentOffset.y > CGRectGetMaxY(self.testView1.frame)) { self.testTopDockView.noLayout = YES; CGRect rect = self.testTopDockView.frame; self.testTopDockView.frame = CGRectMake(rect.origin.x, scrollView.contentOffset.y, rect.size.width, rect.size.height); //这里可以自由设置位置和尺寸了。 } else { //当滚动的偏移小于90后,我们将testTopDocView的noLayout设置回NO,这样这个视图就又会根据所设置的约束而受到布局视图的约束和控制了,这时候frame的设置将不再起作用了。 self.testTopDockView.noLayout = NO; } }
5、边界约束,可通过uBound
最大值约束和lBound
最小值约束,来约束子视图不能大于或者小于父容器、不能大于或者小于兄弟视图的上、左、下、右中的某一边
6、最值约束
a、myMaxSize
,获取指定数组中最大尺寸值,如下
//视图D的高度是: 视图A的宽度、视图B的高度、视图C的高度的一半、50 这四个值中的最大值。那么视图D的高度约束可以如下设置: D.heightSize.equalTo(@[A.widthSize, B.heightSize, C.heightSize.clone(0, 0.5), @50].myMaxSize);
b、myMinSize
,获取指定数组中最小尺寸值
视图C的宽度是:自身宽度、视图B的宽度-20、30这三个值的最小值。 C.widthSize.equalTo(@(MyLayoutSize.wrap),B.widthSize.clone(-20,1),@30).myMinSize);
c、myMaxPos
,获取指定数组中最大边距
视图D的右边距是:视图A的左边距、视图B的右边距、视图C的左边距偏移20、50这四个值中的最大值。那么视图D的右边距约束可以如下设置: D.rightPos.equalTo(@[A.leftPos,B.rightPos,C.leftPos.clone(20), @50].myMaxPos)
d、myMinPos
,获取指定数组中最小边距
(四)、表格布局(MyTableLayout)
1、需要先添加行,才能添加列
2、MyLayoutSize.average
设置均分效果
a、高度固定,宽度均分
[tableLayout addRow:50 colSize:MyLayoutSize.average];
b、高度均分,宽度均分
[tableLayout addRow:MyLayoutSize.average colSize:MyLayoutSize.average];
3、MyLayoutSize.wrap
设置高宽自适应
a、高度有子视图决定,宽度均分
[tableLayout addRow:MyLayoutSize.wrap colSize:MyLayoutSize.average];
b、高度固定,子视图自己决定宽度
[tableLayout addRow:30 colSize:MyLayoutSize.wrap];
4、指定列宽度固定,其他列均分宽度,通过MyLayoutSize.fill
和weight
配合使用
[tableLayout addRow:30 colSize:MyLayoutSize.fill]; MyFrameLayout *cellLayout = [[MyFrameLayout alloc] init]; cellLayout.myWidth = 80; [tableLayout addSubview:cellLayout]; for (NSInteger i = 0; i < 3; i++) { MyFrameLayout *cellLayout2 = [[MyFrameLayout alloc] init]; cellLayout2.weight = 1; [tableLayout addSubview: cellLayout2]; }
(五)、流式布局(MyFlowLayout)
1、流式布局中的子视图总是按一定的规则一次排列,当数量到达一定程度或者内容到达一定程度时就会自动换行从新排列
2、MyLayoutDragger
实现标签拖拽功能
3、arrangedCount
为0时,就是根据内容布局
4、分页滚动
//1、如果父控件是UIScrollView时,父UIScrollView 的delaysContentTouches需要设置为NO,这样就会优先处理子滚动视图的事件
//2、MyFlowLayout所在的UIScrollView的pagingEnabled需要设置为YES
//3、pagedCount的个数必须为arrangedCount的倍数
UIScrollView *parentView = [UIScrollView new];
parentView.delaysContentTouches = NO;
...
UIScrollView *contentScrollView = [UIScollView new];
contentScrollView. pagingEnabled = YES;
...
[parentView addSubview: contentScrollView];
//建立一个水平数量约束流式布局:每列展示3个子视图,每页展示9个子视图,整体从左往右滚动
MyFlowLayout *flowLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Horz arrangedCount:3];
flowLayout.pagedCount = 9;
flowLayout.myWidth = MyLayoutSize.wrap;
flowLayout.heightSize.equalTo(scrollView.heightSize);
//如果设置为如下的话,变为整体从上往下滚动
//flowLayout.myHeight = MyLayoutSize.wrap;
//flowLayout.widthSize.equalTo(scrollView.widthSize);
...
[contentScrollView addSubView:flowLayout];
...5、通过lineGravity
属性可以设置某行的对齐方式
(六)、Flex布局(MyFlexLayout)
(七)、浮动布局(MyFloatLayout)
1、浮动布局是一种里面的子视图按照约定的方向浮动停靠,当浮动布局的剩余空间不足容纳要加入的子视图的尺寸时会自动寻找最佳的位置进行浮动停靠的布局视图。因此浮动布局可以专门用来实现那些不规则布局或者图文环绕的布局。
2、reverseFloat
反向浮动
3、clearFloat
清除浮动,另起一行重新排列
4、setSubviewsSize
设置固定宽度浮动间距
5、alignment
设置其在浮动布局行(列)内的对齐方式
(八)、路径布局(MyPathLayout)
1、布局三要素:坐标、函数、距离
(九)、栅格布局(MyGridLayout)
1、栅格布局是一种将一个矩形的视图区域按行或者按列的方式划分为多个子区域,子区域根据布局的要求可以继续递归划分。栅格布局里面的子视图将按照添加的顺序依次填充到对应的叶子区域中去的布局方式。
栅格布局通过一套自定义的布局体系来划分位置和尺寸,添加到栅格布局里面的子视图将不再需要指定位置和尺寸而是由栅格布局中的子栅格来完成,因此可以很很方便的调整布局结构,从而实现动态布局的能力
2、栅格布局主要用于布局和数据分离的场景,可以通过json数据来完成布局