EZLayout 0.1.1

EZLayout 0.1.1

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布最后发布2015年9月

Jeff Hurray维护。



EZLayout 0.1.1

  • 作者:
  • Jeff Hurray

对iOS布局的新看法,想像是Crack版本的UIStackViews。再见'autolayout'。

完整API速查表

使用方法

您可以选择克隆仓库并将EZLayout中的文件手动添加或者添加以下内容到您的Podfile

pod 'EZLayout', '~> 0.1.1'

然后只需导入以下头文件。

#import "EZLayout.h"

为什么我要制作EZLayout

目前,Autolayout似乎是唯一的布局方式。似乎每个人都在使用它,并且它垄断了布局市场。围绕autolayout构建了无数库来简化它(如MasonryPureLayout等),但最终它对我而言仍然不够好。

Autolayout的缺点
  • 其速度比基于frame的布局慢
  • 难以创建动态布局(动画、调整大小等…)
  • 在某一设备上工作良好的约束可能在另一设备上崩溃
  • 难以创建用于横向和纵向方向的约束

我想制作一个基于frame的布局库,它可以轻松处理可变屏幕尺寸和方向变化,同时保持语法简单易懂。

我使用EZLayout创建了一个简单的应用程序,名为Tuneder。它类似于Tinder用于快速播放列表。那里有很多优秀的示例代码。

布局类

现在每个UIViewUIView子类现在都有一个ezSizeezAlignment属性。任何是EZLayoutContainerView子视图的视图都将根据这些属性进行布局。

EZLayoutAlignment

EZLayoutAlignment允许你表达视图在其父视图中的对齐方式。默认为居中对齐。

// The view will be in the top right of the superview
myView.ezAlignment = [EZLayoutAlignment topRight];

EZLayoutAlignment选项的完整列表

EZLayoutSize

EZLayoutSize允许你表达视图的大小。它可以是相对于父视图大小的百分比或固定大小。

// The view will be 50% of the superviews height and 85% of the superviews width
myView.ezSize = [EZLayoutSize heightPercentage:0.5 widthPercentage:0.85];

// OR

// The view will be 85% of the superviews width and the height will scale to 75% of the width (75% of 85% of the superviews width)
myView.ezSize = [EZLayoutSize widthPercentage:0.85 scaleFactor:0.75];

EZLayoutAlignment选项的完整列表

EZLayoutContainerView

EZLayoutContainerView 是一个 UIView 子类,有助于视图的布局。所有子视图都会根据它们的大小和对齐值进行布局。

EZLayoutContainerView 方法完整列表

水平 + 垂直堆叠布局

基本容器视图应连接到一个视图控制器或 tableview 单元。

EZLayoutContainerView *base = [EZLayoutContainerView containerWithViewController:self];
水平 + 垂直堆叠布局

容器可以以百分比布局视图的水平和垂直方向。

[container verticallyLayoutViews:@[v1, v2, coolStuffContainer] withPercentages:@[@0.5, @0.5]];
空白空间

容器可以使用 kEZBlankSpace 在视图之间布局空白空间。

[container verticallyLayoutViews:@[v1, kEZBlankSpace, v2] withPercentages:@[@0.3, @0.4 @0.3]];
固定大小

容器还可以以固定宽度布局视图。您可以在这些方法中混合使用灵活宽度。

// ezFlexDefault is a macro value that says that view 2 will have a flexible height.
[container verticallyLayoutViews:@[view1, view2, view3] withFixedHeights:@[@20, ezFlexDefault, @22]];

// You can give ratios of flexibilities as well. Here both view2 and view3 are of flexible height, but view3 is twice the height of view2.
[container verticallyLayoutViews:@[view1, view2, view3] withFixedHeights:@[@20, ezFlexRatio(1.0), ezFlexRatio(2.0)]];
横屏布局

容器可以针对横竖屏模式有不同的布局方案。如果您不设置横屏布局,则默认横屏布局将与竖屏布局相同。

[container horizontallyLayoutLandscapeViews:@[descriptionContainer, coolStuffContainer] withLandscapePercentages:@[@0.5, @0.5]];
添加子视图

容器还可以将其他容器视图作为子视图添加。

base = [EZLayoutContainerView container];
subview = [UIView ezMake:^(UIView *make) {
   make.ezSize = [EZLayoutSize heightPercentage:0.8 widthPercentage:0.8];
}];
// subview will be laid out with the appropriate size and alignment in the base container.
[subview attachToContainerView:base];
子视图层次结构

容器将通过标签组织子视图。较大的标签将与较小的或空标签一起排列。

