对iOS布局的新看法,想像是Crack版本的UIStackViews。再见'autolayout'。
您可以选择克隆仓库并将EZLayout中的文件手动添加或者添加以下内容到您的Podfile
pod 'EZLayout', '~> 0.1.1'
然后只需导入以下头文件。
#import "EZLayout.h"
目前,Autolayout似乎是唯一的布局方式。似乎每个人都在使用它,并且它垄断了布局市场。围绕autolayout构建了无数库来简化它(如Masonry、PureLayout等),但最终它对我而言仍然不够好。
我想制作一个基于frame的布局库,它可以轻松处理可变屏幕尺寸和方向变化,同时保持语法简单易懂。
我使用EZLayout创建了一个简单的应用程序,名为Tuneder。它类似于Tinder用于快速播放列表。那里有很多优秀的示例代码。
现在每个UIView
和UIView
子类现在都有一个ezSize
和ezAlignment
属性。任何是EZLayoutContainerView
子视图的视图都将根据这些属性进行布局。
EZLayoutAlignment允许你表达视图在其父视图中的对齐方式。默认为居中对齐。
// The view will be in the top right of the superview
myView.ezAlignment = [EZLayoutAlignment topRight];
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];
EZLayoutContainerView 是一个 UIView 子类,有助于视图的布局。所有子视图都会根据它们的大小和对齐值进行布局。
基本容器视图应连接到一个视图控制器或 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 类别为 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 属性是一个在视图的 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!
#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;
/***
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;
#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]。我非常愿意听取您的意见,或者看到这个技术被应用的示例。