测试已测试 | ✗ |
Lang语言 | Obj-CObjective C |
许可证 | MIT |
Released最后发布 | 2016 年 8 月 |
由 John Boiles,Gabriel Handford 维护。
一个基于框架的布局框架,与 UIView
、NSView
、CALayer
以及任何实现了 setFrame:
的任何其他内容一起工作。避免使用 Interface Builder 和 Auto Layout,并完全掌控您的布局。
以下是一个具有图片、标题标签和多行描述标签的视图的示例,具有动态高度。
// TableViewCellView.h
#import <YOLayout/YOLayout.h>
@interface TableViewCellView : YOView // Subclass YOView
@end
// TableViewCellView.m
@interface TableViewCellView ()
@property UILabel *titleLabel;
@property UILabel *descriptionLabel;
@end
@implementation TableViewCellView
- (void)viewInit {
[super viewInit];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"information.png"]];
[self addSubview:imageView];
self.titleLabel = [[UILabel alloc] init];
self.titleLabel.numberOfLines = 1;
self.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
self.titleLabel.font = [UIFont boldSystemFontOfSize:16];
[self addSubview:self.titleLabel];
self.descriptionLabel = [[UILabel alloc] init];
self.descriptionLabel.font = [UIFont systemFontOfSize:16];
self.descriptionLabel.numberOfLines = 0; // Multi-line label (word wrapping
self.descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;
[self addSubview:self.descriptionLabel];
YOSelf yself = self;
self.viewLayout = [YOLayout layoutWithLayoutBlock:^CGSize(id<YOLayout> layout, CGSize size) {
CGFloat x = 10;
CGFloat y = 10;
// imageView's size is set by the UIImage when using initWithImage:
CGRect imageViewFrame = [layout setOrigin:CGPointMake(x, y) view:imageView options:0];
x += imageViewFrame.size.width + 10;
y += [layout sizeToFitVerticalInFrame:CGRectMake(x, y, size.width - x - 10, 0) view:yself.titleLabel].size.height;
y += [layout sizeToFitVerticalInFrame:CGRectMake(x, y, size.width - x - 10, 1000) view:yself.descriptionLabel].size.height;
// Ensure the y position is at least as high as the image view
y = MAX(y, (imageViewFrame.origin.y + imageViewFrame.size.height));
y += 10;
return CGSizeMake(size.width, y);
}];
}
viewLayout
执行布局并返回它所需的大小。这统一了 layoutSubviews
和 sizeThatFits:
为单个方法。此示例返回与传入相同宽度的变量高度。要使视图填充所有可用大小,可以返回 size
(传入的大小)。viewInit
是一个统一的初始化器。 initWithFrame:
和 initWithCoder:
都调用此方法。通过查看操作来跟踪和学习 YOLayout 的最佳方式是看到它在实际应用中的效果。打开示例项目: YOLayoutExample。它包含 iOS 和 OSX 目标。
支持 NSView 和 Cocoa。YOLayout 使 UIKit 和 Cocoa 的布局保持一致。
您是否曾经尝试使用 IB 完成较大的项目?这是令人沮丧的。小的调整可能会以意想不到的方式破坏 Auto Layout 约束。此外,Interface Builder 并不适合有多个提交者的大型项目;git 合并 storyboards 和 xibs 可能非常困难。最终,我们是程序员;我们喜欢用代码来完成事情。
代码中的 Auto Layout 是向正确方向迈出的一步,但它与基于框架的布局相比存在几个缺点
layoutSubviews
中编写自己的布局代码呢?在layoutSubviews
中编写布局代码的核心问题是需要在layoutSubviews
和sizeThatFits:
中重复编写大量的布局代码。当您有多个子视图可能会动态调整大小,这段代码就会变得重复且难于维护。在sizeThatFits:
中调用layoutIfNeeded
可能会因为父视图在其layoutSubviews
中使用了您的sizeThatFits:
方法而造成无限递归的风险。
您可能没有问这个问题,但您应该问!YOLayout的一个有趣之处在于,布局也适用于在drawRect:
中绘制的视图。因为YOLayout独立于视图层次结构,您可以轻松地在将子视图添加到层次结构或仅在drawRect:
中绘制它之间切换,而不需要更改布局代码。试试看Auto Layout能做这个!
YOLayout非常适合自定义绘制控件。在drawRect:
中绘制的视图可以使用IB_DESIGNABLE
属性在界面构建器中以实时方式绘制。打开示例项目(pod try YOLayout
),查看DrawableView.m和DrawableView.xib。
- (void)viewInit;
是视图的统一初始化器。在YOLayout中,没有必要指定默认框架或处理从界面构建器或从代码加载的视图的初始化。
不需要。如果您的布局非常简单,或者它没有动态大小,只需像平常一样使用layoutSubviews
(UIKit)或layout
(AppKit)。YOLayout不会特别地覆盖行为,并且与现有的布局方法兼容。
就像大多数事情一样,YOLayout也有权衡。我们喜欢使用它在处理具有许多不同对齐和动态大小项目的复杂布局时。
但是,也存在一些不足
还有更多,您可以随时通过提交问题告诉我们您为什么要讨厌它。
没有依赖!
使用 YOLayout 我们实现了一个盒模型(YOVBox
和 YOHBox
),支持一些基本的布局属性,如间距、内边距、水平对齐、最小大小和最大大小。
YOVBox
用于垂直布局,而 YOHBox
用于水平布局。例如
#import <YOLayout/YOBox.h>
@interface BoxExample : YOVBox
@end
@implementation BoxExample
- (void)viewInit {
[super viewInit];
self.backgroundColor = UIColor.whiteColor;
// Labels stacked vertically (VBox)
YOVBox *labelsView = [YOVBox box:@{@"spacing": @"10", @"insets": @"20,20,0,20"}];
{
UILabel *label1 = [[UILabel alloc] init];
label1.text = @"Box Model Test";
label1.font = [UIFont boldSystemFontOfSize:20];
label1.textAlignment = NSTextAlignmentCenter;
[labelsView addSubview:label1];
UILabel *label2 = [[UILabel alloc] init];
label2.font = [UIFont systemFontOfSize:14];
label2.numberOfLines = 0;
label2.text = @"PBR&B Intelligentsia shabby chic. Messenger bag flexitarian cold-pressed VHS 90's. Tofu chillwave pour-over Marfa cold-pressed, kogi bespoke High Life semiotics readymade authentic wolf sriracha craft beer. Next level direct trade shabby chic vegan cliche. Mlkshk butcher church-key cornhole 3 wolf moon, YOLO cold-pressed cronut";
[labelsView addSubview:label2];
}
[self addSubview:labelsView];
// Buttons with min size right aligned (HBox)
YOHBox *buttons = [YOHBox box:@{@"spacing": @"20", @"insets": @"10,20,10,20", @"minSize": @"50,50", @"horizontalAlignment": @"right"}];
{
UIButton *button1 = [self buttonWithText:@"A"];
[buttons addSubview:button1];
UIButton *button2 = [self buttonWithText:@"B"];
[buttons addSubview:button2];
UIButton *button3 = [self buttonWithText:@"C"];
[buttons addSubview:button3];
}
[self addSubview:buttons];
// Buttons centered horizontally (HBox)
YOHBox *buttonsCenter = [YOHBox box:@{@"spacing": @"20", @"horizontalAlignment": @"center"}];
{
[buttonsCenter addSubview:[self buttonWithText:@"D"]];
[buttonsCenter addSubview:[self buttonWithText:@"E"]];
[buttonsCenter addSubview:[self buttonWithText:@"F"]];
}
[self addSubview:buttonsCenter];
}
- (UIButton *)buttonWithText:(NSString *)text {
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
[button setTitle:text forState:UIControlStateNormal];
button.layer.borderWidth = 1.0;
button.layer.borderColor = UIColor.grayColor.CGColor;
button.contentEdgeInsets = UIEdgeInsetsMake(5, 10, 5, 10);
return button;
}
@end
对于边框布局,您可以使用 YOVBorderLayout
或 YOHBorderLayout
。例如
@implementation BorderView
- (void)viewInit {
[super viewInit];
self.backgroundColor = UIColor.blackColor;
UILabel *topView = [self label:@"Top" backgroundColor:UIColor.redColor];
[self addSubview:topView];
YOView *centerView = [YOView view];
{
UILabel *leftLabel = [self label:@"Left" backgroundColor:UIColor.greenColor];
[centerView addSubview:leftLabel];
UILabel *centerLabel = [self label:@"Center" backgroundColor:UIColor.blueColor];
[centerView addSubview:centerLabel];
UILabel *rightLabel = [self label:@"Right" backgroundColor:UIColor.cyanColor];
[centerView addSubview:rightLabel];
centerView.viewLayout = [YOHBorderLayout layoutWithCenter:centerLabel left:@[leftLabel] right:@[rightLabel] insets:UIEdgeInsetsZero spacing:10];
}
[self addSubview:centerView];
UILabel *bottomView = [self label:@"Bottom" backgroundColor:UIColor.orangeColor];
[self addSubview:bottomView];
self.viewLayout = [YOVBorderLayout layoutWithCenter:centerView top:@[topView] bottom:@[bottomView] insets:UIEdgeInsetsMake(20, 20, 20, 20) spacing:10];
}
- (UILabel *)label:(NSString *)text backgroundColor:(UIColor *)backgroundColor {
UILabel *label = [[UILabel alloc] init];
label.font = [UIFont systemFontOfSize:20];
label.text = text;
label.numberOfLines = 0;
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor = backgroundColor;
label.textColor = [UIColor whiteColor];
return label;
}
@end
YOLayout 在 MIT 许可证下可用。有关更多信息,请参阅 LICENSE 文件。