iOS refact DoricLayout

This commit is contained in:
pengfei.zhou 2020-04-03 16:36:43 +08:00 committed by osborn
parent ca6a3284f2
commit abbe0ba377
32 changed files with 540 additions and 761 deletions

View File

@ -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 <NSString *, DoricViewNode *> *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 <NSString *, DoricViewNode *> *map = self.doricContext.headNodes[TYPE_RIGHT];

View File

@ -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 <NSString *, DoricViewNode *> *map = self.doricContext.headNodes[TYPE];

View File

@ -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) {

View File

@ -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 {

View File

@ -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

View File

@ -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 () <UICollectionViewDataSource, UICollectionViewDelegate, DoricFlowLayoutDelegate>
@ -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;
}

View File

@ -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++) {

View File

@ -22,5 +22,5 @@
#import "DoricGroupNode.h"
@interface DoricHLayoutNode : DoricGroupNode<DoricHLayoutView *>
@interface DoricHLayoutNode : DoricGroupNode<UIView *>
@end

View File

@ -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];
}

View File

@ -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

View File

@ -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;
@interface UIView (DoricLayout)
@property(nonatomic, strong) DoricLayout *doricLayout;
@end

View File

@ -20,138 +20,45 @@
#import "DoricLayouts.h"
#import <objc/runtime.h>
#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];
[layout measure:targetSize];
contentWidth = MAX(contentWidth, layout.takenWidth);
contentHeight = MAX(contentHeight, layout.takenHeight);
}
CGSize childSize;
if (CGAffineTransformEqualToTransform(child.transform, CGAffineTransformIdentity)) {
childSize = [child measureSize:CGSizeMake(size.width, size.height)];
} else {
childSize = child.bounds.size;
if (self.widthSpec == DoricLayoutFit) {
self.measuredWidth = contentWidth + self.paddingLeft + self.paddingRight;
}
contentWidth = MAX(contentWidth, childSize.width + childConfig.margin.left + childConfig.margin.right);
contentHeight = MAX(contentHeight, childSize.height + childConfig.margin.top + childConfig.margin.bottom);
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];
had = YES;
[layout measure:CGSizeMake(targetSize.width - contentWidth, targetSize.height)];
contentWidth += layout.takenWidth + self.spacing;
contentHeight = MAX(contentHeight, layout.takenHeight);
}
CGSize size = [child measureSize:CGSizeMake(
targetSize.width - padding.left - padding.right,
targetSize.height - padding.top - padding.bottom)];
[child layoutSelf:size];
DoricGravity gravity = childConfig.alignment;
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

View File

@ -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

View File

@ -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;
}

View File

@ -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 () <UIScrollViewDelegate>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -22,5 +22,5 @@
#import "DoricGroupNode.h"
@interface DoricStackNode : DoricGroupNode<DoricStackView *>
@interface DoricStackNode : DoricGroupNode<UIView *>
@end

View File

@ -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

View File

@ -23,8 +23,6 @@
@interface DoricSuperNode<V:UIView *> : DoricViewNode<V>
@property(nonatomic, assign) BOOL reusable;
- (DoricLayoutConfig *)generateDefaultLayoutParams;
- (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layoutConfig;
- (void)blendSubNode:(NSDictionary *)subModel;

View File

@ -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;
}

View File

@ -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

View File

@ -22,5 +22,5 @@
#import "DoricGroupNode.h"
@interface DoricVLayoutNode : DoricGroupNode<DoricVLayoutView *>
@interface DoricVLayoutNode : DoricGroupNode<UIView *>
@end

View File

@ -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];
}

View File

@ -36,8 +36,6 @@
@property(nonatomic, copy) NSString *type;
@property(nonatomic, readonly) DoricLayoutConfig *layoutConfig;
@property(nonatomic, readonly) NSArray<NSString *> *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

View File

@ -20,6 +20,7 @@
// Created by pengfei.zhou on 2019/7/30.
//
#import <DoricCore/DoricExtensions.h>
#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 {

View File

@ -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

View File

@ -22,8 +22,25 @@
//
#import "UIView+Doric.h"
#import <objc/runtime.h>
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;

View File

@ -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;