feat:step2

This commit is contained in:
pengfei.zhou 2019-11-27 15:28:39 +08:00
parent bb9e6671f6
commit af8a455d46
4 changed files with 58 additions and 251 deletions

View File

@ -51,19 +51,6 @@ - (void)blend:(NSDictionary *)props {
[super blend:props]; [super blend:props];
[self blendHeader]; [self blendHeader];
[self blendContent]; [self blendContent];
dispatch_async(dispatch_get_main_queue(), ^{
[self.view also:^(DoricSwipeRefreshLayout *layout) {
[layout layoutSelf];
[layout.contentView also:^(UIView *it) {
it.x = it.y = 0;
}];
[layout.headerView also:^(UIView *it) {
it.bottom = 0;
it.centerX = layout.width / 2;
}];
layout.contentSize = layout.frame.size;
}];
});
} }
- (void)blendContent { - (void)blendContent {

View File

@ -61,17 +61,13 @@ typedef NS_ENUM(NSInteger, DoricGravity) {
@interface DoricLayoutContainer : UIView @interface DoricLayoutContainer : UIView
@property(nonatomic, assign) DoricGravity gravity;
- (void)layout:(CGSize)targetSize;
- (CGSize)sizeContent:(CGSize)size;
@end @end
@interface DoricStackView : DoricLayoutContainer @interface DoricStackView : DoricLayoutContainer
@end @end
@interface DoricLinearView : DoricLayoutContainer @interface DoricLinearView : DoricLayoutContainer
@property(nonatomic, assign) DoricGravity gravity;
@property(nonatomic, assign) CGFloat space; @property(nonatomic, assign) CGFloat space;
@end @end
@ -93,7 +89,9 @@ typedef NS_ENUM(NSInteger, DoricGravity) {
@end @end
@interface UIView (DoricLayouts) @interface UIView (DoricLayouts)
- (void)layoutSelf; - (void)layoutSelf:(CGSize)targetSize;
- (CGSize)measureSize:(CGSize)targetSize; - (CGSize)measureSize:(CGSize)targetSize;
- (void)doricLayoutSubviews;
@end @end

View File

@ -19,8 +19,8 @@
#import "DoricLayouts.h" #import "DoricLayouts.h"
#import <objc/runtime.h> #import <objc/runtime.h>
#import <Doric/DoricLayouts.h>
#import "UIView+Doric.h" #import "UIView+Doric.h"
#import "Doric.h"
static const void *kLayoutConfig = &kLayoutConfig; static const void *kLayoutConfig = &kLayoutConfig;
@ -60,21 +60,9 @@ - (UIView *)viewWithTagString:(NSString *)tagString {
@implementation UIView (DoricLayouts) @implementation UIView (DoricLayouts)
/**
- (CGSize)targetLayoutSize { * Measure self's size
CGFloat width = self.width; * */
CGFloat height = self.height;
if (self.layoutConfig.widthSpec == DoricLayoutAtMost
|| self.layoutConfig.widthSpec == DoricLayoutWrapContent) {
width = self.superview.targetLayoutSize.width;
}
if (self.layoutConfig.heightSpec == DoricLayoutAtMost
|| self.layoutConfig.heightSpec == DoricLayoutWrapContent) {
height = self.superview.targetLayoutSize.height;
}
return CGSizeMake(width, height);
}
- (CGSize)measureSize:(CGSize)targetSize { - (CGSize)measureSize:(CGSize)targetSize {
CGFloat width = self.width; CGFloat width = self.width;
CGFloat height = self.height; CGFloat height = self.height;
@ -102,26 +90,38 @@ - (CGSize)measureSize:(CGSize)targetSize {
return CGSizeMake(width, height); return CGSizeMake(width, height);
} }
- (void)layoutSelf { /**
CGSize contentSize = [self measureSize:self.targetLayoutSize]; * layout self and subviews
* */
- (void)layoutSelf:(CGSize)targetSize {
CGSize contentSize = [self measureSize:targetSize];
if (self.layoutConfig.widthSpec == DoricLayoutAtMost) { if (self.layoutConfig.widthSpec == DoricLayoutAtMost) {
self.width = self.superview.width; self.width = targetSize.width;
} else if (self.layoutConfig.widthSpec == DoricLayoutWrapContent) { } else if (self.layoutConfig.widthSpec == DoricLayoutWrapContent) {
self.width = contentSize.width; self.width = contentSize.width;
} }
if (self.layoutConfig.heightSpec == DoricLayoutAtMost) { if (self.layoutConfig.heightSpec == DoricLayoutAtMost) {
self.height = self.superview.height; self.height = targetSize.height;
} else if (self.layoutConfig.heightSpec == DoricLayoutWrapContent) { } else if (self.layoutConfig.heightSpec == DoricLayoutWrapContent) {
self.height = contentSize.height; self.height = contentSize.height;
} }
[self.subviews forEach:^(__kindof UIView *obj) { }
if ([obj isKindOfClass:[DoricLayoutContainer class]]) {
[obj layoutSubviews]; - (BOOL)requestSuperview {
return self.superview
&& self.layoutConfig
&& self.layoutConfig.widthSpec != DoricLayoutExact
&& self.layoutConfig.heightSpec != DoricLayoutExact;
}
- (void)doricLayoutSubviews {
if ([self requestSuperview]) {
[self.superview doricLayoutSubviews];
} else { } else {
[obj layoutSelf]; [self layoutSelf:CGSizeMake(self.width, self.height)];
} }
}];
} }
@end @end
DoricMargin DoricMarginMake(CGFloat left, CGFloat top, CGFloat right, CGFloat bottom) { DoricMargin DoricMarginMake(CGFloat left, CGFloat top, CGFloat right, CGFloat bottom) {
@ -168,94 +168,34 @@ @interface DoricLayoutContainer ()
@end @end
@implementation DoricLayoutContainer @implementation DoricLayoutContainer
- (void)layoutSubviews { - (void)layoutSubviews {
if ([self.superview isKindOfClass:[DoricLayoutContainer class]]) { [super layoutSubviews];
[self.superview layoutSubviews]; [self doricLayoutSubviews];
} else {
CGSize size = [self sizeThatFits:self.targetLayoutSize];
[self layout:size];
}
}
- (CGSize)sizeThatFits:(CGSize)size {
CGFloat width = self.width;
CGFloat height = self.height;
DoricLayoutConfig *config = self.layoutConfig;
if (!config) {
config = [DoricLayoutConfig new];
}
if (config.widthSpec == DoricLayoutAtMost
|| config.widthSpec == DoricLayoutWrapContent) {
width = size.width - config.margin.left - config.margin.right;
}
if (config.heightSpec == DoricLayoutAtMost
|| config.heightSpec == DoricLayoutWrapContent) {
height = size.height - config.margin.top - config.margin.bottom;
}
CGSize contentSize = [self sizeContent:CGSizeMake(width, height)];
if (config.widthSpec == DoricLayoutWrapContent) {
width = contentSize.width;
}
if (config.heightSpec == DoricLayoutWrapContent) {
height = contentSize.height;
}
return CGSizeMake(width, height);
}
- (CGSize)sizeContent:(CGSize)size {
return size;
}
- (void)layout:(CGSize)targetSize {
self.width = targetSize.width;
self.height = targetSize.height;
} }
@end @end
@interface DoricStackView () @interface DoricStackView ()
@property(nonatomic, assign) CGFloat contentWidth; @property(nonatomic, assign) CGFloat contentWidth;
@property(nonatomic, assign) CGFloat contentHeight; @property(nonatomic, assign) CGFloat contentHeight;
@end @end
@implementation DoricStackView @implementation DoricStackView
- (CGSize)sizeContent:(CGSize)size { - (CGSize)sizeThatFits:(CGSize)size {
CGFloat contentWidth = 0; CGFloat contentWidth = 0;
CGFloat contentHeight = 0; CGFloat contentHeight = 0;
for (UIView *child in self.subviews) { for (UIView *child in self.subviews) {
if (child.isHidden) { if (child.isHidden) {
continue; continue;
} }
DoricLayoutConfig *childConfig = child.layoutConfig; DoricLayoutConfig *childConfig = child.layoutConfig;
if (!childConfig) { if (!childConfig) {
childConfig = [DoricLayoutConfig new]; childConfig = [DoricLayoutConfig new];
} }
CGSize childSize = CGSizeMake(child.width, child.height); CGSize childSize;
if (CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) { if (CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) {
if ([child isKindOfClass:[DoricLayoutContainer class]] childSize = [child measureSize:CGSizeMake(size.width, size.height)];
|| childConfig.widthSpec == DoricLayoutWrapContent
|| childConfig.heightSpec == DoricLayoutWrapContent) {
childSize = [child sizeThatFits:CGSizeMake(size.width, size.height - contentHeight)];
}
if (childConfig.widthSpec == DoricLayoutExact) {
childSize.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
childSize.width = size.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
childSize.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
childSize.height = size.height - contentHeight;
}
if (childConfig.weight) {
childSize.height = child.height;
}
} else { } else {
childSize = child.bounds.size; childSize = child.bounds.size;
} }
@ -267,9 +207,8 @@ - (CGSize)sizeContent:(CGSize)size {
return CGSizeMake(contentWidth, contentHeight); return CGSizeMake(contentWidth, contentHeight);
} }
- (void)layout:(CGSize)targetSize { - (void)layoutSelf:(CGSize)targetSize {
self.width = targetSize.width; [super layoutSelf:targetSize];
self.height = targetSize.height;
for (UIView *child in self.subviews) { for (UIView *child in self.subviews) {
if (child.isHidden) { if (child.isHidden) {
continue; continue;
@ -281,29 +220,9 @@ - (void)layout:(CGSize)targetSize {
if (!childConfig) { if (!childConfig) {
childConfig = [DoricLayoutConfig new]; childConfig = [DoricLayoutConfig new];
} }
CGSize size = [child measureSize:CGSizeMake(targetSize.width, targetSize.height)];
CGSize size = [child sizeThatFits:CGSizeMake(targetSize.width, targetSize.height)]; [child layoutSelf:size];
if (childConfig.widthSpec == DoricLayoutExact) { DoricGravity gravity = childConfig.alignment;
size.width = child.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
}
if (childConfig.widthSpec == DoricLayoutExact) {
size.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
size.width = targetSize.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
size.height = targetSize.height;
}
child.width = size.width;
child.height = size.height;
DoricGravity gravity = childConfig.alignment | self.gravity;
if ((gravity & LEFT) == LEFT) { if ((gravity & LEFT) == LEFT) {
child.left = 0; child.left = 0;
} else if ((gravity & RIGHT) == RIGHT) { } else if ((gravity & RIGHT) == RIGHT) {
@ -317,7 +236,6 @@ - (void)layout:(CGSize)targetSize {
child.right = targetSize.width - childConfig.margin.right; child.right = targetSize.width - childConfig.margin.right;
} }
} }
if ((gravity & TOP) == TOP) { if ((gravity & TOP) == TOP) {
child.top = 0; child.top = 0;
} else if ((gravity & BOTTOM) == BOTTOM) { } else if ((gravity & BOTTOM) == BOTTOM) {
@ -331,10 +249,6 @@ - (void)layout:(CGSize)targetSize {
child.bottom = targetSize.height - childConfig.margin.bottom; child.bottom = targetSize.height - childConfig.margin.bottom;
} }
} }
if ([child isKindOfClass:[DoricLayoutContainer class]]) {
[(DoricLayoutContainer *) child layout:size];
}
} }
} }
@end @end
@ -343,7 +257,8 @@ @implementation DoricLinearView
@end @end
@implementation DoricVLayoutView @implementation DoricVLayoutView
- (CGSize)sizeContent:(CGSize)size {
- (CGSize)sizeThatFits:(CGSize)size {
CGFloat contentWidth = 0; CGFloat contentWidth = 0;
CGFloat contentHeight = 0; CGFloat contentHeight = 0;
NSUInteger contentWeight = 0; NSUInteger contentWeight = 0;
@ -355,23 +270,9 @@ - (CGSize)sizeContent:(CGSize)size {
if (!childConfig) { if (!childConfig) {
childConfig = [DoricLayoutConfig new]; childConfig = [DoricLayoutConfig new];
} }
CGSize childSize = CGSizeMake(child.width, child.height); CGSize childSize;
if (CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) { if (CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) {
if ([child isKindOfClass:[DoricLayoutContainer class]] childSize = [child measureSize:CGSizeMake(size.width, size.height - contentHeight)];
|| childConfig.widthSpec == DoricLayoutWrapContent
|| childConfig.heightSpec == DoricLayoutWrapContent) {
childSize = [child sizeThatFits:CGSizeMake(size.width, size.height - contentHeight)];
}
if (childConfig.widthSpec == DoricLayoutExact) {
childSize.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
childSize.width = size.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
childSize.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
childSize.height = size.height - contentHeight;
}
if (childConfig.weight) { if (childConfig.weight) {
childSize.height = child.height; childSize.height = child.height;
} }
@ -392,7 +293,8 @@ - (CGSize)sizeContent:(CGSize)size {
return CGSizeMake(contentWidth, contentHeight); return CGSizeMake(contentWidth, contentHeight);
} }
- (void)layout:(CGSize)targetSize { - (void)layoutSelf:(CGSize)targetSize {
[super layoutSelf:targetSize];
self.width = targetSize.width; self.width = targetSize.width;
self.height = targetSize.height; self.height = targetSize.height;
CGFloat yStart = 0; CGFloat yStart = 0;
@ -416,35 +318,12 @@ - (void)layout:(CGSize)targetSize {
childConfig = [DoricLayoutConfig new]; childConfig = [DoricLayoutConfig new];
} }
CGSize size = [child sizeThatFits:CGSizeMake(targetSize.width, targetSize.height - yStart)]; CGSize size = [child measureSize:CGSizeMake(targetSize.width, targetSize.height - yStart)];
if (childConfig.widthSpec == DoricLayoutExact) {
size.width = child.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
}
if (childConfig.widthSpec == DoricLayoutExact) {
size.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
size.width = targetSize.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
size.height = targetSize.height - yStart;
}
if (childConfig.weight) { if (childConfig.weight) {
size.height = child.height; size.height = child.height + remain / self.contentWeight * childConfig.weight;
} }
[child layoutSelf:size];
if (childConfig.weight) {
size.height += remain / self.contentWeight * childConfig.weight;
}
child.width = size.width;
child.height = size.height;
DoricGravity gravity = childConfig.alignment | self.gravity; DoricGravity gravity = childConfig.alignment | self.gravity;
if ((gravity & LEFT) == LEFT) { if ((gravity & LEFT) == LEFT) {
child.left = 0; child.left = 0;
} else if ((gravity & RIGHT) == RIGHT) { } else if ((gravity & RIGHT) == RIGHT) {
@ -466,20 +345,12 @@ - (void)layout:(CGSize)targetSize {
if (childConfig.margin.bottom) { if (childConfig.margin.bottom) {
yStart += childConfig.margin.bottom; yStart += childConfig.margin.bottom;
} }
if ([child isKindOfClass:[DoricLayoutContainer class]]) {
[(DoricLayoutContainer *) child layout:size];
}
} }
} }
@end @end
@implementation DoricHLayoutView @implementation DoricHLayoutView
- (CGSize)sizeThatFits:(CGSize)size {
- (void)layoutSelf {
[super layoutSelf];
}
- (CGSize)sizeContent:(CGSize)size {
CGFloat contentWidth = 0; CGFloat contentWidth = 0;
CGFloat contentHeight = 0; CGFloat contentHeight = 0;
NSUInteger contentWeight = 0; NSUInteger contentWeight = 0;
@ -491,30 +362,15 @@ - (CGSize)sizeContent:(CGSize)size {
if (!childConfig) { if (!childConfig) {
childConfig = [DoricLayoutConfig new]; childConfig = [DoricLayoutConfig new];
} }
CGSize childSize = CGSizeMake(child.width, child.height); CGSize childSize;
if (CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) { if (CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) {
if ([child isKindOfClass:[DoricLayoutContainer class]] childSize = [child measureSize:CGSizeMake(size.width - contentWidth, size.height)];
|| childConfig.widthSpec == DoricLayoutWrapContent
|| childConfig.heightSpec == DoricLayoutWrapContent) {
childSize = [child sizeThatFits:CGSizeMake(size.width - contentWidth, size.height)];
}
if (childConfig.widthSpec == DoricLayoutExact) {
childSize.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
childSize.width = size.width - contentWidth;
}
if (childConfig.heightSpec == DoricLayoutExact) {
childSize.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
childSize.height = size.height;
}
if (childConfig.weight) { if (childConfig.weight) {
childSize.width = child.width; childSize.width = child.width;
} }
} else { } else {
childSize = child.bounds.size; childSize = child.bounds.size;
} }
contentWidth += childSize.width + self.space + childConfig.margin.left + childConfig.margin.right; contentWidth += childSize.width + self.space + childConfig.margin.left + childConfig.margin.right;
contentHeight = MAX(contentHeight, childSize.height + childConfig.margin.top + childConfig.margin.bottom); contentHeight = MAX(contentHeight, childSize.height + childConfig.margin.top + childConfig.margin.bottom);
contentWeight += childConfig.weight; contentWeight += childConfig.weight;
@ -529,9 +385,8 @@ - (CGSize)sizeContent:(CGSize)size {
return CGSizeMake(contentWidth, contentHeight); return CGSizeMake(contentWidth, contentHeight);
} }
- (void)layout:(CGSize)targetSize { - (void)layoutSelf:(CGSize)targetSize {
self.width = targetSize.width; [super layoutSelf:targetSize];
self.height = targetSize.height;
CGFloat xStart = 0; CGFloat xStart = 0;
if (self.contentWeight) { if (self.contentWeight) {
xStart = 0; xStart = 0;
@ -555,32 +410,12 @@ - (void)layout:(CGSize)targetSize {
childConfig = [DoricLayoutConfig new]; childConfig = [DoricLayoutConfig new];
} }
CGSize size = [child sizeThatFits:CGSizeMake(targetSize.width - xStart, targetSize.height)]; CGSize size = [child measureSize:CGSizeMake(targetSize.width - xStart, targetSize.height)];
if (childConfig.widthSpec == DoricLayoutExact) {
size.width = child.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
}
if (childConfig.widthSpec == DoricLayoutExact) {
size.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
size.width = targetSize.width - xStart;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
size.height = targetSize.height;
}
if (childConfig.weight) { if (childConfig.weight) {
size.width = child.width; size.width = child.width + remain / self.contentWeight * childConfig.weight;
} }
if (childConfig.weight) { [child layoutSelf:size];
size.width += remain / self.contentWeight * childConfig.weight;
}
child.width = size.width;
child.height = size.height;
DoricGravity gravity = childConfig.alignment | self.gravity; DoricGravity gravity = childConfig.alignment | self.gravity;
if ((gravity & TOP) == TOP) { if ((gravity & TOP) == TOP) {
@ -605,9 +440,6 @@ - (void)layout:(CGSize)targetSize {
if (childConfig.margin.right) { if (childConfig.margin.right) {
xStart += childConfig.margin.right; xStart += childConfig.margin.right;
} }
if ([child isKindOfClass:[DoricLayoutContainer class]]) {
[(DoricLayoutContainer *) child layout:size];
}
} }
} }
@end @end

View File

@ -86,16 +86,6 @@ - (void)blend:(NSDictionary *)props {
self.view.contentView = it.view; self.view.contentView = it.view;
}]; }];
} }
dispatch_async(dispatch_get_main_queue(), ^{
[self.view also:^(DoricScrollView *it) {
[it layoutSelf];
if (it.contentView) {
CGSize size = [it.contentView sizeThatFits:it.frame.size];
[it setContentSize:size];
}
[it layoutSelf];
}];
});
} }
- (void)blendView:(DoricScrollView *)view forPropName:(NSString *)name propValue:(id)prop { - (void)blendView:(DoricScrollView *)view forPropName:(NSString *)name propValue:(id)prop {