feat:refact DoricLayout and layout config

This commit is contained in:
pengfei.zhou 2019-11-15 15:38:24 +08:00
parent 3289513720
commit 6017e7120d
16 changed files with 355 additions and 405 deletions

View File

@ -85,10 +85,9 @@ public abstract class SuperNode<V extends View> extends ViewNode<V> {
protected abstract void blendSubNode(JSObject subProperties);
protected void blendSubLayoutConfig(ViewNode viewNode, JSObject jsObject) {
JSValue jsValue = jsObject.getProperty("margin");
JSValue margin = jsObject.getProperty("margin");
JSValue widthSpec = jsObject.getProperty("widthSpec");
JSValue heightSpec = jsObject.getProperty("heightSpec");
ViewGroup.LayoutParams layoutParams = viewNode.getLayoutParams();
if (widthSpec.isNumber()) {
switch (widthSpec.asNumber().toInt()) {
@ -114,20 +113,20 @@ public abstract class SuperNode<V extends View> extends ViewNode<V> {
break;
}
}
if (jsValue.isObject() && layoutParams instanceof ViewGroup.MarginLayoutParams) {
JSValue topVal = jsValue.asObject().getProperty("top");
if (margin.isObject() && layoutParams instanceof ViewGroup.MarginLayoutParams) {
JSValue topVal = margin.asObject().getProperty("top");
if (topVal.isNumber()) {
((ViewGroup.MarginLayoutParams) layoutParams).topMargin = DoricUtils.dp2px(topVal.asNumber().toFloat());
}
JSValue leftVal = jsValue.asObject().getProperty("left");
JSValue leftVal = margin.asObject().getProperty("left");
if (leftVal.isNumber()) {
((ViewGroup.MarginLayoutParams) layoutParams).leftMargin = DoricUtils.dp2px(leftVal.asNumber().toFloat());
}
JSValue rightVal = jsValue.asObject().getProperty("right");
JSValue rightVal = margin.asObject().getProperty("right");
if (rightVal.isNumber()) {
((ViewGroup.MarginLayoutParams) layoutParams).rightMargin = DoricUtils.dp2px(rightVal.asNumber().toFloat());
}
JSValue bottomVal = jsValue.asObject().getProperty("bottom");
JSValue bottomVal = margin.asObject().getProperty("bottom");
if (bottomVal.isNumber()) {
((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin = DoricUtils.dp2px(bottomVal.asNumber().toFloat());
}

View File

@ -30,7 +30,7 @@ - (void)viewDidLoad {
NSString *jsContent = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
self.doricContext = [[DoricContext alloc] initWithScript:jsContent source:@"test.js"];
[self.doricContext.rootNode setupRootView:[[DoricStackView new] also:^(DoricStackView *it) {
it.layoutConfig = [[DoricStackConfig alloc] initWithWidth:DoricLayoutAtMost height:DoricLayoutAtMost];
it.layoutConfig = [[DoricLayoutConfig alloc] initWithWidth:DoricLayoutAtMost height:DoricLayoutAtMost];
[self.view addSubview:it];
}]];
[self.doricContext initContextWithWidth:self.view.width height:self.view.height];

View File

@ -24,7 +24,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface DoricGroupNode <V:UIView *, P:DoricLayoutConfig *> : DoricSuperNode<V, P>
@interface DoricGroupNode <V:UIView *> : DoricSuperNode<V>
@end
NS_ASSUME_NONNULL_END

View File

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

View File

@ -37,29 +37,4 @@ - (void)blendView:(DoricHLayoutView *)view forPropName:(NSString *)name propValu
[super blendView:view forPropName:name propValue:prop];
}
}
- (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layoutConfig {
[super blendSubNode:subNode layoutConfig:layoutConfig];
if (![subNode.layoutConfig isKindOfClass:DoricLinearConfig.class]) {
DoricLog(@"blend DoricHLayoutView child error,layout params not match");
return;
}
DoricLinearConfig *params = (DoricLinearConfig *) subNode.layoutConfig;
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];
}
}
- (DoricLinearConfig *)generateDefaultLayoutParams {
return [[DoricLinearConfig alloc] init];
}
@end

View File

@ -54,43 +54,27 @@ typedef NS_ENUM(NSInteger, DoricGravity) {
@interface DoricLayoutConfig : NSObject
@property(nonatomic, assign) DoricLayoutSpec widthSpec;
@property(nonatomic, assign) DoricLayoutSpec heightSpec;
@property(nonatomic) DoricMargin margin;
@property(nonatomic, assign) DoricGravity alignment;
@property(nonatomic, assign) NSUInteger weight;
- (instancetype)init;
- (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)height;
@end
@interface DoricStackConfig : DoricLayoutConfig
@end
@interface DoricMarginConfig : DoricLayoutConfig
@property(nonatomic) DoricMargin margin;
- (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)height margin:(DoricMargin)margin;
@end
@interface DoricLinearConfig : DoricMarginConfig
@property(nonatomic, assign) NSUInteger weight;
@end
@interface DoricLayoutContainer <T :DoricLayoutConfig *> : UIView
- (T)configForChild:(__kindof UIView *)child;
- (void)layout;
- (void)requestLayout;
@end
@interface DoricStackView : DoricLayoutContainer<DoricStackConfig *>
@interface DoricLayoutContainer : UIView
@property(nonatomic, assign) DoricGravity gravity;
@end
@interface DoricLinearView : DoricLayoutContainer<DoricLinearConfig *>
@property(nonatomic, assign) DoricGravity gravity;
@interface DoricStackView : DoricLayoutContainer
@end
@interface DoricLinearView : DoricLayoutContainer
@property(nonatomic, assign) CGFloat space;
@end

View File

@ -46,107 +46,74 @@ - (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)hei
}
return self;
}
@end
@implementation DoricMarginConfig
- (instancetype)init {
if (self = [super init]) {
_margin = DoricMarginMake(0, 0, 0, 0);
}
return self;
}
- (instancetype)initWithWidth:(DoricLayoutSpec)width height:(DoricLayoutSpec)height margin:(DoricMargin)margin {
if (self = [super initWithWidth:width height:height]) {
if (self = [super init]) {
_widthSpec = width;
_heightSpec = height;
_margin = margin;
}
return self;
}
@end
@implementation DoricStackConfig
@end
@implementation DoricLinearConfig
@end
@interface DoricLayoutContainer ()
@property(nonatomic, assign) BOOL waitingLayout;
@property(nonatomic, assign) CGFloat contentWidth;
@property(nonatomic, assign) CGFloat contentHeight;
@property(nonatomic, assign) NSUInteger contentWeight;
- (void)layout:(CGSize)targetSize;
- (CGSize)sizeContent:(CGSize)size;
@end
@implementation DoricLayoutContainer
- (instancetype)init {
if (self = [super init]) {
_waitingLayout = NO;
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
_waitingLayout = NO;
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
_waitingLayout = NO;
}
return self;
}
- (DoricLayoutConfig *)configForChild:(UIView *)child {
DoricLayoutConfig *config = child.layoutConfig;
if (!config) {
config = [[DoricLayoutConfig alloc] init];
}
return config;
}
- (void)requestLayout {
if ([self.superview isKindOfClass:[DoricLinearView class]]) {
[(DoricLinearView *) self.superview requestLayout];
return;
}
if (self.waitingLayout) {
return;
}
self.waitingLayout = YES;
__weak typeof(self) _self = self;
dispatch_async(dispatch_get_main_queue(), ^{
__strong typeof(_self) self = _self;
[self sizeToFit];
[self layout];
self.waitingLayout = NO;
});
}
- (void)setNeedsLayout {
[super setNeedsLayout];
if (self.waitingLayout) {
return;
}
[self requestLayout];
}
- (BOOL)waitingLayout {
- (void)layoutSubviews {
if ([self.superview isKindOfClass:[DoricLayoutContainer class]]) {
return [(DoricLayoutContainer *) self.superview waitingLayout];
[self.superview layoutSubviews];
} else {
CGSize size = [self sizeThatFits:CGSizeMake(self.superview.width, self.superview.height)];
[self layout:size];
}
return _waitingLayout;
}
- (void)layout {
[self.subviews enumerateObjectsUsingBlock:^(__kindof UIView *child, NSUInteger idx, BOOL *stop) {
if ([child isKindOfClass:[DoricLayoutContainer class]]) {
[(DoricLayoutContainer *) child layout];
- (CGSize)sizeThatFits:(CGSize)size {
CGFloat width = self.width;
CGFloat height = self.height;
DoricLayoutConfig *config = self.layoutConfig;
if (!config) {
config = [DoricLayoutConfig new];
}
}];
if (config.widthSpec == DoricLayoutAtMost
|| config.widthSpec == DoricLayoutWrapContent) {
width = size.width - config.margin.left - config.margin.right;
}
if (config.heightSpec == DoricLayoutAtMost
|| config.heightSpec == DoricLayoutWrapContent) {
height = size.height - config.margin.top - config.margin.bottom;
}
CGSize contentSize = [self sizeContent:CGSizeMake(width, height)];
if (config.widthSpec == DoricLayoutWrapContent) {
width = contentSize.width;
}
if (config.heightSpec == DoricLayoutWrapContent) {
height = contentSize.height;
}
return CGSizeMake(width, height);
}
- (CGSize)sizeContent:(CGSize)size {
return size;
}
- (void)layout:(CGSize)targetSize {
self.width = targetSize.width;
self.height = targetSize.height;
}
@end
@ -157,175 +124,223 @@ @interface DoricStackView ()
@end
@implementation DoricStackView
- (DoricStackConfig *)configForChild:(UIView *)child {
DoricStackConfig *config = (DoricStackConfig *) child.layoutConfig;
if (!config) {
config = [[DoricStackConfig alloc] init];
}
return config;
}
- (void)sizeToFit {
DoricLayoutConfig *config = self.layoutConfig;
self.contentWidth = 0;
self.contentHeight = 0;
- (CGSize)sizeContent:(CGSize)size {
CGFloat contentWidth = 0;
CGFloat contentHeight = 0;
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
}
DoricStackConfig *childConfig = [self configForChild:child];
DoricLayoutConfig *childConfig = child.layoutConfig;
if (!childConfig) {
childConfig = [DoricLayoutConfig new];
}
CGSize childSize = CGSizeMake(child.width, child.height);
if ([child isKindOfClass:[DoricLayoutContainer class]]
|| childConfig.widthSpec == DoricLayoutWrapContent
|| childConfig.heightSpec == DoricLayoutWrapContent) {
[child sizeToFit];
childSize = [child sizeThatFits:CGSizeMake(size.width, size.height - contentHeight)];
}
self.contentWidth = MAX(self.contentWidth, child.width);
self.contentHeight = MAX(self.contentHeight, child.height);
if (childConfig.widthSpec == DoricLayoutExact) {
childSize.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
childSize.width = size.width;
}
if (config.widthSpec == DoricLayoutWrapContent) {
self.width = self.contentWidth;
} else if (config.widthSpec == DoricLayoutAtMost) {
self.width = self.superview.width;
if (childConfig.heightSpec == DoricLayoutExact) {
childSize.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
childSize.height = size.height - contentHeight;
}
if (config.heightSpec == DoricLayoutWrapContent) {
self.height = self.contentHeight;
} else if (config.heightSpec == DoricLayoutAtMost) {
self.height = self.superview.height;
}
}
- (void)layout {
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
}
DoricStackConfig *childConfig = [self configForChild:child];
DoricGravity gravity = childConfig.alignment | self.gravity;
if ((gravity & LEFT) == LEFT) {
child.left = 0;
} else if ((gravity & RIGHT) == RIGHT) {
child.right = self.width;
} else if ((gravity & CENTER_X) == CENTER_X) {
child.centerX = self.width / 2;
}
if ((gravity & TOP) == TOP) {
child.top = 0;
} else if ((gravity & BOTTOM) == BOTTOM) {
child.bottom = self.height;
} else if ((gravity & CENTER_Y) == CENTER_Y) {
child.centerY = self.height / 2;
}
if (childConfig.widthSpec == DoricLayoutAtMost) {
child.width = self.width;
}
if (childConfig.heightSpec == DoricLayoutAtMost) {
child.height = self.height;
}
if ([child isKindOfClass:[DoricLayoutContainer class]]) {
[(DoricLayoutContainer *) child layout];
}
}
}
@end
@interface DoricLinearView ()
@property(nonatomic, assign) CGFloat contentWidth;
@property(nonatomic, assign) CGFloat contentHeight;
@property(nonatomic, assign) NSUInteger contentWeight;
@end
@implementation DoricLinearView
- (DoricLinearConfig *)configForChild:(UIView *)child {
DoricLinearConfig *config = (DoricLinearConfig *) child.layoutConfig;
if (!config) {
config = [[DoricLinearConfig alloc] init];
}
return config;
}
@end
@implementation DoricVLayoutView
- (void)sizeToFit {
DoricLayoutConfig *config = self.layoutConfig;
self.contentWidth = 0;
self.contentHeight = 0;
self.contentWeight = 0;
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
}
DoricLinearConfig *childConfig = [self configForChild:child];
if ([child isKindOfClass:[DoricLayoutContainer class]]
|| childConfig.widthSpec == DoricLayoutWrapContent
|| childConfig.heightSpec == DoricLayoutWrapContent) {
[child sizeToFit];
}
self.contentWidth = MAX(self.contentWidth, child.width + childConfig.margin.left + childConfig.margin.right);
self.contentHeight += child.height + self.space + childConfig.margin.top + childConfig.margin.bottom;
self.contentWeight += childConfig.weight;
}
self.contentHeight -= self.space;
if (config.widthSpec == DoricLayoutWrapContent) {
self.width = self.contentWidth;
} else if (config.widthSpec == DoricLayoutAtMost) {
self.width = self.superview.width;
}
if (config.heightSpec == DoricLayoutWrapContent) {
self.height = self.contentHeight;
} else if (config.heightSpec == DoricLayoutAtMost) {
self.height = self.superview.height;
}
if (self.contentWeight) {
CGFloat remain = self.height - self.contentHeight;
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
}
DoricLinearConfig *childConfig = [self configForChild:child];
if (childConfig.weight) {
child.height += remain / self.contentWeight * childConfig.weight;
childSize.height = child.height;
}
contentWidth = MAX(contentWidth, childSize.width + childConfig.margin.left + childConfig.margin.right);
contentHeight = MAX(contentHeight, childSize.height + childConfig.margin.top + childConfig.margin.bottom);
}
self.contentHeight = self.height;
}
self.contentWidth = contentWidth;
self.contentHeight = contentHeight;
return CGSizeMake(contentWidth, contentHeight);
}
- (void)layout {
CGFloat yStart = 0;
if ((self.gravity & TOP) == TOP) {
yStart = 0;
} else if ((self.gravity & BOTTOM) == BOTTOM) {
yStart = self.height - self.contentHeight;
} else if ((self.gravity & CENTER_Y) == CENTER_Y) {
yStart = (self.height - self.contentHeight) / 2;
}
- (void)layout:(CGSize)targetSize {
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
}
DoricLinearConfig *childConfig = [self configForChild:child];
DoricLayoutConfig *childConfig = child.layoutConfig;
if (!childConfig) {
childConfig = [DoricLayoutConfig new];
}
CGSize size = [child sizeThatFits:CGSizeMake(targetSize.width, targetSize.height)];
if (childConfig.widthSpec == DoricLayoutExact) {
size.width = child.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
}
if (childConfig.widthSpec == DoricLayoutExact) {
size.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
size.width = targetSize.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
size.height = targetSize.height;
}
child.width = size.width;
child.height = size.height;
DoricGravity gravity = childConfig.alignment | self.gravity;
if ((gravity & LEFT) == LEFT) {
child.left = 0;
} else if ((gravity & RIGHT) == RIGHT) {
child.right = self.width;
child.right = targetSize.width;
} else if ((gravity & CENTER_X) == CENTER_X) {
child.centerX = self.width / 2;
child.centerX = targetSize.width / 2;
} else {
if (childConfig.margin.left) {
child.left = childConfig.margin.left;
} else if (childConfig.margin.right) {
child.right = self.width - childConfig.margin.right;
child.right = targetSize.width - childConfig.margin.right;
}
}
if (childConfig.widthSpec == DoricLayoutAtMost) {
child.width = self.width;
if ((gravity & TOP) == TOP) {
child.top = 0;
} else if ((gravity & BOTTOM) == BOTTOM) {
child.bottom = targetSize.height;
} else if ((gravity & CENTER_Y) == CENTER_Y) {
child.centerY = targetSize.height / 2;
} else {
if (childConfig.margin.top) {
child.top = childConfig.margin.top;
} else if (childConfig.margin.bottom) {
child.bottom = targetSize.height - childConfig.margin.bottom;
}
}
if ([child isKindOfClass:[DoricLayoutContainer class]]) {
[(DoricLayoutContainer *) child layout:size];
}
}
self.width = targetSize.width;
self.height = targetSize.height;
}
@end
@implementation DoricLinearView
@end
@implementation DoricVLayoutView
- (CGSize)sizeContent:(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 = CGSizeMake(child.width, child.height);
if ([child isKindOfClass:[DoricLayoutContainer class]]
|| childConfig.widthSpec == DoricLayoutWrapContent
|| childConfig.heightSpec == DoricLayoutWrapContent) {
childSize = [child sizeThatFits:CGSizeMake(size.width, size.height - contentHeight)];
}
if (childConfig.widthSpec == DoricLayoutExact) {
childSize.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
childSize.width = size.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
childSize.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
childSize.height = size.height - contentHeight;
}
if (childConfig.weight) {
childSize.height = child.height;
}
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)layout:(CGSize)targetSize {
CGFloat yStart = 0;
if ((self.gravity & TOP) == TOP) {
yStart = 0;
} else if ((self.gravity & BOTTOM) == BOTTOM) {
yStart = targetSize.height - self.contentHeight;
} else if ((self.gravity & CENTER_Y) == CENTER_Y) {
yStart = (targetSize.height - self.contentHeight) / 2;
}
CGFloat remain = targetSize.height - self.contentHeight;
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
}
DoricLayoutConfig *childConfig = child.layoutConfig;
if (!childConfig) {
childConfig = [DoricLayoutConfig new];
}
CGSize size = [child sizeThatFits:CGSizeMake(targetSize.width, targetSize.height - yStart)];
if (childConfig.widthSpec == DoricLayoutExact) {
size.width = child.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
}
if (childConfig.widthSpec == DoricLayoutExact) {
size.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
size.width = targetSize.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
size.height = targetSize.height - yStart;
}
if (childConfig.weight) {
size.height = child.height;
}
if (childConfig.weight) {
size.height += remain / self.contentWeight * childConfig.weight;
}
child.width = size.width;
child.height = size.height;
DoricGravity gravity = childConfig.alignment | self.gravity;
if ((gravity & LEFT) == LEFT) {
child.left = 0;
} else if ((gravity & RIGHT) == RIGHT) {
child.right = self.width;
} else if ((gravity & CENTER_X) == CENTER_X) {
child.centerX = targetSize.width / 2;
} else {
if (childConfig.margin.left) {
child.left = childConfig.margin.left;
} else if (childConfig.margin.right) {
child.right = targetSize.width - childConfig.margin.right;
}
if (childConfig.heightSpec == DoricLayoutAtMost) {
child.height = self.height - yStart - childConfig.margin.top - childConfig.margin.bottom - self.space;
}
if (childConfig.margin.top) {
yStart += childConfig.margin.top;
@ -336,102 +351,124 @@ - (void)layout {
yStart += childConfig.margin.bottom;
}
if ([child isKindOfClass:[DoricLayoutContainer class]]) {
[(DoricLayoutContainer *) child layout];
[(DoricLayoutContainer *) child layout:size];
}
}
self.width = targetSize.width;
self.height = targetSize.height;
}
@end
@implementation DoricHLayoutView
- (void)sizeToFit {
DoricLinearConfig *config;
if ([self.superview isKindOfClass:[DoricLinearView class]]) {
config = [(DoricLinearView *) self.superview configForChild:self];
} else {
config = (DoricLinearConfig *) self.layoutConfig;
if (!config) {
config = [[DoricLinearConfig alloc] init];
}
}
self.contentWidth = 0;
self.contentHeight = 0;
self.contentWeight = 0;
- (CGSize)sizeContent:(CGSize)size {
CGFloat contentWidth = 0;
CGFloat contentHeight = 0;
NSUInteger contentWeight = 0;
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
}
DoricLinearConfig *childConfig = [self configForChild:child];
DoricLayoutConfig *childConfig = child.layoutConfig;
if (!childConfig) {
childConfig = [DoricLayoutConfig new];
}
CGSize childSize = CGSizeMake(child.width, child.height);
if ([child isKindOfClass:[DoricLayoutContainer class]]
|| childConfig.widthSpec == DoricLayoutWrapContent
|| childConfig.heightSpec == DoricLayoutWrapContent) {
[child sizeToFit];
childSize = [child sizeThatFits:CGSizeMake(size.width - contentWidth, size.height)];
}
self.contentHeight = MAX(self.contentHeight, child.height + childConfig.margin.top + childConfig.margin.bottom);
self.contentWidth += child.width + self.space + childConfig.margin.left + childConfig.margin.right;
self.contentWeight += childConfig.weight;
if (childConfig.widthSpec == DoricLayoutExact) {
childSize.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
childSize.width = size.width - contentWidth;
}
self.contentWidth -= self.space;
if (config.widthSpec == DoricLayoutWrapContent) {
self.width = self.contentWidth;
} else if (config.widthSpec == DoricLayoutAtMost) {
self.width = self.superview.width;
if (childConfig.heightSpec == DoricLayoutExact) {
childSize.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
childSize.height = size.height;
}
if (config.heightSpec == DoricLayoutWrapContent) {
self.height = self.contentHeight;
} else if (config.heightSpec == DoricLayoutAtMost) {
self.height = self.superview.height;
}
if (self.contentWeight) {
CGFloat remain = self.width - self.contentWidth;
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
}
DoricLinearConfig *childConfig = [self configForChild:child];
if (childConfig.weight) {
child.width += remain / self.contentWeight * childConfig.weight;
childSize.width = child.width;
}
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;
}
self.contentWidth = self.width;
contentWidth -= self.space;
self.contentWidth = contentWidth;
self.contentHeight = contentHeight;
self.contentWeight = contentWeight;
if (contentWeight) {
contentWidth = size.width;
}
return CGSizeMake(contentWidth, contentHeight);
}
- (void)layout {
- (void)layout:(CGSize)targetSize {
CGFloat xStart = 0;
if ((self.gravity & LEFT) == LEFT) {
if (self.contentWeight) {
xStart = 0;
} else if ((self.gravity & LEFT) == LEFT) {
xStart = 0;
} else if ((self.gravity & RIGHT) == RIGHT) {
xStart = self.width - self.contentWidth;
xStart = targetSize.width - self.contentWidth;
} else if ((self.gravity & CENTER_X) == CENTER_X) {
xStart = (self.width - self.contentWidth) / 2;
xStart = (targetSize.width - self.contentWidth) / 2;
}
CGFloat remain = targetSize.width - self.contentWidth;
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
}
DoricLinearConfig *childConfig = [self configForChild:child];
DoricLayoutConfig *childConfig = child.layoutConfig;
if (!childConfig) {
childConfig = [DoricLayoutConfig new];
}
CGSize size = [child sizeThatFits:CGSizeMake(targetSize.width - xStart, targetSize.height)];
if (childConfig.widthSpec == DoricLayoutExact) {
size.width = child.width;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
}
if (childConfig.widthSpec == DoricLayoutExact) {
size.width = child.width;
} else if (childConfig.widthSpec == DoricLayoutAtMost) {
size.width = targetSize.width - xStart;
}
if (childConfig.heightSpec == DoricLayoutExact) {
size.height = child.height;
} else if (childConfig.heightSpec == DoricLayoutAtMost) {
size.height = targetSize.height;
}
if (childConfig.weight) {
size.width = child.width;
}
if (childConfig.weight) {
size.width += remain / self.contentWeight * childConfig.weight;
}
child.width = size.width;
child.height = size.height;
DoricGravity gravity = childConfig.alignment | self.gravity;
if ((gravity & TOP) == TOP) {
child.top = 0;
} else if ((gravity & BOTTOM) == BOTTOM) {
child.bottom = self.height;
child.bottom = targetSize.height;
} else if ((gravity & CENTER_Y) == CENTER_Y) {
child.centerY = self.height / 2;
child.centerY = targetSize.height / 2;
} else {
if (childConfig.margin.top) {
child.top = childConfig.margin.top;
} else if (childConfig.margin.bottom) {
child.bottom = self.height - childConfig.margin.bottom;
child.bottom = targetSize.height - childConfig.margin.bottom;
}
}
if (childConfig.heightSpec == DoricLayoutAtMost) {
child.height = self.height;
}
if (childConfig.widthSpec == DoricLayoutAtMost) {
child.width = self.width - xStart - childConfig.margin.right - childConfig.margin.left - self.space;
}
if (childConfig.margin.left) {
xStart += childConfig.margin.left;
}
@ -441,9 +478,11 @@ - (void)layout {
xStart += childConfig.margin.right;
}
if ([child isKindOfClass:[DoricLayoutContainer class]]) {
[(DoricLayoutContainer *) child layout];
[(DoricLayoutContainer *) child layout:size];
}
}
self.width = targetSize.width;
self.height = targetSize.height;
}
@end

View File

@ -31,6 +31,6 @@ - (void)render:(NSDictionary *)props {
[self blend:props];
}
- (void)requestLayout {
[self.view requestLayout];
[self.view setNeedsLayout];
}
@end

View File

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

View File

@ -21,7 +21,6 @@
//
#import "DoricStackNode.h"
#import "DoricUtil.h"
@implementation DoricStackNode
@ -36,22 +35,4 @@ - (void)blendView:(DoricStackView *)view forPropName:(NSString *)name propValue:
[super blendView:view forPropName:name propValue:prop];
}
}
- (DoricStackConfig *)generateDefaultLayoutParams {
return [[DoricStackConfig alloc] init];
}
- (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layoutConfig {
[super blendSubNode:subNode layoutConfig:layoutConfig];
if (![subNode.layoutConfig isKindOfClass:DoricStackConfig.class]) {
DoricLog(@"blend DoricHLayoutView child error,layout params not match");
return;
}
DoricStackConfig *params = (DoricStackConfig *) subNode.layoutConfig;
NSNumber *alignment = layoutConfig[@"alignment"];
if (alignment) {
params.alignment = (DoricGravity) [alignment integerValue];
}
}
@end

View File

@ -20,8 +20,8 @@
#import <Foundation/Foundation.h>
#import "DoricViewNode.h"
@interface DoricSuperNode<V:UIView *, P:DoricLayoutConfig *> : DoricViewNode<V>
- (P)generateDefaultLayoutParams;
@interface DoricSuperNode<V:UIView *> : DoricViewNode<V>
- (DoricLayoutConfig *)generateDefaultLayoutParams;
- (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layoutConfig;

View File

@ -80,17 +80,20 @@ - (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layou
}
}];
if ([params isKindOfClass:DoricMarginConfig.class]) {
DoricMarginConfig *marginParams = (DoricMarginConfig *) params;
NSDictionary *margin = layoutConfig[@"margin"];
if (margin) {
marginParams.margin = DoricMarginMake(
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];
}
}
- (void)blendSubNode:(NSDictionary *)subModel {

View File

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

View File

@ -21,7 +21,6 @@
//
#import "DoricVLayoutNode.h"
#import "DoricUtil.h"
@implementation DoricVLayoutNode
@ -39,28 +38,4 @@ - (void)blendView:(DoricVLayoutView *)view forPropName:(NSString *)name propValu
}
}
- (void)blendSubNode:(DoricViewNode *)subNode layoutConfig:(NSDictionary *)layoutconfig {
[super blendSubNode:subNode layoutConfig:layoutconfig];
if (![subNode.layoutConfig isKindOfClass:DoricLinearConfig.class]) {
DoricLog(@"blend DoricVLayoutView child error,layout params not match");
return;
}
DoricLinearConfig *params = (DoricLinearConfig *) subNode.layoutConfig;
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];
}
}
- (DoricLinearConfig *)generateDefaultLayoutParams {
return [[DoricLinearConfig alloc] init];
}
@end

View File

@ -16,14 +16,6 @@
import { LayoutConfig, Group, Property, IView } from "./view";
import { Gravity } from "../util/gravity";
export interface StackConfig extends LayoutConfig {
}
export interface LinearConfig extends LayoutConfig {
weight?: number
}
export interface IStack extends IView {
gravity?: Gravity
}

View File

@ -35,6 +35,8 @@ export interface LayoutConfig {
bottom?: number,
}
alignment?: Gravity
//Only affective in VLayout or HLayout
weight?: number
}
export function Property(target: Object, propKey: string) {