diff --git a/doric-iOS/Pod/Classes/Plugin/DoricNavBarPlugin.m b/doric-iOS/Pod/Classes/Plugin/DoricNavBarPlugin.m index d6bc2fe2..d9095a26 100644 --- a/doric-iOS/Pod/Classes/Plugin/DoricNavBarPlugin.m +++ b/doric-iOS/Pod/Classes/Plugin/DoricNavBarPlugin.m @@ -81,7 +81,7 @@ - (void)setLeft:(NSDictionary *)params withPromise:(DoricPromise *)promise { viewNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) { it.viewId = viewId; [it initWithSuperNode:nil]; - it.view.layoutConfig = [DoricLayoutConfig new]; + it.view.doricLayout = [DoricLayout new]; [self.doricContext.navBar doric_navBar_setLeft:it.view]; NSMutableDictionary *map = self.doricContext.headNodes[TYPE_LEFT]; @@ -112,7 +112,7 @@ - (void)setRight:(NSDictionary *)params withPromise:(DoricPromise *)promise { viewNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) { it.viewId = viewId; [it initWithSuperNode:nil]; - it.view.layoutConfig = [DoricLayoutConfig new]; + it.view.doricLayout = [DoricLayout new]; [self.doricContext.navBar doric_navBar_setRight:it.view]; NSMutableDictionary *map = self.doricContext.headNodes[TYPE_RIGHT]; diff --git a/doric-iOS/Pod/Classes/Plugin/DoricPopoverPlugin.m b/doric-iOS/Pod/Classes/Plugin/DoricPopoverPlugin.m index f268c5db..252fc88d 100644 --- a/doric-iOS/Pod/Classes/Plugin/DoricPopoverPlugin.m +++ b/doric-iOS/Pod/Classes/Plugin/DoricPopoverPlugin.m @@ -17,7 +17,8 @@ - (void)show:(NSDictionary *)params withPromise:(DoricPromise *)promise { dispatch_async(dispatch_get_main_queue(), ^{ UIView *superView = [UIApplication sharedApplication].windows.lastObject; if (!self.fullScreenView) { - self.fullScreenView = [[DoricStackView new] also:^(UIView *it) { + self.fullScreenView = [[UIView new] also:^(UIView *it) { + it.doricLayout.layoutType = DoricStack; it.width = superView.width; it.height = superView.height; it.top = it.left = 0; @@ -33,7 +34,7 @@ - (void)show:(NSDictionary *)params withPromise:(DoricPromise *)promise { viewNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) { it.viewId = viewId; [it initWithSuperNode:nil]; - it.view.layoutConfig = [DoricLayoutConfig new]; + it.view.doricLayout = [DoricLayout new]; [self.fullScreenView addSubview:it.view]; NSMutableDictionary *map = self.doricContext.headNodes[TYPE]; diff --git a/doric-iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.m b/doric-iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.m index 25def1a5..610867c1 100644 --- a/doric-iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.m +++ b/doric-iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.m @@ -54,40 +54,40 @@ - (instancetype)init { return self; } -- (CGSize)sizeThatFits:(CGSize)size { - if (self.contentView) { - return [self.contentView measureSize:size]; - } - return CGSizeZero; -} - -- (BOOL)requestFromSubview:(UIView *)subview { - if (subview == self.headerView) { - return NO; - } - return [super requestFromSubview:subview]; -} +//- (CGSize)sizeThatFits:(CGSize)size { +// if (self.contentView) { +// return [self.contentView measureSize:size]; +// } +// return CGSizeZero; +//} +// +//- (BOOL)requestFromSubview:(UIView *)subview { +// if (subview == self.headerView) { +// return NO; +// } +// return [super requestFromSubview:subview]; +//} - (void)layoutSubviews { [super layoutSubviews]; } -- (void)layoutSelf:(CGSize)targetSize { - if (self.contentOffset.y != 0) { - return; - } - self.width = targetSize.width; - self.height = targetSize.height; - [self.headerView also:^(UIView *it) { - [it layoutSelf:[it measureSize:targetSize]]; - it.bottom = 0; - it.centerX = self.centerX; - }]; - [self.contentView also:^(UIView *it) { - [it layoutSelf:targetSize]; - }]; - self.contentSize = self.frame.size; -} +//- (void)layoutSelf:(CGSize)targetSize { +// if (self.contentOffset.y != 0) { +// return; +// } +// self.width = targetSize.width; +// self.height = targetSize.height; +// [self.headerView also:^(UIView *it) { +// [it layoutSelf:[it measureSize:targetSize]]; +// it.bottom = 0; +// it.centerX = self.centerX; +// }]; +// [self.contentView also:^(UIView *it) { +// [it layoutSelf:targetSize]; +// }]; +// self.contentSize = self.frame.size; +//} - (void)setContentView:(UIView *)contentView { if (_contentView) { diff --git a/doric-iOS/Pod/Classes/Shader/DoricDraggableNode.m b/doric-iOS/Pod/Classes/Shader/DoricDraggableNode.m index 6f5a625e..a4536d5a 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricDraggableNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricDraggableNode.m @@ -23,8 +23,8 @@ #import "DoricDraggableNode.h" @implementation DoricDraggableNode -- (DoricStackView *)build { - DoricStackView *stackView = [DoricStackView new]; +- (UIView *)build { + UIView *stackView = [UIView new]; UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onDrag:)]; [stackView addGestureRecognizer:gesture]; return stackView; @@ -40,7 +40,7 @@ - (void)onDrag:(UIPanGestureRecognizer *)gesture { [self callJSResponse:_onDragFunction, @(originalFrame.origin.x), @(originalFrame.origin.y), nil]; } -- (void)blendView:(DoricStackView *)view forPropName:(NSString *)name propValue:(id)prop { +- (void)blendView:(UIView *)view forPropName:(NSString *)name propValue:(id)prop { if ([name isEqualToString:@"onDrag"]) { _onDragFunction = prop; } else { diff --git a/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutItemNode.m b/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutItemNode.m index 417e87e0..44b08beb 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutItemNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutItemNode.m @@ -19,7 +19,7 @@ #import "DoricFlowLayoutItemNode.h" -@interface DoricFlowLayoutItemView : DoricStackView +@interface DoricFlowLayoutItemView : UIView @end @implementation DoricFlowLayoutItemView @@ -42,7 +42,7 @@ - (void)initWithSuperNode:(DoricSuperNode *)superNode { self.reusable = YES; } -- (DoricStackView *)build { +- (DoricFlowLayoutItemView *)build { return [DoricFlowLayoutItemView new]; } @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.m b/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.m index cde438e9..eb17f3f8 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.m @@ -139,23 +139,6 @@ @interface DoricFlowLayoutView : UICollectionView @end @implementation DoricFlowLayoutView -- (CGSize)sizeThatFits:(CGSize)size { - if (self.subviews.count > 0) { - CGFloat width = size.width; - CGFloat height = size.height; - for (UIView *child in self.subviews) { - CGSize childSize = [child measureSize:size]; - width = MAX(childSize.width, width); - height = MAX(childSize.height, height); - } - return CGSizeMake(width, height); - } - return size; -} - -- (void)layoutSelf:(CGSize)targetSize { - [super layoutSelf:targetSize]; -} @end @interface DoricFlowLayoutNode () @@ -336,14 +319,14 @@ - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collection node.viewId = model[@"id"]; [node blend:props]; CGFloat width = (collectionView.width - (self.columnCount - 1) * self.columnSpace) / self.columnCount; - CGSize size = [node.view measureSize:CGSizeMake(width, collectionView.height)]; - if (position > 0 && position >= self.itemCount && self.onLoadMoreFuncId) { - size = CGSizeMake(collectionView.width, size.height); - [self callJSResponse:self.onLoadMoreFuncId, nil]; - } - - [node.view layoutSelf:size]; - [self callItem:position size:size]; +// CGSize size = [node.view measureSize:CGSizeMake(width, collectionView.height)]; +// if (position > 0 && position >= self.itemCount && self.onLoadMoreFuncId) { +// size = CGSizeMake(collectionView.width, size.height); +// [self callJSResponse:self.onLoadMoreFuncId, nil]; +// } +// +// [node.view layoutSelf:size]; +// [self callItem:position size:size]; return cell; } diff --git a/doric-iOS/Pod/Classes/Shader/DoricGroupNode.m b/doric-iOS/Pod/Classes/Shader/DoricGroupNode.m index ac50601d..9fa56198 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricGroupNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricGroupNode.m @@ -51,16 +51,10 @@ - (void)blendView:(UIView *)view forPropName:(NSString *)name propValue:(id)prop } } -- (void)blend:(NSDictionary *)props { - [super blend:props]; +- (void)afterBlended:(NSDictionary *)props { [self configChildNodes]; } -- (DoricLayoutConfig *)generateDefaultLayoutParams { - DoricLayoutConfig *params = [[DoricLayoutConfig alloc] init]; - return params; -} - - (void)configChildNodes { NSMutableArray *childNodes = [self.childNodes mutableCopy]; for (NSUInteger idx = 0; idx < self.childViewIds.count; idx++) { diff --git a/doric-iOS/Pod/Classes/Shader/DoricHLayoutNode.h b/doric-iOS/Pod/Classes/Shader/DoricHLayoutNode.h index edcbda0a..64cadb7e 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricHLayoutNode.h +++ b/doric-iOS/Pod/Classes/Shader/DoricHLayoutNode.h @@ -22,5 +22,5 @@ #import "DoricGroupNode.h" -@interface DoricHLayoutNode : DoricGroupNode +@interface DoricHLayoutNode : DoricGroupNode @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricHLayoutNode.m b/doric-iOS/Pod/Classes/Shader/DoricHLayoutNode.m index ee66564a..c5cfe7a8 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricHLayoutNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricHLayoutNode.m @@ -21,18 +21,20 @@ // #import "DoricHLayoutNode.h" -#import "DoricUtil.h" +#import "DoricExtensions.h" @implementation DoricHLayoutNode -- (DoricHLayoutView *)build { - return [DoricHLayoutView new]; +- (UIView *)build { + return [[UIView new] also:^(UIView *it) { + it.doricLayout.layoutType = DoricHLayout; + }]; } -- (void)blendView:(DoricHLayoutView *)view forPropName:(NSString *)name propValue:(id)prop { +- (void)blendView:(UIView *)view forPropName:(NSString *)name propValue:(id)prop { if ([name isEqualToString:@"gravity"]) { - view.gravity = (DoricGravity) [(NSNumber *) prop integerValue]; + view.doricLayout.gravity = (DoricGravity) [(NSNumber *) prop integerValue]; } else if ([name isEqualToString:@"space"]) { - view.space = [(NSNumber *) prop floatValue]; + view.doricLayout.spacing = [(NSNumber *) prop floatValue]; } else { [super blendView:view forPropName:name propValue:prop]; } diff --git a/doric-iOS/Pod/Classes/Shader/DoricImageNode.m b/doric-iOS/Pod/Classes/Shader/DoricImageNode.m index eb599bdd..970596b8 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricImageNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricImageNode.m @@ -28,46 +28,9 @@ @interface DoricImageView : YYAnimatedImageView @end @implementation DoricImageView -- (CGSize)measureSize:(CGSize)targetSize { - CGFloat width = self.width; - CGFloat height = self.height; - DoricLayoutConfig *config = self.layoutConfig; - if (!config) { - config = [DoricLayoutConfig new]; - } - if (config.widthSpec == DoricLayoutMost - || config.widthSpec == DoricLayoutFit) { - width = targetSize.width - config.margin.left - config.margin.right; - } - if (config.heightSpec == DoricLayoutMost - || config.heightSpec == DoricLayoutFit) { - height = targetSize.height - config.margin.top - config.margin.bottom; - } - DoricPadding padding = self.padding; - CGSize contentSize = [self sizeThatFits:CGSizeMake( - width - padding.left - padding.right, - height - padding.top - padding.bottom)]; - if (config.widthSpec == DoricLayoutFit) { - width = contentSize.width + padding.left + padding.right; - if (config.heightSpec != DoricLayoutFit && contentSize.width != 0 && contentSize.height != 0) { - width = contentSize.width / contentSize.height * height + padding.left + padding.right; - } - } - if (config.heightSpec == DoricLayoutFit) { - height = contentSize.height + padding.top + padding.bottom; - if (config.widthSpec != DoricLayoutFit && contentSize.width != 0 && contentSize.height != 0) { - height = contentSize.height / contentSize.width * width + padding.top + padding.bottom; - } - } - if (config.weight) { - if ([self.superview isKindOfClass:[DoricVLayoutView class]]) { - height = self.height; - } else if ([self.superview isKindOfClass:[DoricHLayoutView class]]) { - width = self.width; - } - } - return CGSizeMake(width, height); +- (CGSize)sizeThatFits:(CGSize)size { + return [self sizeThatFits:size]; } @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricLayouts.h b/doric-iOS/Pod/Classes/Shader/DoricLayouts.h index a8526e7c..722adab3 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricLayouts.h +++ b/doric-iOS/Pod/Classes/Shader/DoricLayouts.h @@ -26,6 +26,14 @@ typedef UIEdgeInsets DoricPadding; DoricMargin DoricMarginMake(CGFloat left, CGFloat top, CGFloat right, CGFloat bottom); + +typedef NS_ENUM(NSInteger, DoricLayoutType) { + DoricUndefined = 0, + DoricStack = 1, + DoricVLayout = 2, + DoricHLayout = 3, +}; + typedef NS_ENUM(NSInteger, DoricLayoutSpec) { DoricLayoutJust = 0, DoricLayoutFit = 1, @@ -40,67 +48,52 @@ typedef NS_ENUM(NSInteger, DoricGravity) { DoricGravityShiftY = 4, DoricGravityLeft = (DoricGravityStart | DoricGravitySpecified) << DoricGravityShiftX, DoricGravityRight = (DoricGravityEnd | DoricGravitySpecified) << DoricGravityShiftX, - DoricGravityTOP = (DoricGravityStart | DoricGravitySpecified) << DoricGravityShiftY, + DoricGravityTop = (DoricGravityStart | DoricGravitySpecified) << DoricGravityShiftY, DoricGravityBottom = (DoricGravityEnd | DoricGravitySpecified) << DoricGravityShiftY, DoricGravityCenterX = DoricGravitySpecified << DoricGravityShiftX, DoricGravityCenterY = DoricGravitySpecified << DoricGravityShiftY, DoricGravityCenter = DoricGravityCenterX | DoricGravityCenterY, }; -@interface DoricLayoutConfig : NSObject +@interface DoricLayout : NSObject @property(nonatomic, assign) DoricLayoutSpec widthSpec; @property(nonatomic, assign) DoricLayoutSpec heightSpec; -@property(nonatomic) DoricMargin margin; + @property(nonatomic, assign) DoricGravity alignment; + +@property(nonatomic, assign) DoricGravity gravity; + +@property(nonatomic, assign) CGFloat width; +@property(nonatomic, assign) CGFloat height; +@property(nonatomic, assign) CGFloat x; +@property(nonatomic, assign) CGFloat y; + +@property(nonatomic, assign) CGFloat spacing; + +@property(nonatomic, assign) CGFloat marginLeft; +@property(nonatomic, assign) CGFloat marginTop; +@property(nonatomic, assign) CGFloat marginRight; +@property(nonatomic, assign) CGFloat marginBottom; + +@property(nonatomic, assign) CGFloat paddingLeft; +@property(nonatomic, assign) CGFloat paddingTop; +@property(nonatomic, assign) CGFloat paddingRight; +@property(nonatomic, assign) CGFloat paddingBottom; + @property(nonatomic, assign) NSUInteger weight; +@property(nonatomic, weak) UIView *view; + +@property(nonatomic, assign) DoricLayoutType layoutType; + +@property(nonatomic, assign) BOOL disabled; + - (instancetype)init; -- (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)height; - -- (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)height margin:(DoricMargin)margin; - +- (void)apply; @end -@interface DoricLayoutContainer : UIView -@end - -@interface DoricStackView : DoricLayoutContainer -@end - -@interface DoricLinearView : DoricLayoutContainer -@property(nonatomic, assign) DoricGravity gravity; -@property(nonatomic, assign) CGFloat space; -@end - - -@interface DoricVLayoutView : DoricLinearView -@end - -@interface DoricHLayoutView : DoricLinearView -@end - -@interface UIView (DoricLayoutConfig) -@property(nonatomic, strong) DoricLayoutConfig *layoutConfig; -@end - -@interface UIView (DoricPadding) -@property(nonatomic, assign) DoricPadding padding; -@end - -@interface UIView (DoricTag) -@property(nonatomic, copy) NSString *tagString; - -- (UIView *)viewWithTagString:(NSString *)tagString; -@end - -@interface UIView (DoricLayouts) -- (void)layoutSelf:(CGSize)targetSize; - -- (CGSize)measureSize:(CGSize)targetSize; - -- (void)doricLayoutSubviews; - -- (BOOL)requestFromSubview:(UIView *)subview; -@end +@interface UIView (DoricLayout) +@property(nonatomic, strong) DoricLayout *doricLayout; +@end \ No newline at end of file diff --git a/doric-iOS/Pod/Classes/Shader/DoricLayouts.m b/doric-iOS/Pod/Classes/Shader/DoricLayouts.m index 0db9df8a..cbd3c03a 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricLayouts.m +++ b/doric-iOS/Pod/Classes/Shader/DoricLayouts.m @@ -20,138 +20,45 @@ #import "DoricLayouts.h" #import #import "UIView+Doric.h" +#import "DoricExtensions.h" static const void *kLayoutConfig = &kLayoutConfig; -@implementation UIView (DoricLayoutConfig) -@dynamic layoutConfig; +@implementation UIView (DoricLayout) +@dynamic doricLayout; -- (void)setLayoutConfig:(DoricLayoutConfig *)layoutConfig { - objc_setAssociatedObject(self, kLayoutConfig, layoutConfig, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +- (void)setDoricLayout:(DoricLayout *)doricLayout { + objc_setAssociatedObject(self, kLayoutConfig, doricLayout, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } -- (DoricLayoutConfig *)layoutConfig { - return objc_getAssociatedObject(self, kLayoutConfig); +- (DoricLayout *)doricLayout { + DoricLayout *layout = objc_getAssociatedObject(self, kLayoutConfig); + if (!layout) { + layout = [DoricLayout new]; + layout.width = self.width; + layout.height = self.height; + layout.x = self.x; + layout.y = self.y; + layout.view = self; + self.doricLayout = layout; + } + return layout; } @end -static const void *kLayoutPadding = &kLayoutPadding; - -@implementation UIView (DoricPadding) -@dynamic padding; - -- (void)setPadding:(DoricPadding)padding { - objc_setAssociatedObject(self, kLayoutPadding, [NSValue value:&padding withObjCType:@encode(DoricPadding)], OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -- (DoricPadding)padding { - DoricPadding value; - value.left = value.right = value.top = value.bottom = 0; - [objc_getAssociatedObject(self, kLayoutPadding) getValue:&value]; - return value; -} +@interface DoricLayout () +@property(nonatomic, assign) CGFloat contentWidth; +@property(nonatomic, assign) CGFloat contentHeight; +@property(nonatomic, assign) CGFloat measuredWidth; +@property(nonatomic, assign) CGFloat measuredHeight; +@property(nonatomic, assign) CGFloat measuredX; +@property(nonatomic, assign) CGFloat measuredY; +@property(nonatomic, assign) BOOL resolved; @end -static const void *kTagString = &kTagString; - -@implementation UIView (DoricTag) - -- (void)setTagString:(NSString *)tagString { - objc_setAssociatedObject(self, kTagString, tagString, OBJC_ASSOCIATION_COPY_NONATOMIC); - self.tag = [tagString hash]; -} - -- (NSString *)tagString { - return objc_getAssociatedObject(self, kTagString); -} - - -- (UIView *)viewWithTagString:(NSString *)tagString { - // notice the potential hash collision - return [self viewWithTag:[tagString hash]]; -} - -@end - - -@implementation UIView (DoricLayouts) -/** - * Measure self's size - * */ -- (CGSize)measureSize:(CGSize)targetSize { - CGFloat width = self.width; - CGFloat height = self.height; - - DoricLayoutConfig *config = self.layoutConfig; - if (!config) { - config = [DoricLayoutConfig new]; - } - if (config.widthSpec == DoricLayoutMost - || config.widthSpec == DoricLayoutFit) { - width = targetSize.width - config.margin.left - config.margin.right; - } - if (config.heightSpec == DoricLayoutMost - || config.heightSpec == DoricLayoutFit) { - height = targetSize.height - config.margin.top - config.margin.bottom; - } - DoricPadding padding = self.padding; - CGSize contentSize = [self sizeThatFits:CGSizeMake( - width - padding.left - padding.right, - height - padding.top - padding.bottom)]; - if (config.widthSpec == DoricLayoutFit) { - width = contentSize.width + padding.left + padding.right; - } - if (config.heightSpec == DoricLayoutFit) { - height = contentSize.height + padding.top + padding.bottom; - } - if (config.weight) { - if ([self.superview isKindOfClass:[DoricVLayoutView class]]) { - height = self.height; - } else if ([self.superview isKindOfClass:[DoricHLayoutView class]]) { - width = self.width; - } - } - return CGSizeMake(width, height); -} - -/** - * layout self and subviews - * */ -- (void)layoutSelf:(CGSize)targetSize { - self.width = targetSize.width; - self.height = targetSize.height; - for (UIView *view in self.subviews) { - [view layoutSelf:[view measureSize:targetSize]]; - } -} - - -- (void)doricLayoutSubviews { - if ([self.superview requestFromSubview:self]) { - [self.superview doricLayoutSubviews]; - } else { - CGSize size = [self measureSize:CGSizeMake(self.superview.width, self.superview.height)]; - [self layoutSelf:size]; - } -} - -- (BOOL)requestFromSubview:(UIView *)subview { - if (self.layoutConfig - && self.layoutConfig.widthSpec != DoricLayoutJust - && self.layoutConfig.heightSpec != DoricLayoutJust) { - return YES; - } - return NO; -} -@end - -DoricMargin DoricMarginMake(CGFloat left, CGFloat top, CGFloat right, CGFloat bottom) { - return UIEdgeInsetsMake(top, left, bottom, right); -} - -@implementation DoricLayoutConfig +@implementation DoricLayout - (instancetype)init { if (self = [super init]) { _widthSpec = DoricLayoutJust; @@ -160,349 +67,317 @@ - (instancetype)init { return self; } -- (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)height { - if (self = [super init]) { - _widthSpec = width; - _heightSpec = height; +- (void)apply { + if (!CGAffineTransformEqualToTransform(self.view.transform, CGAffineTransformIdentity)) { + return; } - return self; + self.resolved = NO; + [self measure:self.view.frame.size]; + [self layout]; + [self setFrame]; } -- (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)height margin:(DoricMargin)margin { - if (self = [super init]) { - _widthSpec = width; - _heightSpec = height; - _margin = margin; +- (void)measure:(CGSize)targetSize { + if (self.widthSpec == DoricLayoutMost) { + self.measuredWidth = targetSize.width; + } else { + self.measuredWidth = self.width; } - return self; -} -@end - - -@interface DoricLayoutContainer () -@property(nonatomic, assign) CGFloat contentWidth; -@property(nonatomic, assign) CGFloat contentHeight; -@property(nonatomic, assign) NSUInteger contentWeight; -@end - -@implementation DoricLayoutContainer -- (void)setNeedsLayout { - [super setNeedsLayout]; + if (self.heightSpec == DoricLayoutMost) { + self.measuredHeight = targetSize.height; + } else{ + self.measuredHeight = self.height; + } + [self measureContent:CGSizeMake( + self.measuredWidth - self.paddingLeft - self.paddingRight, + self.measuredHeight - self.paddingTop - self.paddingBottom)]; + self.resolved = YES; } -- (void)layoutSubviews { - [super layoutSubviews]; - [self doricLayoutSubviews]; +- (void)measureContent:(CGSize)targetSize { + switch (self.layoutType) { + case DoricStack: { + [self measureStackContent:targetSize]; + break; + } + case DoricVLayout: { + [self measureVLayoutContent:targetSize]; + break; + } + case DoricHLayout: { + [self measureHLayoutContent:targetSize]; + break; + } + default: { + [self measureUndefinedContent:targetSize]; + break; + } + } } -@end +- (void)layout { + switch (self.layoutType) { + case DoricStack: { + [self layoutStack]; + break; + } + case DoricVLayout: { + [self layoutVLayout]; + break; + } + case DoricHLayout: { + [self layoutHLayout]; + break; + } + default: { + break; + } + } +} -@interface DoricStackView () -@end +- (void)setFrame { + [self.view.subviews forEach:^(__kindof UIView *obj) { + [obj.doricLayout setFrame]; + }]; + self.view.width = self.measuredWidth; + self.view.height = self.measuredHeight; + self.view.x = self.measuredX; + self.view.y = self.measuredY; +} -@implementation DoricStackView +- (void)measureUndefinedContent:(CGSize)targetSize { + CGSize measuredSize = [self.view sizeThatFits:targetSize]; + if (self.widthSpec == DoricLayoutFit) { + self.measuredWidth = measuredSize.width + self.paddingLeft + self.paddingRight; + } + if (self.heightSpec == DoricLayoutFit) { + self.measuredHeight = measuredSize.height + self.paddingTop + self.paddingBottom; + } +} -- (CGSize)sizeThatFits:(CGSize)size { - CGFloat contentWidth = 0; - CGFloat contentHeight = 0; - for (UIView *child in self.subviews) { - if (child.isHidden) { +- (CGFloat)takenWidth { + return self.measuredWidth + self.marginLeft + self.marginRight; +} + +- (CGFloat)takenHeight { + return self.measuredHeight + self.marginTop + self.marginBottom; +} + +- (void)measureStackContent:(CGSize)targetSize { + CGFloat contentWidth = 0, contentHeight = 0; + for (__kindof UIView *subview in self.view.subviews) { + DoricLayout *layout = subview.doricLayout; + if (layout.disabled) { continue; } - DoricLayoutConfig *childConfig = child.layoutConfig; - if (!childConfig) { - childConfig = [DoricLayoutConfig new]; - } - CGSize childSize; - if (CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) { - childSize = [child measureSize:CGSizeMake(size.width, size.height)]; - } else { - childSize = child.bounds.size; - } - contentWidth = MAX(contentWidth, childSize.width + childConfig.margin.left + childConfig.margin.right); - contentHeight = MAX(contentHeight, childSize.height + childConfig.margin.top + childConfig.margin.bottom); + [layout measure:targetSize]; + contentWidth = MAX(contentWidth, layout.takenWidth); + contentHeight = MAX(contentHeight, layout.takenHeight); } + if (self.widthSpec == DoricLayoutFit) { + self.measuredWidth = contentWidth + self.paddingLeft + self.paddingRight; + } + + if (self.heightSpec == DoricLayoutFit) { + self.measuredHeight = contentHeight + self.paddingTop + self.paddingBottom; + } + self.contentWidth = contentWidth; + self.contentHeight = contentHeight; - return CGSizeMake(contentWidth, contentHeight); } -- (void)layoutSelf:(CGSize)targetSize { - self.width = targetSize.width; - self.height = targetSize.height; - DoricPadding padding = self.padding; - - for (UIView *child in self.subviews) { - if (child.isHidden) { +- (void)measureVLayoutContent:(CGSize)targetSize { + CGFloat contentWidth = 0, contentHeight = 0; + BOOL had = NO; + for (__kindof UIView *subview in self.view.subviews) { + DoricLayout *layout = subview.doricLayout; + if (layout.disabled) { continue; } - if (!CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) { + had = YES; + [layout measure:CGSizeMake(targetSize.width, targetSize.height - contentHeight)]; + contentWidth = MAX(contentWidth, layout.takenWidth); + contentHeight += layout.takenHeight + self.spacing; + } + + if (had) { + contentHeight -= self.spacing; + } + + if (self.widthSpec == DoricLayoutFit) { + self.measuredWidth = contentWidth + self.paddingLeft + self.paddingRight; + } + + if (self.heightSpec == DoricLayoutFit) { + self.measuredHeight = contentHeight + self.paddingTop + self.paddingBottom; + } + + self.contentWidth = contentWidth; + + self.contentHeight = contentHeight; +} + +- (void)measureHLayoutContent:(CGSize)targetSize { + CGFloat contentWidth = 0, contentHeight = 0; + BOOL had = NO; + for (__kindof UIView *subview in self.view.subviews) { + DoricLayout *layout = subview.doricLayout; + if (layout.disabled) { continue; } - DoricLayoutConfig *childConfig = child.layoutConfig; - if (!childConfig) { - childConfig = [DoricLayoutConfig new]; - } - CGSize size = [child measureSize:CGSizeMake( - targetSize.width - padding.left - padding.right, - targetSize.height - padding.top - padding.bottom)]; - [child layoutSelf:size]; - DoricGravity gravity = childConfig.alignment; + had = YES; + [layout measure:CGSizeMake(targetSize.width - contentWidth, targetSize.height)]; + contentWidth += layout.takenWidth + self.spacing; + contentHeight = MAX(contentHeight, layout.takenHeight); + } - CGPoint point = child.frame.origin; + if (had) { + contentWidth -= self.spacing; + } + if (self.widthSpec == DoricLayoutFit) { + self.measuredWidth = contentWidth + self.paddingLeft + self.paddingRight; + } + + if (self.heightSpec == DoricLayoutFit) { + self.measuredHeight = contentHeight + self.paddingTop + self.paddingBottom; + } + + self.contentWidth = contentWidth; + + self.contentHeight = contentHeight; +} + +- (void)layoutStack { + for (__kindof UIView *subview in self.view.subviews) { + DoricLayout *layout = subview.doricLayout; + if (layout.disabled) { + continue; + } + [layout layout]; + DoricGravity gravity = layout.alignment; if ((gravity & DoricGravityLeft) == DoricGravityLeft) { - point.x = padding.left; + layout.measuredX = self.paddingLeft; } else if ((gravity & DoricGravityRight) == DoricGravityRight) { - point.x = targetSize.width - padding.right - child.width; + layout.measuredX = self.measuredWidth - self.paddingRight - layout.measuredWidth; } else if ((gravity & DoricGravityCenterX) == DoricGravityCenterX) { - point.x = targetSize.width / 2 - child.width / 2; + layout.measuredX = self.measuredWidth / 2 - layout.measuredWidth / 2; } else { - if (childConfig.margin.left || childConfig.margin.right) { - point.x = padding.left; + if (layout.marginLeft || layout.marginRight) { + layout.measuredX = self.paddingLeft; + } else { + layout.measuredX = layout.x; } } - if ((gravity & DoricGravityTOP) == DoricGravityTOP) { - point.y = padding.top; + if ((gravity & DoricGravityTop) == DoricGravityTop) { + layout.measuredY = self.paddingTop; } else if ((gravity & DoricGravityBottom) == DoricGravityBottom) { - point.y = targetSize.height - padding.bottom - child.height; + layout.measuredY = self.measuredHeight - self.paddingBottom - layout.measuredHeight; } else if ((gravity & DoricGravityCenterY) == DoricGravityCenterY) { - point.y = targetSize.height / 2 - child.height / 2; + layout.measuredY = self.measuredHeight / 2 - layout.measuredHeight / 2; } else { - if (childConfig.margin.top || childConfig.margin.bottom) { - point.y = padding.top; + if (layout.marginTop || layout.marginBottom) { + layout.measuredY = self.paddingTop; + } else { + layout.measuredY = layout.y; } } if (!gravity) { - gravity = DoricGravityLeft | DoricGravityTOP; + gravity = DoricGravityLeft | DoricGravityTop; } - if (childConfig.margin.left && !((gravity & DoricGravityRight) == DoricGravityRight)) { - point.x += childConfig.margin.left; + if (layout.marginLeft && !((gravity & DoricGravityRight) == DoricGravityRight)) { + layout.measuredX += layout.marginLeft; } - if (childConfig.margin.right && !((gravity & DoricGravityLeft) == DoricGravityLeft)) { - point.x -= childConfig.margin.right; + if (layout.marginRight && !((gravity & DoricGravityLeft) == DoricGravityLeft)) { + layout.measuredX -= layout.marginRight; } - if (childConfig.margin.top && !((gravity & DoricGravityBottom) == DoricGravityBottom)) { - point.y += childConfig.margin.top; + if (layout.marginTop && !((gravity & DoricGravityBottom) == DoricGravityBottom)) { + layout.measuredY += layout.marginTop; } - if (childConfig.margin.bottom && !((gravity & DoricGravityTOP) == DoricGravityTOP)) { - point.y -= childConfig.margin.bottom; - } - if (point.x != child.x) { - child.x = point.x; - } - if (point.y != child.y) { - child.y = point.y; + if (layout.marginBottom && !((gravity & DoricGravityTop) == DoricGravityTop)) { + layout.measuredY -= layout.marginBottom; } } } -@end -@implementation DoricLinearView -@end - -@implementation DoricVLayoutView - -- (CGSize)sizeThatFits:(CGSize)size { - CGFloat contentWidth = 0; - CGFloat contentHeight = 0; - NSUInteger contentWeight = 0; - for (UIView *child in self.subviews) { - if (child.isHidden) { - continue; - } - DoricLayoutConfig *childConfig = child.layoutConfig; - if (!childConfig) { - childConfig = [DoricLayoutConfig new]; - } - CGSize childSize; - if (CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) { - childSize = [child measureSize:CGSizeMake(size.width, size.height - contentHeight)]; - } else { - childSize = child.bounds.size; - } - contentWidth = MAX(contentWidth, childSize.width + childConfig.margin.left + childConfig.margin.right); - contentHeight += childSize.height + self.space + childConfig.margin.top + childConfig.margin.bottom; - contentWeight += childConfig.weight; - } - contentHeight -= self.space; - self.contentWidth = contentWidth; - self.contentHeight = contentHeight; - self.contentWeight = contentWeight; - if (contentWeight) { - contentHeight = size.height; - } - return CGSizeMake(contentWidth, contentHeight); -} - -- (void)layoutSelf:(CGSize)targetSize { - self.width = targetSize.width; - self.height = targetSize.height; - DoricPadding padding = self.padding; - CGFloat yStart = padding.top; - if ((self.gravity & DoricGravityTOP) == DoricGravityTOP) { - yStart = padding.top; +- (void)layoutVLayout { + CGFloat yStart = self.paddingTop; + if ((self.gravity & DoricGravityTop) == DoricGravityTop) { + yStart = self.paddingTop; } else if ((self.gravity & DoricGravityBottom) == DoricGravityBottom) { - yStart = targetSize.height - self.contentHeight - padding.bottom; + yStart = self.measuredHeight - self.contentHeight - self.paddingBottom; } else if ((self.gravity & DoricGravityCenterY) == DoricGravityCenterY) { - yStart = (targetSize.height - self.contentHeight - padding.top - padding.bottom) / 2 + padding.top; + yStart = (self.measuredHeight - self.contentHeight - self.paddingTop - self.paddingBottom) / 2 + self.paddingTop; } - CGFloat remain = targetSize.height - self.contentHeight - padding.top - padding.bottom; - for (UIView *child in self.subviews) { - if (child.isHidden) { + for (UIView *child in self.view.subviews) { + DoricLayout *layout = child.doricLayout; + if (layout.disabled) { continue; } - if (!CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) { - continue; - } - DoricLayoutConfig *childConfig = child.layoutConfig; - if (!childConfig) { - childConfig = [DoricLayoutConfig new]; - } - - CGSize size = [child measureSize:CGSizeMake( - targetSize.width - padding.left - padding.right, - targetSize.height - yStart - padding.bottom)]; - if (childConfig.weight) { - size.height += remain / self.contentWeight * childConfig.weight; - } - [child layoutSelf:size]; - DoricGravity gravity = childConfig.alignment | self.gravity; - CGPoint point = child.frame.origin; + [layout layout]; + DoricGravity gravity = layout.alignment | self.gravity; if ((gravity & DoricGravityLeft) == DoricGravityLeft) { - point.x = padding.left; + layout.measuredX = self.paddingLeft; } else if ((gravity & DoricGravityRight) == DoricGravityRight) { - point.x = targetSize.width - padding.right - child.width; + layout.measuredX = self.measuredWidth - self.paddingRight - layout.measuredWidth; } else if ((gravity & DoricGravityCenterX) == DoricGravityCenterX) { - point.x = targetSize.width / 2 - child.width / 2; + layout.measuredX = self.measuredWidth / 2 - layout.measuredWidth / 2; } else { - point.x = padding.left; + layout.measuredX = self.paddingLeft; } if (!gravity) { gravity = DoricGravityLeft; } - if (childConfig.margin.left && !((gravity & DoricGravityRight) == DoricGravityRight)) { - point.x += childConfig.margin.left; + if (layout.marginLeft && !((gravity & DoricGravityRight) == DoricGravityRight)) { + layout.measuredX += layout.marginLeft; } - if (childConfig.margin.right && !((gravity & DoricGravityLeft) == DoricGravityLeft)) { - point.x -= childConfig.margin.right; - } - if (point.x != child.x) { - child.x = point.x; - } - if (childConfig.margin.top) { - yStart += childConfig.margin.top; - } - child.top = yStart; - yStart = child.bottom + self.space; - if (childConfig.margin.bottom) { - yStart += childConfig.margin.bottom; + if (layout.marginRight && !((gravity & DoricGravityLeft) == DoricGravityLeft)) { + layout.measuredX -= layout.marginRight; } + layout.measuredY = yStart + layout.marginTop; + yStart += self.spacing + layout.takenHeight; } } -@end -@implementation DoricHLayoutView -- (CGSize)sizeThatFits:(CGSize)size { - CGFloat contentWidth = 0; - CGFloat contentHeight = 0; - NSUInteger contentWeight = 0; - for (UIView *child in self.subviews) { - if (child.isHidden) { - continue; - } - DoricLayoutConfig *childConfig = child.layoutConfig; - if (!childConfig) { - childConfig = [DoricLayoutConfig new]; - } - CGSize childSize; - if (CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) { - childSize = [child measureSize:CGSizeMake(size.width - contentWidth, size.height)]; - } else { - childSize = child.bounds.size; - } - contentWidth += childSize.width + self.space + childConfig.margin.left + childConfig.margin.right; - contentHeight = MAX(contentHeight, childSize.height + childConfig.margin.top + childConfig.margin.bottom); - contentWeight += childConfig.weight; - } - if (self.subviews.count > 0) { - contentWidth -= self.space; - } - self.contentWidth = contentWidth; - self.contentHeight = contentHeight; - self.contentWeight = contentWeight; - if (contentWeight) { - contentWidth = size.width; - } - return CGSizeMake(contentWidth, contentHeight); -} - -- (void)layoutSelf:(CGSize)targetSize { - self.width = targetSize.width; - self.height = targetSize.height; - DoricPadding padding = self.padding; - CGFloat xStart = padding.left; +- (void)layoutHLayout { + CGFloat xStart = self.paddingLeft; if ((self.gravity & DoricGravityLeft) == DoricGravityLeft) { - xStart = padding.left; + xStart = self.paddingLeft; } else if ((self.gravity & DoricGravityRight) == DoricGravityRight) { - xStart = targetSize.width - self.contentWidth - padding.right; + xStart = self.measuredWidth - self.contentWidth - self.paddingRight; } else if ((self.gravity & DoricGravityCenterX) == DoricGravityCenterX) { - xStart = (targetSize.width - self.contentWidth - padding.left - padding.right) / 2 + padding.left; + xStart = (self.measuredWidth - self.contentWidth - self.paddingLeft - self.paddingRight) / 2 + self.paddingLeft; } - CGFloat remain = targetSize.width - self.contentWidth - padding.left - padding.right; - for (UIView *child in self.subviews) { - if (child.isHidden) { + for (UIView *child in self.view.subviews) { + DoricLayout *layout = child.doricLayout; + if (layout.disabled) { continue; } - if (!CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) { - continue; - } - DoricLayoutConfig *childConfig = child.layoutConfig; - if (!childConfig) { - childConfig = [DoricLayoutConfig new]; - } + [layout layout]; - CGSize size = [child measureSize:CGSizeMake( - targetSize.width - xStart - padding.right, - targetSize.height - padding.top - padding.bottom)]; - if (childConfig.weight) { - size.width += remain / self.contentWeight * childConfig.weight; - } - - [child layoutSelf:size]; - - DoricGravity gravity = childConfig.alignment | self.gravity; - - CGPoint point = child.frame.origin; - if ((gravity & DoricGravityTOP) == DoricGravityTOP) { - point.y = padding.top; + DoricGravity gravity = layout.alignment | self.gravity; + if ((gravity & DoricGravityTop) == DoricGravityTop) { + layout.measuredY = self.paddingTop; } else if ((gravity & DoricGravityBottom) == DoricGravityBottom) { - point.y = targetSize.height - padding.bottom - child.height; + layout.measuredY = self.measuredHeight - self.paddingBottom - child.height; } else if ((gravity & DoricGravityCenterY) == DoricGravityCenterY) { - point.y = targetSize.height / 2 - child.height / 2; + layout.measuredY = self.measuredHeight / 2 - layout.measuredHeight / 2; } else { - point.y = padding.top; + layout.measuredY = self.paddingTop; } if (!gravity) { - gravity = DoricGravityTOP; + gravity = DoricGravityTop; } - if (childConfig.margin.top && !((gravity & DoricGravityBottom) == DoricGravityBottom)) { - point.y += childConfig.margin.top; + if (layout.marginTop && !((gravity & DoricGravityBottom) == DoricGravityBottom)) { + layout.measuredY += layout.marginTop; } - if (childConfig.margin.bottom && !((gravity & DoricGravityTOP) == DoricGravityTOP)) { - point.y -= childConfig.margin.bottom; - } - if (point.y != child.y) { - child.y = point.y; - } - if (childConfig.margin.left) { - xStart += childConfig.margin.left; - } - child.left = xStart; - xStart = child.right + self.space; - if (childConfig.margin.right) { - xStart += childConfig.margin.right; + if (layout.marginBottom && !((gravity & DoricGravityTop) == DoricGravityTop)) { + layout.measuredY -= layout.marginBottom; } + layout.measuredX = xStart + layout.marginLeft; + xStart += self.spacing + layout.takenWidth; } } + @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricListItemNode.m b/doric-iOS/Pod/Classes/Shader/DoricListItemNode.m index f08abf9d..5662e746 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricListItemNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricListItemNode.m @@ -23,7 +23,7 @@ @interface DoricListItemNode () @end -@interface DoricListItemView : DoricStackView +@interface DoricListItemView : UIView @end @implementation DoricListItemView @@ -43,7 +43,7 @@ - (void)initWithSuperNode:(DoricSuperNode *)superNode { self.reusable = YES; } -- (DoricStackView *)build { +- (DoricListItemView *)build { return [DoricListItemView new]; } @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricListNode.m b/doric-iOS/Pod/Classes/Shader/DoricListNode.m index 0ca9ded7..a8483fa2 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricListNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricListNode.m @@ -35,24 +35,24 @@ @interface DoricTableView : UITableView @end @implementation DoricTableView -- (CGSize)sizeThatFits:(CGSize)size { - if (self.subviews.count > 0) { - CGFloat width = size.width; - CGFloat height = 0; - - for (UIView *child in self.subviews) { - CGSize childSize = [child measureSize:size]; - width = MAX(childSize.width, width); - height += childSize.height; - } - return CGSizeMake(width, MAX(height, size.height)); - } - return size; -} - -- (void)layoutSelf:(CGSize)targetSize { - [super layoutSelf:targetSize]; -} +//- (CGSize)sizeThatFits:(CGSize)size { +// if (self.subviews.count > 0) { +// CGFloat width = size.width; +// CGFloat height = 0; +// +// for (UIView *child in self.subviews) { +// CGSize childSize = [child measureSize:size]; +// width = MAX(childSize.width, width); +// height += childSize.height; +// } +// return CGSizeMake(width, MAX(height, size.height)); +// } +// return size; +//} +// +//- (void)layoutSelf:(CGSize)targetSize { +// [super layoutSelf:targetSize]; +//} @end @@ -158,9 +158,9 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N DoricListItemNode *node = cell.doricListItemNode; node.viewId = model[@"id"]; [node blend:props]; - CGSize size = [node.view measureSize:CGSizeMake(tableView.width, tableView.height)]; - [node.view layoutSelf:size]; - [self callItem:position height:size.height]; +// CGSize size = [node.view measureSize:CGSizeMake(tableView.width, tableView.height)]; +// [node.view layoutSelf:size]; +// [self callItem:position height:size.height]; return cell; } diff --git a/doric-iOS/Pod/Classes/Shader/DoricNestedSliderNode.m b/doric-iOS/Pod/Classes/Shader/DoricNestedSliderNode.m index cc1815d4..c9730795 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricNestedSliderNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricNestedSliderNode.m @@ -25,27 +25,27 @@ @interface DoricNestedSliderView : UIScrollView @end @implementation DoricNestedSliderView -- (CGSize)sizeThatFits:(CGSize)size { - if (self.subviews.count > 0) { - CGFloat width = size.width; - CGFloat height = size.height; - for (UIView *child in self.subviews) { - CGSize childSize = [child measureSize:size]; - width = MAX(childSize.width, width); - height = MAX(childSize.height, height); - } - return CGSizeMake(width, height); - } - return size; -} - -- (void)layoutSelf:(CGSize)targetSize { - [super layoutSelf:targetSize]; - [self.subviews forEachIndexed:^(__kindof UIView *obj, NSUInteger idx) { - obj.left = idx * self.width; - }]; - [self setContentSize:CGSizeMake(self.subviews.count * self.width, self.height)]; -} +//- (CGSize)sizeThatFits:(CGSize)size { +// if (self.subviews.count > 0) { +// CGFloat width = size.width; +// CGFloat height = size.height; +// for (UIView *child in self.subviews) { +// CGSize childSize = [child measureSize:size]; +// width = MAX(childSize.width, width); +// height = MAX(childSize.height, height); +// } +// return CGSizeMake(width, height); +// } +// return size; +//} +// +//- (void)layoutSelf:(CGSize)targetSize { +// [super layoutSelf:targetSize]; +// [self.subviews forEachIndexed:^(__kindof UIView *obj, NSUInteger idx) { +// obj.left = idx * self.width; +// }]; +// [self setContentSize:CGSizeMake(self.subviews.count * self.width, self.height)]; +//} @end @interface DoricNestedSliderNode () diff --git a/doric-iOS/Pod/Classes/Shader/DoricRootNode.h b/doric-iOS/Pod/Classes/Shader/DoricRootNode.h index 2380c4a0..6a210cd2 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricRootNode.h +++ b/doric-iOS/Pod/Classes/Shader/DoricRootNode.h @@ -22,12 +22,12 @@ #import "DoricStackNode.h" -@interface DoricRootView : DoricStackView +@interface DoricRootView : UIView @property(nonatomic, strong) void (^frameChangedBlock)(CGSize oldSize, CGSize newSize); @end @interface DoricRootNode : DoricStackNode -- (void)setupRootView:(DoricStackView *)view; +- (void)setupRootView:(UIView *)view; @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricRootNode.m b/doric-iOS/Pod/Classes/Shader/DoricRootNode.m index 01e644f2..17b434f9 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricRootNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricRootNode.m @@ -35,12 +35,12 @@ - (instancetype)init { return self; } -- (void)layoutSelf:(CGSize)targetSize { - [super layoutSelf:targetSize]; - if (!CGSizeEqualToSize(self.currentSize, targetSize) && self.frameChangedBlock) { - self.frameChangedBlock(self.currentSize, targetSize); +- (void)layoutSubviews { + [super layoutSubviews]; + if (!CGSizeEqualToSize(self.currentSize, self.frame.size) && self.frameChangedBlock) { + self.frameChangedBlock(self.currentSize, self.frame.size); } - self.currentSize = targetSize; + self.currentSize = self.frame.size; } - (void)setX:(CGFloat)x { @@ -54,11 +54,12 @@ - (void)setY:(CGFloat)y { @end @implementation DoricRootNode -- (void)setupRootView:(DoricStackView *)view { +- (void)setupRootView:(UIView *)view { + view.doricLayout.layoutType = DoricStack; self.view = view; } - (void)requestLayout { - [self.view setNeedsLayout]; + [self.view.doricLayout apply]; } @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricScrollerNode.m b/doric-iOS/Pod/Classes/Shader/DoricScrollerNode.m index 2bc6d14c..efb8533e 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricScrollerNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricScrollerNode.m @@ -27,25 +27,25 @@ @implementation DoricScrollView -- (void)setContentView:(UIView *)contentView { - if (_contentView) { - [_contentView removeFromSuperview]; - } - _contentView = contentView; - [self addSubview:contentView]; -} - -- (CGSize)sizeThatFits:(CGSize)size { - if (self.contentView) { - return [self.contentView measureSize:size]; - } - return CGSizeZero; -} - -- (void)layoutSelf:(CGSize)targetSize { - [super layoutSelf:targetSize]; - [self setContentSize:self.contentView.frame.size]; -} +//- (void)setContentView:(UIView *)contentView { +// if (_contentView) { +// [_contentView removeFromSuperview]; +// } +// _contentView = contentView; +// [self addSubview:contentView]; +//} +// +//- (CGSize)sizeThatFits:(CGSize)size { +// if (self.contentView) { +// return [self.contentView measureSize:size]; +// } +// return CGSizeZero; +//} +// +//- (void)layoutSelf:(CGSize)targetSize { +// [super layoutSelf:targetSize]; +// [self setContentSize:self.contentView.frame.size]; +//} @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricSlideItemNode.m b/doric-iOS/Pod/Classes/Shader/DoricSlideItemNode.m index 9e254323..706cb808 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricSlideItemNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricSlideItemNode.m @@ -21,7 +21,7 @@ // #import "DoricSlideItemNode.h" -@interface DoricSlideItemView : DoricStackView +@interface DoricSlideItemView : UIView @end @implementation DoricSlideItemView @@ -45,7 +45,7 @@ - (void)initWithSuperNode:(DoricSuperNode *)superNode { self.view.clipsToBounds = YES; } -- (DoricStackView *)build { +- (DoricSlideItemView *)build { return [DoricSlideItemView new]; } @end \ No newline at end of file diff --git a/doric-iOS/Pod/Classes/Shader/DoricSliderNode.m b/doric-iOS/Pod/Classes/Shader/DoricSliderNode.m index c0717d85..8c4f4deb 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricSliderNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricSliderNode.m @@ -44,24 +44,24 @@ @interface DoricSliderView : UICollectionView @end @implementation DoricSliderView -- (CGSize)sizeThatFits:(CGSize)size { - if (self.subviews.count > 0) { - CGFloat width = size.width; - CGFloat height = size.height; - for (UIView *child in self.subviews) { - CGSize childSize = [child measureSize:size]; - width = MAX(childSize.width, width); - height = MAX(childSize.height, height); - } - return CGSizeMake(width, height); - } - return size; -} - -- (void)layoutSelf:(CGSize)targetSize { - [super layoutSelf:targetSize]; - [self reloadData]; -} +//- (CGSize)sizeThatFits:(CGSize)size { +// if (self.subviews.count > 0) { +// CGFloat width = size.width; +// CGFloat height = size.height; +// for (UIView *child in self.subviews) { +// CGSize childSize = [child measureSize:size]; +// width = MAX(childSize.width, width); +// height = MAX(childSize.height, height); +// } +// return CGSizeMake(width, height); +// } +// return size; +//} +// +//- (void)layoutSelf:(CGSize)targetSize { +// [super layoutSelf:targetSize]; +// [self reloadData]; +//} @end @implementation DoricSliderNode @@ -143,8 +143,8 @@ - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collection DoricSlideItemNode *node = cell.doricSlideItemNode; node.viewId = model[@"id"]; [node blend:props]; - CGSize size = [node.view measureSize:CGSizeMake(collectionView.width, collectionView.height)]; - [node.view layoutSelf:size]; +// CGSize size = [node.view measureSize:CGSizeMake(collectionView.width, collectionView.height)]; +// [node.view layoutSelf:size]; return cell; } diff --git a/doric-iOS/Pod/Classes/Shader/DoricStackNode.h b/doric-iOS/Pod/Classes/Shader/DoricStackNode.h index 947d9c75..d8ab6d60 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricStackNode.h +++ b/doric-iOS/Pod/Classes/Shader/DoricStackNode.h @@ -22,5 +22,5 @@ #import "DoricGroupNode.h" -@interface DoricStackNode : DoricGroupNode +@interface DoricStackNode : DoricGroupNode @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricStackNode.m b/doric-iOS/Pod/Classes/Shader/DoricStackNode.m index 7b0ea338..087a1548 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricStackNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricStackNode.m @@ -21,14 +21,13 @@ // #import "DoricStackNode.h" +#import "DoricExtensions.h" @implementation DoricStackNode -- (DoricStackView *)build { - return [DoricStackView new]; -} - -- (void)blendView:(DoricStackView *)view forPropName:(NSString *)name propValue:(id)prop { - [super blendView:view forPropName:name propValue:prop]; +- (UIView *)build { + return [[UIView new] also:^(UIView *it) { + it.doricLayout.layoutType = DoricStack; + }]; } @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricSuperNode.h b/doric-iOS/Pod/Classes/Shader/DoricSuperNode.h index eef33d3b..94b65039 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricSuperNode.h +++ b/doric-iOS/Pod/Classes/Shader/DoricSuperNode.h @@ -23,8 +23,6 @@ @interface DoricSuperNode : DoricViewNode @property(nonatomic, assign) BOOL reusable; -- (DoricLayoutConfig *)generateDefaultLayoutParams; - - (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layoutConfig; - (void)blendSubNode:(NSDictionary *)subModel; diff --git a/doric-iOS/Pod/Classes/Shader/DoricSuperNode.m b/doric-iOS/Pod/Classes/Shader/DoricSuperNode.m index 596d207d..7fd62944 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricSuperNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricSuperNode.m @@ -92,37 +92,7 @@ - (void)recursiveMixin:(NSDictionary *)srcModel to:(NSMutableDictionary *)target } - (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layoutConfig { - DoricLayoutConfig *params = subNode.layoutConfig; - - [layoutConfig[@"widthSpec"] also:^(NSNumber *it) { - if (it) { - params.widthSpec = (DoricLayoutSpec) [it integerValue]; - } - }]; - - [layoutConfig[@"heightSpec"] also:^(NSNumber *it) { - if (it) { - params.heightSpec = (DoricLayoutSpec) [it integerValue]; - } - }]; - - NSDictionary *margin = layoutConfig[@"margin"]; - if (margin) { - params.margin = DoricMarginMake( - [(NSNumber *) margin[@"left"] floatValue], - [(NSNumber *) margin[@"top"] floatValue], - [(NSNumber *) margin[@"right"] floatValue], - [(NSNumber *) margin[@"bottom"] floatValue]); - } - - NSNumber *alignment = layoutConfig[@"alignment"]; - if (alignment) { - params.alignment = (DoricGravity) [alignment integerValue]; - } - NSNumber *weight = layoutConfig[@"weight"]; - if (weight) { - params.weight = (DoricGravity) [weight integerValue]; - } + [subNode blendLayoutConfig:layoutConfig]; } - (void)blendSubNode:(NSDictionary *)subModel { @@ -130,8 +100,8 @@ - (void)blendSubNode:(NSDictionary *)subModel { NSStringFromSelector(_cmd)); } -- (DoricLayoutConfig *)generateDefaultLayoutParams { - DoricLayoutConfig *params = [[DoricLayoutConfig alloc] init]; +- (DoricLayout *)generateDefaultLayoutParams { + DoricLayout *params = [[DoricLayout alloc] init]; return params; } diff --git a/doric-iOS/Pod/Classes/Shader/DoricTextNode.m b/doric-iOS/Pod/Classes/Shader/DoricTextNode.m index 2d46a9c2..49322146 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricTextNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricTextNode.m @@ -32,20 +32,13 @@ @interface DoricTextView : UILabel @implementation DoricTextView - (void)drawTextInRect:(CGRect)rect { - [super drawTextInRect:UIEdgeInsetsInsetRect(rect, self.padding)]; -} - -- (CGSize)measureSize:(CGSize)targetSize { - CGSize measuredSize = [super measureSize:targetSize]; - CGFloat measuredWidth = measuredSize.width; - CGFloat measuredHeight = measuredSize.height; - if (self.maxWidth >= 0) { - measuredWidth = MIN(self.maxWidth, measuredSize.width); - } - if (self.maxHeight >= 0) { - measuredHeight = MIN(self.maxHeight, measuredSize.height); - } - return CGSizeMake(measuredWidth, measuredHeight); + [super drawTextInRect:UIEdgeInsetsInsetRect( + rect, + UIEdgeInsetsMake( + self.doricLayout.paddingTop, + self.doricLayout.paddingLeft, + self.doricLayout.paddingBottom, + self.doricLayout.paddingRight))]; } @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricVLayoutNode.h b/doric-iOS/Pod/Classes/Shader/DoricVLayoutNode.h index 853f3f7b..3cdc4a0d 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricVLayoutNode.h +++ b/doric-iOS/Pod/Classes/Shader/DoricVLayoutNode.h @@ -22,5 +22,5 @@ #import "DoricGroupNode.h" -@interface DoricVLayoutNode : DoricGroupNode +@interface DoricVLayoutNode : DoricGroupNode @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricVLayoutNode.m b/doric-iOS/Pod/Classes/Shader/DoricVLayoutNode.m index d7b5d94d..93cc16af 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricVLayoutNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricVLayoutNode.m @@ -21,18 +21,21 @@ // #import "DoricVLayoutNode.h" +#import "DoricExtensions.h" @implementation DoricVLayoutNode -- (DoricVLayoutView *)build { - return [DoricVLayoutView new]; +- (UIView *)build { + return [[UIView new] also:^(UIView *it) { + it.doricLayout.layoutType = DoricVLayout; + }]; } -- (void)blendView:(DoricVLayoutView *)view forPropName:(NSString *)name propValue:(id)prop { +- (void)blendView:(UIView *)view forPropName:(NSString *)name propValue:(id)prop { if ([name isEqualToString:@"gravity"]) { - view.gravity = (DoricGravity) [(NSNumber *) prop integerValue]; + view.doricLayout.gravity = (DoricGravity) [(NSNumber *) prop integerValue]; } else if ([name isEqualToString:@"space"]) { - view.space = [(NSNumber *) prop floatValue]; + view.doricLayout.spacing = [(NSNumber *) prop floatValue]; } else { [super blendView:view forPropName:name propValue:prop]; } diff --git a/doric-iOS/Pod/Classes/Shader/DoricViewNode.h b/doric-iOS/Pod/Classes/Shader/DoricViewNode.h index faad1da5..5967425c 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricViewNode.h +++ b/doric-iOS/Pod/Classes/Shader/DoricViewNode.h @@ -36,8 +36,6 @@ @property(nonatomic, copy) NSString *type; -@property(nonatomic, readonly) DoricLayoutConfig *layoutConfig; - @property(nonatomic, readonly) NSArray *idList; - (void)initWithSuperNode:(DoricSuperNode *)superNode; @@ -53,4 +51,8 @@ + (__kindof DoricViewNode *)create:(DoricContext *)context withType:(NSString *)type; - (void)requestLayout; + +- (void)blendLayoutConfig:(NSDictionary *)params; + +- (void)afterBlended:(NSDictionary *)props; @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricViewNode.m b/doric-iOS/Pod/Classes/Shader/DoricViewNode.m index 90b41dcd..6f510446 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricViewNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricViewNode.m @@ -20,6 +20,7 @@ // Created by pengfei.zhou on 2019/7/30. // +#import #import "DoricViewNode.h" #import "DoricUtil.h" #import "DoricGroupNode.h" @@ -121,13 +122,7 @@ - (void)initWithSuperNode:(DoricSuperNode *)superNode { ((DoricSuperNode *) self).reusable = superNode.reusable; } self.superNode = superNode; - self.view = [[self build] also:^(UIView *it) { - it.layoutConfig = [superNode generateDefaultLayoutParams]; - }]; -} - -- (DoricLayoutConfig *)layoutConfig { - return self.view.layoutConfig; + self.view = [self build]; } - (UIView *)build { @@ -135,7 +130,6 @@ - (UIView *)build { } - (void)blend:(NSDictionary *)props { - self.view.layoutConfig = self.layoutConfig; for (NSString *key in props) { id value = props[key]; if (!value || [value isKindOfClass:[NSNull class]]) { @@ -144,9 +138,14 @@ - (void)blend:(NSDictionary *)props { [self blendView:self.view forPropName:key propValue:value]; } [self transformProperties]; + [self afterBlended:props]; + [self requestLayout]; self.gradientLayer.frame = CGRectMake(0, 0, self.view.width, self.view.height); } +- (void)afterBlended:(NSDictionary *)props { +} + - (void)transformProperties { CGAffineTransform transform = CGAffineTransformIdentity; if (self.translationX || self.translationY) { @@ -171,19 +170,13 @@ - (void)transformProperties { - (void)blendView:(UIView *)view forPropName:(NSString *)name propValue:(id)prop { if ([name isEqualToString:@"width"]) { - NSNumber *width = (NSNumber *) prop; - if ([width floatValue] >= 0) { - view.width = [width floatValue]; - } + view.doricLayout.width = [prop floatValue]; } else if ([name isEqualToString:@"height"]) { - NSNumber *height = (NSNumber *) prop; - if ([height floatValue] >= 0) { - view.height = [height floatValue]; - } + view.doricLayout.height = [prop floatValue]; } else if ([name isEqualToString:@"x"]) { - view.x = [prop floatValue]; + view.doricLayout.x = [prop floatValue]; } else if ([name isEqualToString:@"y"]) { - view.y = [prop floatValue]; + view.doricLayout.y = [prop floatValue]; } else if ([name isEqualToString:@"backgroundColor"]) { if ([prop isKindOfClass:[NSNumber class]]) { view.backgroundColor = DoricColor(prop); @@ -298,19 +291,20 @@ - (void)blendView:(UIView *)view forPropName:(NSString *)name propValue:(id)prop } else if ([name isEqualToString:@"rotation"]) { self.rotation = prop; } else if ([name isEqualToString:@"padding"]) { - DoricPadding padding; - padding.left = padding.right = padding.top = padding.bottom = 0; + view.doricLayout.paddingLeft = 0; + view.doricLayout.paddingRight = 0; + view.doricLayout.paddingTop = 0; + view.doricLayout.paddingBottom = 0; if ([prop isKindOfClass:[NSDictionary class]]) { NSDictionary *dictionary = prop; - padding.left = [dictionary[@"left"] floatValue]; - padding.right = [dictionary[@"right"] floatValue]; - padding.top = [dictionary[@"top"] floatValue]; - padding.bottom = [dictionary[@"bottom"] floatValue]; + view.doricLayout.paddingLeft = [dictionary[@"left"] floatValue]; + view.doricLayout.paddingRight = [dictionary[@"right"] floatValue]; + view.doricLayout.paddingTop = [dictionary[@"top"] floatValue]; + view.doricLayout.paddingBottom = [dictionary[@"bottom"] floatValue]; } - self.view.padding = padding; } else if ([name isEqualToString:@"hidden"]) { self.view.hidden = [prop boolValue]; - [self.view.superview setNeedsLayout]; + self.view.doricLayout.disabled = [prop boolValue]; } else { DoricLog(@"Blend View error for View Type :%@, prop is %@", self.class, name); } @@ -380,38 +374,26 @@ - (NSDictionary *)getLocationOnScreen { } - (void)blendLayoutConfig:(NSDictionary *)params { - if (!self.layoutConfig) { - self.view.layoutConfig = [DoricLayoutConfig new]; - } + [params[@"widthSpec"] also:^(NSNumber *it) { - if (it) { - self.layoutConfig.widthSpec = (DoricLayoutSpec) [it integerValue]; - } + self.view.doricLayout.widthSpec = (DoricLayoutSpec) [it integerValue]; }]; [params[@"heightSpec"] also:^(NSNumber *it) { - if (it) { - self.layoutConfig.heightSpec = (DoricLayoutSpec) [it integerValue]; - } + self.view.doricLayout.heightSpec = (DoricLayoutSpec) [it integerValue]; + }]; + [params[@"margin"] also:^(NSDictionary *it) { + self.view.doricLayout.marginLeft = [it[@"left"] floatValue]; + self.view.doricLayout.marginTop = [it[@"top"] floatValue]; + self.view.doricLayout.marginRight = [it[@"right"] floatValue]; + self.view.doricLayout.marginBottom = [it[@"bottom"] floatValue]; + }]; + [params[@"alignment"] also:^(NSNumber *it) { + self.view.doricLayout.alignment = (DoricGravity) [it integerValue]; + }]; + [params[@"weight"] also:^(NSNumber *it) { + self.view.doricLayout.weight = (DoricGravity) [it integerValue]; }]; - - NSDictionary *margin = params[@"margin"]; - if (margin) { - self.layoutConfig.margin = DoricMarginMake( - [(NSNumber *) margin[@"left"] floatValue], - [(NSNumber *) margin[@"top"] floatValue], - [(NSNumber *) margin[@"right"] floatValue], - [(NSNumber *) margin[@"bottom"] floatValue]); - } - - NSNumber *alignment = params[@"alignment"]; - if (alignment) { - self.layoutConfig.alignment = (DoricGravity) [alignment integerValue]; - } - NSNumber *weight = params[@"weight"]; - if (weight) { - self.layoutConfig.weight = (DoricGravity) [weight integerValue]; - } } - (NSDictionary *)transformation { diff --git a/doric-iOS/Pod/Classes/Shader/UIView+Doric.h b/doric-iOS/Pod/Classes/Shader/UIView+Doric.h index 06502cbb..f48fa6da 100644 --- a/doric-iOS/Pod/Classes/Shader/UIView+Doric.h +++ b/doric-iOS/Pod/Classes/Shader/UIView+Doric.h @@ -37,6 +37,9 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic) CGFloat left; @property(nonatomic) CGFloat right; @property(nonatomic) CGFloat bottom; +@property(nonatomic, copy) NSString *tagString; + +- (UIView *)viewWithTagString:(NSString *)tagString; @end NS_ASSUME_NONNULL_END diff --git a/doric-iOS/Pod/Classes/Shader/UIView+Doric.m b/doric-iOS/Pod/Classes/Shader/UIView+Doric.m index a81d7021..f6894880 100644 --- a/doric-iOS/Pod/Classes/Shader/UIView+Doric.m +++ b/doric-iOS/Pod/Classes/Shader/UIView+Doric.m @@ -22,8 +22,25 @@ // #import "UIView+Doric.h" +#import + +static const void *kTagString = &kTagString; @implementation UIView (Doric) +- (void)setTagString:(NSString *)tagString { + objc_setAssociatedObject(self, kTagString, tagString, OBJC_ASSOCIATION_COPY_NONATOMIC); + self.tag = [tagString hash]; +} + +- (NSString *)tagString { + return objc_getAssociatedObject(self, kTagString); +} + + +- (UIView *)viewWithTagString:(NSString *)tagString { + // notice the potential hash collision + return [self viewWithTag:[tagString hash]]; +} - (CGFloat)x { return self.frame.origin.x; diff --git a/doric-iOS/Pod/Classes/Util/DoricUtil.m b/doric-iOS/Pod/Classes/Util/DoricUtil.m index e59a2b44..6769e197 100644 --- a/doric-iOS/Pod/Classes/Util/DoricUtil.m +++ b/doric-iOS/Pod/Classes/Util/DoricUtil.m @@ -73,7 +73,7 @@ void ShowToast(NSString *text, DoricGravity gravity) { label.centerX = superView.width / 2; if ((gravity & DoricGravityBottom) == DoricGravityBottom) { label.bottom = superView.height - 20; - } else if ((gravity & DoricGravityTOP) == DoricGravityTOP) { + } else if ((gravity & DoricGravityTop) == DoricGravityTop) { label.top = 108; } else { label.centerY = (superView.height - 88) / 2;