一. 概述
进行iOS项目开发时,常用的布局方法有两种:Frame
布局和AutoLayout
,Frame
布局没啥可说的,直接设置控件的横纵坐标,并指定宽高。AutoLayout
是通过设置控件相对方位的束缚进行布局。AutoLayout
的原意是好的,可是由于他的语法真实不怎么友爱,导致我们在实践项目开发顶用的并不多,只能靠Masonry
这样的第三方库来运用它。Masonry
布局尽管简单理解,可是它的代码量太大,每一个控件都要对其进行block设置。
在前端开发中,Flex布局运用尤为广泛,那么iOS端有没有类似前端Flex布局的方案呢?答案是必定的,除了在 Weex
以及 React Native
两个出名的跨渠道项目里有用到 Flex布局外,AsyncDisplayKit
也同样引进了 Flex布局,它们都是依据 Facebook
的 Yoga
的二次开发。而今日我们要介绍的 FlexLib 同样如此。
二. Flex布局与相关特色介绍
先来了解一下Flex布局:
Flex布局又名弹性布局,是一种为一维布局而规划的布局方法。一维的意思是你期望内容是按行或许列来布局。你可以运用display:flex
来将元素变为弹性布局。我们直接看比如:
完结7个item横向摆放
<!DOCTYPE html>
<html>
<head>
<title>flex布局2</title>
<meta charset="UTF-8">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-end;
background-color: wheat;
flex-wrap: wrap;
}
.item {
width: 100px;
height: 100px;
border: 1px solid royalblue;
text-align: center;
line-height: 100px;
margin: 10px 10px;
}
.item6 {
flex: 1;
}
.item7 {
flex: 2;
}
</style>
</head>
<body>
<div class="container">
<div class="item0 item">item0</div>
<div class="item1 item">item1</div>
<div class="item2 item">item2</div>
<div class="item3 item">item3</div>
<div class="item4 item">item4</div>
<div class="item5 item">item5</div>
<div class="item6 item">item6</div>
<div class="item7 item">item7</div>
</div>
</body>
</html>
上面是前端代码,看不懂不要紧,这儿重点是借这个比如来了解一下Flex布局的一些常用特色。Flex特色分类两类:一类是作用在容器上的,另一类是作用在子Item上的。
- 作用在容器上的特色
-
display:flex
: 设置container
容器为弹性布局 -
flex-direction
:决议主轴的方向,项目横向或是纵向摆放 取值:row | row-reverse | column | column-reverse;row
(默认值):主轴为水平方向,起点在左端。row-reverse
:主轴为水平方向,起点在右端。column
:主轴为垂直方向,起点在上沿。column-reverse
:主轴为垂直方向,起点在下沿。 -
justify-content
: 定义Item在主轴上怎么对齐。 取值:flex-start | flex-end | center | space-between | space-around;flex-start
(默认值):左对齐flex-end
:右对齐center
: 居中space-between
:两头对齐,项目之间的间隔都持平。space-around
:每个项目两头的间隔持平。所以,项目之间的间隔比项目与边框的间隔大一倍。 -
align-items
:定义Item在交叉轴上怎么对齐。 取值:align-items: flex-start | flex-end | center;flex-start
:交叉轴的起点对齐。flex-end
:交叉轴的结束对齐。center
:交叉轴的中心点对齐。 -
flex-wrap
:一条轴线上放不下,决议其是否换行 取值: nowrap(不换行) | wrap(换行) -
align-content
:也是控制Flex Item 在交叉轴上的对齐方法,只不过是以一整行作为最小单位。留意,假设Flex Item只有一行,该特色不起作用的。调整flex-wrap
为 Wrap,作用才显示出来。 取值:flex-start | flex-end | center | space-between | space-around;
- 作用在Item上的特色
-
align-self
:可以让单个 Flex Item 与其它 Flex Item 有不一样的对齐方法,掩盖align-items
特色。默认值为auto,表明继承Flex容器的align-items
特色。 -
flex
特色:flex特色是flex-grow
,flex-shrink
和flex-basis
的简写,默认值为0 1 auto
。flex-grow
: 特色定义项目的放大比例,默认为0,即假设存在剩余空间也不放大。 取值越大,占用剩余空间越大。flex-shrink
: 特色定义了项目的缩小比例,默认为1,即假设空间缺乏,该项目将缩小。flex-basis
:特色指定了flex元素在主轴方向上的初始巨细
这儿设置item6
与 item7
的flex为1和2,表明当前轴剩余的空间item6占1/3,item7占2/3.
更多的关于flex的特色可以检查这儿:Flex布局
三. FlexLib的运用
1.运用方法
CocoaPods
引进FlexLib:
pod 'FlexLib'
运用:
- 创建视图控制器继承
FlexBaseVC
,或许创建视图继承FlexCustomBaseView
- 创建与视图控制器或视图同名的xml文件
- 在xml文件中增加控件进行布局 比如:
TestLoginVC.h
@interface TestLoginVC : FlexBaseVC
@end
TestLoginVC.m
#import "TestLoginVC.h"
@interface TestLoginVC ()
{
UIScrollView* scroll;//自动绑定name特色的值
UIView* close;
}
@end
@implementation TestLoginVC
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"Touch Demo";
}
- (void)tapTouchAction
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@""
message:@"You pressed"
delegate:nil
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK",nil];
[alert show];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
TestLoginVC.xml
<?xml version="1.0" encoding="utf-8"?>
<UIView
layout="
flex:1,
alignItems:center"
attr="bgColor:white">
<FlexScrollView name="scroll" layout="padding:50,flex:1,width:100%,alignItems:center" attr="bgColor:white,vertScroll:true,">
<FlexTouchView onPress="tapTouchAction" attr="underlayColor:blue">
<UIImageView layout="width:100,height:100" attr="borderRadius:50,clipsToBounds:true,source:qrcode.png">
<FlexTouchMaskView attr="bgColor:red,alpha:0.7"/>
</UIImageView>
</FlexTouchView>
<UIView layout="height:20"/>
<FlexTouchView onPress="tapTouchAction" layout="height:100,width:100%,alignItems:center,justifyContent:center" attr="bgColor:#e5e5e5,borderRadius:8,underlayColor:darkGray">
<UILabel layout="width:100%" attr="fontSize:16,textAlign:center,color:red,text:Please touch me and move\,\r\n这是检验touch功能的控件,linesNum:0"/>
</FlexTouchView>
<UIView layout="height:20"/>
<UILabel layout="width:100%" attr="fontSize:20,linesNum:0,color:#333333,text:You can press the buttons above to see the effect. We use FlexTouchView to provide more powerful function and better flexibility than button."/>
</FlexScrollView>
</UIView>
说明:
-
默认视图从上到下进行摆放,在视图标签内增加其他视图,相当于为视图增加子视图
-
FlexLib
支撑两种类型的特色:布局特色(Layout)和视图特色(attr),布局特色与yoga
所支撑的特色一致,视图特色除了文档中所列的特色以外,还可以运用FLEXSET宏对现有特色进行扩展。你可以在这儿检查它所支撑的 layout attributes 和 view attributes -
FlexScrollView
(UIScrollView的子类)可以自动管理滚动范围,FlexTouchView
类似于UIButton,内置onPress
特色,可以设置其触发方法。 -
可以设置控件的
name
特色,name
特色的值会自动绑定代码中具有相同称号的成员变量,你可以直接在代码中运用它。 -
你可以预定义一些特色值,将其放入全局xml文件中,在
AppDelegate
进行初始化
全局xml文件 system.style
的格式类似这样:
<?xml version="1.0" encoding="utf-8"?>
<styles>
<style name="buttonAttrStyle">
<attr name="bgColor">black</attr>
<attr name="color">white</attr>
<attr name="borderRadius">4</attr>
<attr name="underlayColor">darkGray</attr>
<attr name="shadowColor">red</attr>
<attr name="shadowOffset">5/5</attr>
<attr name="shadowOpacity">0.2</attr>
<attr name="shadowRadius">3</attr>
</style >
<style name="buttonLayoutStyle">
<attr name="height">44</attr>
<attr name="width">150</attr>
<attr name="alignItems">center</attr>
<attr name="justifyContent">center</attr>
<attr name="margin">20</attr>
</style>
</styles>
导入体系款式文件
NSString *path = [[NSBundle mainBundle]pathForResource:@"system" ofType:@"style"];
[[FlexStyleMgr instance] loadClassStyle:path];
运用:
<UILabel attr="@:system/buttonAttrStyle" layout="@:system/buttonLayoutStyle" />
-
FlexLib
支撑运行时更新界面,详细的配备方法那你可以看这儿 -
FlexLib
支撑Cell高度自动核算,而且适配iPhone X等机型,实践开发中自定义UITableViewCell
需求继承FlexBaseTableCell
,自定义UICollectionViewCell
需求继承FlexCollectionCell
。
2.FlexXmlBaseView、FlexFrameView、FlexCustomBaseView 的运用
在运用xml
进行布局时,不可避免的要用到自定义视图,假设自定义视图也想要用xml进行布局,此时需求继承FlexXmlBaseView
、FlexFrameView
、FlexCustomBaseView
这三种视图中的一种。
(1)自定义视图运用xml布局
-
继承
FlexXmlBaseView
的视图:能在xml文件中运用,可以通过initWithRootView
方法创建,但不能通过initWithFrame
创建,也不能能直接设置frame,长处是更加轻量级,不会增加额定的视图层级. -
继承
FlexFrameView
的视图:可以直接设置frame,可是不能用在xml文件中。例如
FlexFrameView *frameView = [[FlexFrameView alloc] initWithFlex:@"CustomFrameView" Frame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 0) Owner:self];
frameView.flexibleHeight = YES;//设置高度自适应
[_scrollView addSubview:frameView];
CustomFrameView.xml
是这个视图对应的xml布局文件
- 继承
FlexCustomBaseView
的视图:既可以用在xml中,也可以像传统的UIView派生类那样运用initWithFrame
创建,缺点是会额定的增加多余的视图层级.
留意:继承
FlexCustomBaseView
或FlexFrameView
的视图必需要设置以下两个特色
//宽和高是否可变?缺省值均为NO
@property(nonatomic,assign) BOOL flexibleWidth;
@property(nonatomic,assign) BOOL flexibleHeight;
(2)自定义视图不运用xml布局,可是也想用在xml文件中
此时我们的自定义视图需求满足以下两个条件就可以用于xml文件中:
- 一切的初始化必须在
init
方法中完结。任何其他的init
函数,比如initWith…
不会被调用。 - 你可以用
FLEXSET
宏扩展视图特色,然后你可以在xml文件中设置特色。
直接在父视图中运用
<?xml version="1.0" encoding="utf-8"?>
<UIView layout="flex:1,alignItems:center" attr="bgColor:white">
<!-- 无xml对应的,自定义View 这么运用 -->
<ComplateCustomView layout="width:100%,height:80"/>
</UIView>
3.其他设置
- 缩放因子 在进行页面布局时,假设想让不同标准的屏幕共用一套规划,跟着屏幕标准的改变,页面控件的巨细随之缩放,这时候会用到缩放因子。设置缩放因子:
// 设置缩放因子,运用方法 在xml 布局中 *16 ==> 16*factor + 1
float factor = [UIScreen mainScreen].bounds.size.width/375;
FlexSetScale(factor, 1);
在布局xml中运用,数字前面加上*
<UILabel attr="fontSize: *16"/>
这表明:Label的fontSize为16*factor + 1
- 在特色中运用表达式
在布局特色和视图特色中增加表达式,特色名前要加
$
,ScreenWidth
是体系预定义的宏,你也可以用自定义的宏。现在支撑的运算符+, -, *, /, (, ),
<UIView layout="$width:ScreenWidth*0.6,height:50,alignItems:center,justifyContent:center" attr="bgColor:#e5e5e5,borderRadius:6">
<UILabel attr="@:system/buttonText,text:表达式核算,屏幕宽度的60%"/>
</UIView>
- FlexTextView 它是别的一个体系提供的类,可以自动依据输入的文字调整其高度,且保证其高度不会超出最小(minHeight)和最大高度(maxHeight)。
<FlexTextView layout="flex:1,minHeight:40,maxHeight:95" attr="borderColor:red,borderWidth:1,borderRadius:4,fontSize:18,color:darkGray,text:这是一个能自动依据字数调整高度的文本输入框,placeholder:我是占位,placeholderColor:red"/>
四. 总结
FlexLib
可能对有前端开发经历的同学比较友爱,对原生开发同学而言,学习一下他的语法也没害处。在日常开发中,我们可以有选择的运用这个布局,了解了这个布局后,会极大的提高我们页面布局功率,从而让我们将精力会集到更加中心的功能上。
参看: github.com/zhenglibao/…