iOS refact DoricLayout
This commit is contained in:
parent
ca6a3284f2
commit
abbe0ba377
@ -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];
|
||||
|
@ -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];
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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++) {
|
||||
|
@ -22,5 +22,5 @@
|
||||
|
||||
#import "DoricGroupNode.h"
|
||||
|
||||
@interface DoricHLayoutNode : DoricGroupNode<DoricHLayoutView *>
|
||||
@interface DoricHLayoutNode : DoricGroupNode<UIView *>
|
||||
@end
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -22,5 +22,5 @@
|
||||
|
||||
#import "DoricGroupNode.h"
|
||||
|
||||
@interface DoricStackNode : DoricGroupNode<DoricStackView *>
|
||||
@interface DoricStackNode : DoricGroupNode<UIView *>
|
||||
@end
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -22,5 +22,5 @@
|
||||
|
||||
#import "DoricGroupNode.h"
|
||||
|
||||
@interface DoricVLayoutNode : DoricGroupNode<DoricVLayoutView *>
|
||||
@interface DoricVLayoutNode : DoricGroupNode<UIView *>
|
||||
@end
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user