UIView *v1 = [UIView ezMakeBasic];
UIView *v2 = [UIView ezMakeBasic];
EZLayoutContainerView *base = [EZLayoutContainerView container];

// v2 will be above v1
v1.tag = 5;
v2.tag = 10;
[v1 attachToContainerView:base];
[v2 attachToContainerView:base];

如果您不希望情况如此,可以将 orderSubviewsByTag 属性设置为 false

UIView+EZLayout

初始化器

UIView+EZLayout 类别为 EZLayout 提供了初始化器。

// Standard initializer
UIView *view1 = [UIView ezMakeBasic];

// A block initializer that will return a view configured in the block
UIButton *button = [UIButton ezMake:^(UIView *make) {
   make.ezSize = [EZLayoutSize heightPercentage:0.8 widthPercentage:0.85];
   make.ezAlignment = [EZLayoutAlignment top];
}];

// A block initializer that will return an array of views configured in the block.
NSArray *imageViews = [UIImageView ezMakeViews:3 make:^(UIView *make, NSUInteger index) {
   UIImageView *imageView = (UIImageView *)make;
   imageView.image = [UIImage imageNamed:@"default"];
   imageView.ezSize = [EZLayoutSize widthPercentage:0.85 scaleFactor:1.0];
}];

FrameWasSetBlock

frameWasSetBlock 属性是一个在视图的 frame 设置后将被调用的代码块。这是一个设置 Corner Radius 和依赖视图 frame 的其他属性的理想位置。

view.frameWasSetBlock = ezFrameWasSetBlock() {
    self.view.layer.cornerRadius = self.view.ezHeight/2.0;
};

助手

以下属性是视图 frame 值的快捷方式。这些属性可读可写。

#pragma mark - EZLayout Helpers
@property (nonatomic) CGFloat ezX;
@property (nonatomic) CGFloat ezY;
@property (nonatomic) CGFloat ezHeight;
@property (nonatomic) CGFloat ezWidth;

调试模式

要查看视图如何布局,可以将 kEZDebugMode 标志设置为 YES。这将在 EZLayoutContainerView 中布局的所有视图周围添加虚线。这对调试非常有利。您可以在 EZLayoutConstants.h 中找到此标志。

/* DEBUG */

// YES: Dotted Lines will appear around all views to show their containment.
// NO: No dotted lines around views
#define kEZDebugMode YES

预计算值

EZLayoutConstants.h 中有许多预计算值,代表不同的百分比。这应该使布局计算变得容易。

[container verticallyLayoutViews:@[view1, view2, view3] 
         withLandscapePercentages:@[kEZSeventh, kEZTwoSevenths, kEZFourSevenths]];

缩写

一些方法略微庞大。如果您是 EZLayout 专家并且希望有更短的类名和方法,则可以导入以下头文件。

#import "EZLayout+Shorthand.h"
// EZLayoutContainerView -> EZContainerView
// EZLayoutSize -> EZSize
// EZLayoutAlignment - > EZAlignment

view.ezAlignment = [EZLayoutAlignment topPercentage:0.1 rightFixed:40];
// becomes
view.ezAlignment = [EZAlignment tP:0.1 rF:40];

// There are many more shorthand methods for the classes above. Try it out!

API 技巧表

EZLayoutAlignment

#pragma mark - Absolute

+ (instancetype) center; // default val
+ (instancetype) top;
+ (instancetype) bottom;
+ (instancetype) left;
+ (instancetype) right;
+ (instancetype) topLeft;
+ (instancetype) topRight;
+ (instancetype) bottomLeft;
+ (instancetype) bottomRight;

#pragma mark - Percentage

+ (instancetype) topPercentage:(CGFloat)topMarginPercentage;
+ (instancetype) bottomPercentage:(CGFloat)bottomMarginPercentage;
+ (instancetype) leftPercentage:(CGFloat)leftMarginPercentage;
+ (instancetype) rightPercentage:(CGFloat)rightMarginPercentage;
+ (instancetype) topPercentage:(CGFloat)topMarginPercentage leftPercentage:(CGFloat)leftMarginPercentage;
+ (instancetype) topPercentage:(CGFloat)topMarginPercentage rightPercentage:(CGFloat)rightMarginPercentage;
+ (instancetype) bottomPercentage:(CGFloat)bottomMarginPercentage leftPercentage:(CGFloat)leftMarginPercentage;
+ (instancetype) bottomPercentage:(CGFloat)bottomMarginPercentage rightPercentage:(CGFloat)rightMarginPercentage;

