FlexBoxLayout
特点
- Flexbox 布局;
- 链式调用,布局方便;
- 虚拟视图 Div;
- TableView 支持自动高度、布局缓存,contentView 缓存,和自动 cache 失效机制;
- ScrollView 支持自适应 contentSize;
- 异步计算布局。
预览
示例
- 使用
git clone
命令下载此仓库,Examples
目录包含示例程序; - 用 XCode 打开对应项目编译。
或执行以下命令:
git clone [email protected]:LPD-iOS/FlexBoxLayout.git; cd FlexBoxLayout/Example; open 'FlexBoxLayout.xcworkspace'
安装
FlexBoxLayout 可以通过 CocoaPods 进行获取。只需在你的 Podfile 中添加以下代码即可实现引入:
pod "FlexBoxLayout"
然后,执行以下命令即可:
$ pod install
示例代码
- (void)layoutView {
[self fb_makeLayout:^(FBLayout *layout) {
layout.flexDirection.equalTo(@(FBFlexDirectionColumn)).margin.equalToEdgeInsets(UIEdgeInsetsMake(0, 15, 0, 15)).alignItems.equalTo(@(FBAlignFlexStart));
}];
[_titleLabel fb_makeLayout:^(FBLayout *layout) {
layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0)).wrapContent();
}] ;
[_contentLabel fb_makeLayout:^(FBLayout *layout) {
layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0)).wrapContent();
}];
[_contentImageView fb_makeLayout:^(FBLayout *layout) {
layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0)).wrapContent();
}];
[_usernameLabel fb_makeLayout:^(FBLayout *layout) {
layout.wrapContent().flexGrow.equalTo(@(1.0));
}];
[_timeLabel fb_makeLayout:^(FBLayout *layout) {
layout.wrapContent().flexGrow.equalTo(@(1.0));
}];
FBLayoutDiv *div = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionRow ];
[div fb_makeLayout:^(FBLayout *layout) {
layout.flexDirection.equalTo(@(FBFlexDirectionRow)).justifyContent.equalTo(@(FBJustifySpaceBetween)).alignItems.equalTo(@(FBAlignFlexStart)).margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 0, 0, 0));
}];
div.fb_children = @[_usernameLabel,_timeLabel];
self.fb_children =@[_titleLabel,_contentLabel,_contentImageView,div];
}
使用
以下是一些有关 Flexbox 的介绍:FlexBox(中文)、Flexbox 完美指南 和 CSS3 Flexbox 属性视觉指南。
1. UIView + FBLayout 使用
这里有一些简单用法
UIScrollView *contentView = [UIScrollView new];
contentView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-44);
[self.view addSubview:contentView];
UIView *child1 = [UIView new];
child1.backgroundColor = [UIColor blueColor];
[child1 fb_makeLayout:^(FBLayout *layout) {
layout.width.height.equalTo(@100);
}];
UIView *child2 = [UIView new];
child2.backgroundColor = [UIColor greenColor];
[child2 fb_makeLayout:^(FBLayout *layout) {
layout.equalTo(child1);
}];
UILabel *child3 = [UILabel new];
child3.numberOfLines = 0;
child3.backgroundColor = [UIColor yellowColor];
[child3 fb_wrapContent];
[child3 setAttributedText:[[NSAttributedString alloc] initWithString:@"testfdsfdsfdsfdsfdsfdsafdsafdsafasdkkk" attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:18]}] ];
[contentView addSubview:child1];
[contentView addSubview:child2];
[contentView addSubview:child3];
FBLayoutDiv *div1 = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn
justifyContent:FBJustifySpaceBetween
alignItems:FBAlignCenter
children:@[child1, child2,child3]];
[div1 fb_makeLayout:^(FBLayout *layout) {
layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(20, 0, 0, 0));
layout.width.equalTo(@(150));
}];
UIView *child5 = [UIView new];
child5.backgroundColor = [UIColor blueColor];
child5.CSSStyles = @{FBWidthAttributeName:@(50),
FBHeightAttributeName:@(50),
FBMarginAttributeName:[NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(0, 0, 10, 0)],
FBFlexGrowAttributeName:@1.0};
UIView *child6 = [UIView new];
child6.backgroundColor = [UIColor greenColor];
[child6 fb_makeLayout:^(FBLayout *layout) {
layout.equalTo(child5);
layout.flexGrow.equalTo(@(2.0));
layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(10, 10, 10, 10));
}];
UIView *child7 = [UIView new];
child7.backgroundColor = [UIColor yellowColor];
[child7 fb_makeLayout:^(FBLayout *layout) {
layout.equalTo(child5);
}];
UIView *child8 = [UIView new];
child8.backgroundColor = [UIColor blackColor];
[child8 fb_makeLayout:^(FBLayout *layout) {
layout.equalTo(child5);
}];
FBLayoutDiv *div2 =[FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn
justifyContent:FBJustifySpaceAround
alignItems:FBAlignCenter
children:@[child5,child6,child7,child8]];
[div2 fb_makeLayout:^(FBLayout *layout) {
layout.margin.equalToEdgeInsets(UIEdgeInsetsMake(20, 0, 0, 0));
layout.width.equalTo(@(150));
}];
[contentView addSubview:child5];
[contentView addSubview:child6];
[contentView addSubview:child7];
[contentView addSubview:child8];
FBLayoutDiv *root = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionRow
justifyContent:FBJustifySpaceAround
alignItems:FBAlignCenter
children:@[div1,div2]];
contentView.fb_contentDiv = root;
[root fb_asyApplyLayoutWithSize:[UIScreen mainScreen].bounds.size];
2. FBLayoutDiv
FBLayoutDiv 是虚拟视图,将视图分割到不同的区域,避免过多视图。
FBLayoutDiv *div1 = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn
justifyContent:FBJustifySpaceBetween
alignItems:FBAlignCenter
children:@[child1, child2,child3]];
FBLayoutDiv *div2 =[FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionColumn
justifyContent:FBJustifySpaceAround
alignItems:FBAlignCenter
children:@[child5,child6,child7,child8]];
root.fb_children = @[div1,div2];
3. UITableView+FBLayout
它是 UITableViewDataSource 的分类。它支持 FBLayout 的自动单元格高度和易于使用。
[self.tableView fb_setCellContnetViewBlockForIndexPath:^UIView *(NSIndexPath *indexPath) {
return [[FBFeedView alloc]initWithModel:weakSelf.sections[indexPath.section][indexPath.row]];
}];
....
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self.tableView fb_heightForIndexPath:indexPath];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self.tableView fb_cellForIndexPath:indexPath];
}
4. UIScrollView+FBLayout
它支持自动内容大小
FBLayoutDiv *root = [FBLayoutDiv layoutDivWithFlexDirection:FBFlexDirectionRow
justifyContent:FBJustifySpaceAround
alignItems:FBAlignCenter
children:@[div1,div2]];
contentView.fb_contentDiv = root;
5. Flexbox 容器属性
5.1 flex-direction
该属性指定了flex项目在flex容器中的布局方式,通过设置flex容器主轴的方向。它们可以以两种主要方向布局,例如水平排列或垂直排列。
FBFlexDirectionRow;
FBFlexDirectionRowReverse;
FBFlexDirectionColumn;
FBFlexDirectionColumnReverse;
5.2 flex-wrap
flexbox的初始概念是将contaner中的项目设置为单行。flex-wrap属性控制flex容器是否在单行或多行中排列其项目,以及新行堆叠的方向。只支持'nowarp'(这是默认设置)或'wrap'。
FBWrapNoWrap;
FBWrapWrap;
5.3 justify-content
justify-content属性沿着flex容器当前行的轴线排列flex项目。它有助于在一条线上的所有flex项目都是不可缩放的,或者都是可缩放的但达到了最大大小时,分配左侧的空闲空间。
FBJustifyFlexStart;
FBJustifyCenter;
FBJustifyFlexEnd
FBJustifySpaceBetween;
FBJustifySpaceAround;
5.4 align-items
Flex项目可以在flex容器当前行的交叉轴上对齐,类似于justify-content,但在垂直方向上。此属性设置了所有flex项目的默认对齐方式,包括匿名flex项目。
FBAlignFlexStart;
FBAlignCenter;
FBAlignFlexEnd;
FBAlignStretch;
5.5 align-content
对齐内容属性在交叉轴上有多余空间时,将自适应容器内的行对齐,类似于如何对主轴上的单个元素进行对齐。
FBAlignFlexStart;
FBAlignCenter;
FBAlignFlexEnd;
FBAlignStretch;
6. 弹性框项属性
6.1 fle-grow
这个属性指定了弹性增长因子,它决定了在分配正自由空间时,弹性项相对于弹性容器中其他弹性项的增长多少。
FlexGrow;
6.2 fle-shrink
flex-shrink属性指定了弹性缩减因子,它决定了在分配负自由空间时,弹性项相对于弹性容器中其他弹性项的缩减多少。
默认情况下,所有弹性项都可以被缩小,但如果我们将其设置为0(不缩小),它们将保持原始大小
FlexShrink;
6.3 fle-basis
此属性具有与width和height属性相同的值,并指定了弹性项的初始主大小,在根据弹性因子分配自由空间之前。
FlexBasis:350;
6.4 align-self
此 align-self 属性允许覆盖单个 flex 元素的默认对齐(或通过 align-items 指定的对齐)。请参考 flex 容器的 align-items 解释了解可用的值。
FBAlignFlexStart;
作者
qiang.shen
协议
FlexBoxLayout 基于 MIT 协议进行分发和使用,更多信息参见协议文件。