2020-04-09 17:07:24 +08:00
|
|
|
/*
|
|
|
|
* Copyright [2019] [Doric.Pub]
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
//
|
|
|
|
// Created by pengfei.zhou on 2020/4/9.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import <YogaKit/UIView+Yoga.h>
|
|
|
|
#import "DoricFlexNode.h"
|
|
|
|
#import "DoricExtensions.h"
|
2020-04-11 13:27:44 +08:00
|
|
|
#import "UIView+Yoga.h"
|
2020-04-09 17:07:24 +08:00
|
|
|
|
|
|
|
@interface DoricFlexView : UIView
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation DoricFlexView
|
|
|
|
- (CGSize)sizeThatFits:(CGSize)size {
|
2020-04-11 19:10:56 +08:00
|
|
|
for (UIView *view in self.subviews) {
|
2020-04-13 11:57:31 +08:00
|
|
|
[view.doricLayout measure:size];
|
|
|
|
[view configureLayoutWithBlock:^(YGLayout *layout) {
|
|
|
|
layout.isEnabled = YES;
|
|
|
|
if (layout.width.unit == YGUnitUndefined || layout.width.unit == YGUnitAuto) {
|
2020-04-11 19:10:56 +08:00
|
|
|
layout.width = YGPointValue(view.doricLayout.measuredWidth);
|
2020-04-13 11:57:31 +08:00
|
|
|
}
|
|
|
|
if (layout.height.unit == YGUnitUndefined || layout.height.unit == YGUnitAuto) {
|
2020-04-11 19:10:56 +08:00
|
|
|
layout.height = YGPointValue(view.doricLayout.measuredHeight);
|
2020-04-13 11:57:31 +08:00
|
|
|
}
|
|
|
|
}];
|
2020-04-11 19:10:56 +08:00
|
|
|
}
|
2020-04-15 18:36:50 +08:00
|
|
|
if (self.yoga.isLeaf) {
|
|
|
|
return CGSizeZero;
|
|
|
|
}
|
2020-04-10 11:37:48 +08:00
|
|
|
return [self.yoga intrinsicSize];
|
2020-04-09 17:07:24 +08:00
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation DoricFlexNode
|
|
|
|
- (UIView *)build {
|
|
|
|
return [[DoricFlexView new] also:^(DoricFlexView *it) {
|
2020-04-10 20:41:43 +08:00
|
|
|
it.clipsToBounds = YES;
|
2020-04-10 11:37:48 +08:00
|
|
|
[it configureLayoutWithBlock:^(YGLayout *_Nonnull layout) {
|
2020-04-09 20:01:22 +08:00
|
|
|
layout.isEnabled = YES;
|
|
|
|
}];
|
2020-04-09 17:07:24 +08:00
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)blendView:(UIView *)view forPropName:(NSString *)name propValue:(id)prop {
|
|
|
|
if ([name isEqualToString:@"flexConfig"]) {
|
2020-04-09 20:01:22 +08:00
|
|
|
[self blendYoga:view.yoga from:prop];
|
2020-04-09 17:07:24 +08:00
|
|
|
} else {
|
|
|
|
[super blendView:view forPropName:name propValue:prop];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)blendSubNode:(DoricViewNode *)subNode flexConfig:(NSDictionary *)flexConfig {
|
2020-04-10 11:37:48 +08:00
|
|
|
[subNode.view configureLayoutWithBlock:^(YGLayout *_Nonnull layout) {
|
2020-04-09 20:01:22 +08:00
|
|
|
layout.isEnabled = YES;
|
|
|
|
}];
|
2020-04-11 19:10:56 +08:00
|
|
|
subNode.view.doricLayout.disabled = YES;
|
2020-04-09 20:01:22 +08:00
|
|
|
[self blendYoga:subNode.view.yoga from:flexConfig];
|
2020-04-09 17:07:24 +08:00
|
|
|
}
|
|
|
|
|
2020-04-11 13:27:44 +08:00
|
|
|
- (void)blendYoga:(YGLayout *)yoga from:(NSDictionary *)flexConfig {
|
|
|
|
[flexConfig enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
|
|
|
|
[self blendYoga:yoga name:key value:obj];
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)blendYoga:(YGLayout *)yoga name:(NSString *)name value:(id)value {
|
|
|
|
if ([name isEqualToString:@"direction"]) {
|
|
|
|
yoga.direction = (YGDirection) [(NSNumber *) value integerValue];
|
|
|
|
} else if ([name isEqualToString:@"flexDirection"]) {
|
|
|
|
yoga.flexDirection = (YGFlexDirection) [(NSNumber *) value integerValue];
|
|
|
|
} else if ([name isEqualToString:@"justifyContent"]) {
|
|
|
|
yoga.justifyContent = (YGJustify) [(NSNumber *) value integerValue];
|
|
|
|
} else if ([name isEqualToString:@"alignContent"]) {
|
|
|
|
yoga.alignContent = (YGAlign) [(NSNumber *) value integerValue];
|
|
|
|
} else if ([name isEqualToString:@"alignItems"]) {
|
|
|
|
yoga.alignItems = (YGAlign) [(NSNumber *) value integerValue];
|
|
|
|
} else if ([name isEqualToString:@"alignSelf"]) {
|
|
|
|
yoga.alignSelf = (YGAlign) [(NSNumber *) value integerValue];
|
|
|
|
} else if ([name isEqualToString:@"positionType"]) {
|
|
|
|
yoga.position = (YGPositionType) [(NSNumber *) value integerValue];
|
|
|
|
} else if ([name isEqualToString:@"flexWrap"]) {
|
|
|
|
yoga.flexWrap = (YGWrap) [(NSNumber *) value integerValue];
|
|
|
|
} else if ([name isEqualToString:@"overFlow"]) {
|
|
|
|
yoga.overflow = (YGOverflow) [(NSNumber *) value integerValue];
|
|
|
|
} else if ([name isEqualToString:@"display"]) {
|
|
|
|
yoga.display = (YGDisplay) [(NSNumber *) value integerValue];
|
|
|
|
} else if ([name isEqualToString:@"flex"]) {
|
|
|
|
yoga.flex = [(NSNumber *) value floatValue];
|
|
|
|
} else if ([name isEqualToString:@"flexGrow"]) {
|
|
|
|
yoga.flexGrow = [(NSNumber *) value floatValue];
|
|
|
|
} else if ([name isEqualToString:@"flexShrink"]) {
|
|
|
|
yoga.flexShrink = [(NSNumber *) value floatValue];
|
|
|
|
} else if ([name isEqualToString:@"flexBasis"]) {
|
|
|
|
yoga.flexBasis = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"marginLeft"]) {
|
|
|
|
yoga.marginLeft = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"marginRight"]) {
|
|
|
|
yoga.marginRight = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"marginTop"]) {
|
|
|
|
yoga.marginTop = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"marginBottom"]) {
|
|
|
|
yoga.marginBottom = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"marginStart"]) {
|
|
|
|
yoga.marginStart = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"marginEnd"]) {
|
|
|
|
yoga.marginEnd = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"marginHorizontal"]) {
|
|
|
|
yoga.marginHorizontal = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"marginVertical"]) {
|
|
|
|
yoga.marginVertical = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"margin"]) {
|
|
|
|
yoga.margin = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"paddingLeft"]) {
|
|
|
|
yoga.paddingLeft = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"paddingRight"]) {
|
|
|
|
yoga.paddingRight = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"paddingTop"]) {
|
|
|
|
yoga.paddingTop = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"paddingBottom"]) {
|
|
|
|
yoga.paddingBottom = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"paddingStart"]) {
|
|
|
|
yoga.paddingStart = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"paddingEnd"]) {
|
|
|
|
yoga.paddingEnd = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"paddingHorizontal"]) {
|
|
|
|
yoga.paddingHorizontal = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"paddingVertical"]) {
|
|
|
|
yoga.paddingVertical = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"padding"]) {
|
|
|
|
yoga.padding = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"borderLeftWidth"]) {
|
|
|
|
yoga.borderLeftWidth = [(NSNumber *) value floatValue];
|
|
|
|
} else if ([name isEqualToString:@"borderRightWidth"]) {
|
|
|
|
yoga.borderRightWidth = [(NSNumber *) value floatValue];
|
|
|
|
} else if ([name isEqualToString:@"borderTopWidth"]) {
|
|
|
|
yoga.borderTopWidth = [(NSNumber *) value floatValue];
|
|
|
|
} else if ([name isEqualToString:@"borderBottomWidth"]) {
|
|
|
|
yoga.borderBottomWidth = [(NSNumber *) value floatValue];
|
|
|
|
} else if ([name isEqualToString:@"borderStartWidth"]) {
|
|
|
|
yoga.borderStartWidth = [(NSNumber *) value floatValue];
|
|
|
|
} else if ([name isEqualToString:@"borderEndWidth"]) {
|
|
|
|
yoga.borderEndWidth = [(NSNumber *) value floatValue];
|
|
|
|
} else if ([name isEqualToString:@"borderWidth"]) {
|
|
|
|
yoga.borderWidth = [(NSNumber *) value floatValue];
|
|
|
|
} else if ([name isEqualToString:@"left"]) {
|
|
|
|
yoga.left = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"right"]) {
|
|
|
|
yoga.right = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"top"]) {
|
|
|
|
yoga.top = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"bottom"]) {
|
|
|
|
yoga.bottom = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"start"]) {
|
|
|
|
yoga.start = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"end"]) {
|
|
|
|
yoga.end = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"width"]) {
|
|
|
|
yoga.width = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"height"]) {
|
|
|
|
yoga.height = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"minWidth"]) {
|
|
|
|
yoga.minWidth = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"minHeight"]) {
|
|
|
|
yoga.minHeight = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"maxWidth"]) {
|
|
|
|
yoga.maxWidth = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"maxHeight"]) {
|
|
|
|
yoga.maxHeight = [self translateYGValueFromProperty:value];
|
|
|
|
} else if ([name isEqualToString:@"aspectRatio"]) {
|
|
|
|
yoga.aspectRatio = [(NSNumber *) value floatValue];
|
|
|
|
} else {
|
|
|
|
NSLog(@"Should not exists in flex box:%@,%@", name, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (YGValue)translateYGValueFromProperty:(id)prop {
|
|
|
|
if ([prop isKindOfClass:[NSDictionary class]]) {
|
|
|
|
NSNumber *type = prop[@"type"];
|
|
|
|
NSNumber *value = prop[@"value"];
|
|
|
|
switch (type.integerValue) {
|
|
|
|
case YGUnitPoint:
|
|
|
|
return YGPointValue(value.floatValue);
|
|
|
|
case YGUnitPercent:
|
|
|
|
return YGPercentValue(value.floatValue);
|
|
|
|
case YGUnitUndefined:
|
|
|
|
return YGValueUndefined;
|
|
|
|
default:
|
|
|
|
return YGValueAuto;
|
|
|
|
}
|
|
|
|
} else if ([prop isKindOfClass:[NSNumber class]]) {
|
|
|
|
return YGPointValue([prop floatValue]);
|
|
|
|
} else {
|
|
|
|
return YGValueAuto;
|
|
|
|
}
|
|
|
|
}
|
2020-04-09 17:07:24 +08:00
|
|
|
|
|
|
|
- (void)requestLayout {
|
2020-04-10 11:37:48 +08:00
|
|
|
if (self.view.doricLayout.widthSpec != DoricLayoutFit) {
|
|
|
|
self.view.yoga.width = YGPointValue(self.view.width);
|
|
|
|
}
|
|
|
|
if (self.view.doricLayout.heightSpec != DoricLayoutFit) {
|
|
|
|
self.view.yoga.height = YGPointValue(self.view.height);
|
|
|
|
}
|
|
|
|
[self.view.yoga applyLayoutPreservingOrigin:YES];
|
|
|
|
/// Need layout again.
|
|
|
|
for (UIView *view in self.view.subviews) {
|
2020-04-11 19:10:56 +08:00
|
|
|
if ([view isKindOfClass:[DoricFlexView class]]) {
|
2020-04-10 11:37:48 +08:00
|
|
|
continue;
|
|
|
|
}
|
2020-04-15 19:08:10 +08:00
|
|
|
if (view.doricLayout.measuredWidth != view.width || view.doricLayout.measuredHeight != view.height) {
|
|
|
|
view.doricLayout.widthSpec = DoricLayoutJust;
|
|
|
|
view.doricLayout.heightSpec = DoricLayoutJust;
|
|
|
|
view.doricLayout.width = view.width;
|
|
|
|
view.doricLayout.height = view.height;
|
2020-04-10 11:37:48 +08:00
|
|
|
}
|
|
|
|
view.doricLayout.measuredX = view.left;
|
|
|
|
view.doricLayout.measuredY = view.top;
|
2020-04-09 20:01:22 +08:00
|
|
|
[view.doricLayout apply];
|
|
|
|
}
|
2020-04-13 11:57:31 +08:00
|
|
|
[super requestLayout];
|
2020-04-09 17:07:24 +08:00
|
|
|
}
|
2020-04-09 20:01:22 +08:00
|
|
|
@end
|