@property (nonatomic) CGFloat topMarginPercentage;
@property (nonatomic) CGFloat bottomMarginPercentage;
@property (nonatomic) CGFloat leftMarginPercentage;
@property (nonatomic) CGFloat rightMarginPercentage;

#pragma mark - Fixed

+ (instancetype) topFixed:(CGFloat)topMarginFixed;
+ (instancetype) bottomFixed:(CGFloat)bottomMarginFixed;
+ (instancetype) leftFixed:(CGFloat)leftMarginFixed;
+ (instancetype) rightFixed:(CGFloat)rightMarginFixed;
+ (instancetype) topFixed:(CGFloat)topMarginFixed leftFixed:(CGFloat)leftMarginFixed;
+ (instancetype) topFixed:(CGFloat)topMarginFixed rightFixed:(CGFloat)rightMarginFixed;
+ (instancetype) bottomFixed:(CGFloat)bottomMarginFixed leftFixed:(CGFloat)leftMarginFixed;
+ (instancetype) bottomFixed:(CGFloat)bottomMarginFixed rightFixed:(CGFloat)rightMarginFixed;

@property (nonatomic) CGFloat topMarginFixed;
@property (nonatomic) CGFloat bottomMarginFixed;
@property (nonatomic) CGFloat leftMarginFixed;
@property (nonatomic) CGFloat rightMarginFixed;

#pragma mark - Percentage + Fixed

+ (instancetype) topPercentage:(CGFloat)topMarginPercentage leftFixed:(CGFloat)leftMarginFixed;
+ (instancetype) topFixed:(CGFloat)topMarginFixed leftPercentage:(CGFloat)leftMarginPercentage;

+ (instancetype) topPercentage:(CGFloat)topMarginPercentage rightFixed:(CGFloat)rightMarginFixed;
+ (instancetype) topFixed:(CGFloat)topMarginFixed rightPercentage:(CGFloat)rightMarginPercentage;

+ (instancetype) bottomPercentage:(CGFloat)bottomMarginPercentage leftFixed:(CGFloat)leftMarginFixed;
+ (instancetype) bottomFixed:(CGFloat)bottomMarginFixed leftPercentage:(CGFloat)leftMarginPercentage;

+ (instancetype) bottomPercentage:(CGFloat)bottomMarginPercentage rightFixed:(CGFloat)rightMarginFixed;
+ (instancetype) bottomFixed:(CGFloat)bottomMarginFixed rightPercentage:(CGFloat)rightMarginPercentage;

EZLayoutSize

/***

 EZLayoutSizeTypeHeightAndWidth: heightPercentage and widthPercentage set: scale factor plays no role.

 EZLayoutSizeTypeHeightAndScale: heightPercentage and scaleFactor set: widthPercentage = MIN(1.0, heightPercentage*scaleFactor)

 EZLayoutSizeTypeWidthAndScale: widthPercentage and scaleFactor set: heightPercentage = MIN(1.0, widthPercentage*scaleFactor)

 EZLayoutSizeTypeFixed: fixed height and width in frame pixels. Does not need to be between 1.0 and 0.0

***/

// Dynamic
+ (instancetype) heightPercentage:(CGFloat)heightPercentage widthPercentage:(CGFloat)widthPercentage;
+ (instancetype) heightPercentage:(CGFloat)heightPercentage scaleFactor:(CGFloat)scaleFactor;
+ (instancetype) widthPercentage:(CGFloat)widthPercentage scaleFactor:(CGFloat)scaleFactor;

// Fixed
+ (instancetype)  heightFixed:(CGFloat) heightFixed  widthFixed:(CGFloat) widthFixed;
// Fixed + Dynamic
+ (instancetype)  heightFixed:(CGFloat) heightFixed widthPercentage:(CGFloat)widthPercentage;
+ (instancetype)  widthFixed:(CGFloat)widthFixed heightPercentage:(CGFloat)heightPercentage;

// Dynamic
@property (nonatomic) CGFloat heightPercentage;
@property (nonatomic) CGFloat widthPercentage;
@property (nonatomic) CGFloat scaleFactor;
// Fixed
@property (nonatomic) CGFloat fixedWidth;
@property (nonatomic) CGFloat fixedHeight;

EZLayoutContainerView

#pragma mark - Class Initializers
// Basic init
+ (instancetype) container;
// Initializers for portrait mode
+ (instancetype) containerFilledWithView:(UIView *)view;
+ (instancetype) containerWithHorizontalViews:(NSArray *)views percentages:(NSArray *)percentages;
+ (instancetype) containerWithVerticalViews:(NSArray *)views percentages:(NSArray *)percentages;
+ (instancetype) containerWithHorizontalViews:(NSArray *)views fixedWidths:(NSArray *)fixedWidths;
+ (instancetype) containerWithVerticalViews:(NSArray *)views fixedHeights:(NSArray *)fixedHeights;
// Initializer for the first container view
// starts EZLayout
// calls attachToViewController:
+ (instancetype) containerWithViewController:(UIViewController *)viewController;
// Initializer for the first container view
// starts EZLayout
// calls attachToTableViewCell:
+ (instancetype) containerWithTableViewCell:(UITableViewCell *)cell;
// Initializer for the first container view
// starts EZLayout
// calls attachToContainerView:
+ (instancetype) containerWithContainerView:(EZLayoutContainerView *)containerView;

#pragma mark - Instance Initializers
// Initializers for portrait mode
- (instancetype) initWithViewToFill:(UIView *)view;
- (instancetype) initWithHorizontalViews:(NSArray *)views percentages:(NSArray *)percentages;
- (instancetype) initWithVerticalViews:(NSArray *)views percentages:(NSArray *)percentages;
- (instancetype) initWithHorizontalViews:(NSArray *)views fixedWidths:(NSArray *)fixedWidths;
- (instancetype) initWithVerticalViews:(NSArray *)views fixedHeights:(NSArray *)fixedHeights;
// Initializer for the first container view
// starts EZLayout
// calls attachToViewController:
- (instancetype) initWithViewController:(UIViewController *)viewController;
// Initializer for the first container view
// starts EZLayout
// calls attachToTableViewCell:
- (instancetype) initWithTableViewCell:(UITableViewCell *)cell;
// Initializer for the first container view
// starts EZLayout
// calls attachToContainerView:
- (instancetype) initWithContainerView:(EZLayoutContainerView *)containerView;

// Used to start EZLayout
- (void) attachToViewController:(UIViewController *)viewController;
- (void) attachToTableViewCell:(UITableViewCell *)cell;
- (void) attachToContainerView:(EZLayoutContainerView *)containerView;

#pragma mark - Portrait Orientation
// Must be set
@property (nonatomic, strong, readonly) NSArray *views;
@property (nonatomic, strong, readonly) NSArray *percentages;

/* Fill */
- (void) fillWithView:(UIView *)view;

/* Dynamic */
// lays out views left to right
- (void) horizontallyLayoutViews:(NSArray *)views withPercentages:(NSArray *)percentages;
// Lays out views top to bottom
- (void) verticallyLayoutViews:(NSArray *)views withPercentages:(NSArray *)percentages;

/* Fixed + Dynamic */
// lays out views left to right
- (void) horizontallyLayoutViews:(NSArray *)views withFixedWidths:(NSArray *)widths;
// Lays out views top to bottom
- (void) verticallyLayoutViews:(NSArray *)views withFixedHeights:(NSArray *)heights;

#pragma mark - Landscape Orientation
// Can be nil
// If nil and portrait supported, will translate to portrait layout
@property (nonatomic, strong, readonly) NSArray *landscapeViews;
@property (nonatomic, strong, readonly) NSArray *landscapePercentages;

/* Fill */
- (void) fillWithLandscapeView:(UIView *)view;

/* Dynamic */
// lays out views left to right
- (void) horizontallyLayoutLandscapeViews:(NSArray *)landscapeViews withLandscapePercentages:(NSArray *)landscapePercentages;
// Lays out views top to bottom
- (void) verticallyLayoutLandscapeViews:(NSArray *)landscapeViews withLandscapePercentages:(NSArray *)landscapePercentages;

/* Fixed + Dynamic */
// lays out views left to right
- (void) horizontallyLayoutLandscapeViews:(NSArray *)landscapeViews withFixedLandscapeWidths:(NSArray *)landscapeWidths;
// Lays out views top to bottom
- (void) verticallyLayoutLandscapeViews:(NSArray *)landscapeViews withFixedLandscapeHeights:(NSArray *)landscapeHeights;

#pragma mark - Force Layout
// These should be called if views and/or percentages are  changed.
// Animated is wrapped in animation block
- (void) ezLayoutSubviews;
- (void) ezLayoutSubviewsAnimated;

#pragma mark - View Ordering 

@property (nonatomic) BOOL orderSubviewsByTag; // Defaults to 'true'

待办事项

如果您认为这里缺少任何内容,请告诉我!以下是我计划按任意顺序进行的工作。

  • 代码片段

联系方式 && 贡献

请随时通过电子邮件与我联系:[email protected]。我非常愿意听取您的意见,或者看到这个技术被应用的示例。

MIT许可证