Moved properties to a YKLayout object
This commit is contained in:
@@ -8,68 +8,10 @@
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "YKEnums.h"
|
||||
#import <YogaKit/YKLayout.h>
|
||||
|
||||
@interface UIView (YogaKit)
|
||||
|
||||
/**
|
||||
The property that decides if we should include this view when calculating layout. Defaults to YES.
|
||||
*/
|
||||
@property (nonatomic, setter=yk_setIncludeInLayout:) BOOL yk_includeInLayout NS_SWIFT_NAME(includeInLayout);
|
||||
|
||||
/**
|
||||
The property that decides during layout/sizing whether or not yk_* properties should be applied. Defaults to NO.
|
||||
*/
|
||||
@property (nonatomic, setter=yk_setUsesYoga:) BOOL yk_usesYoga NS_SWIFT_NAME(usesYoga);
|
||||
|
||||
@property (nonatomic, setter=yk_setDirection:) YKDirection yk_direction NS_SWIFT_NAME(layoutDirection);
|
||||
@property (nonatomic, setter=yk_setFlexDirection:) YKFlexDirection yk_flexDirection NS_SWIFT_NAME(layoutFlexDirection);
|
||||
@property (nonatomic, setter=yk_setJustifyContent:) YKJustify yk_justifyContent NS_SWIFT_NAME(layoutJustifyContent);
|
||||
@property (nonatomic, setter=yk_setAlignContent:) YKAlign yk_alignContent NS_SWIFT_NAME(layoutAlignContent);
|
||||
@property (nonatomic, setter=yk_setAlignItems:) YKAlign yk_alignItems NS_SWIFT_NAME(layoutAlignItems);
|
||||
@property (nonatomic, setter=yk_setAlignSelf:) YKAlign yk_alignSelf NS_SWIFT_NAME(layoutAlignSelf);
|
||||
@property (nonatomic, setter=yk_setPositionType:) YKPositionType yk_positionType NS_SWIFT_NAME(layoutPositionType);
|
||||
@property (nonatomic, setter=yk_setFlexWrap:) YKWrap yk_flexWrap NS_SWIFT_NAME(layoutFlexWrap);
|
||||
|
||||
@property (nonatomic, setter=yk_setFlexGrow:) CGFloat yk_flexGrow NS_SWIFT_NAME(layoutFlexGrow);
|
||||
@property (nonatomic, setter=yk_setFlexShrink:) CGFloat yk_flexShrink NS_SWIFT_NAME(layoutFlexShrink);
|
||||
@property (nonatomic, setter=yk_setFlexBasis:) CGFloat yk_flexBasis NS_SWIFT_NAME(layoutFlexBasis);
|
||||
|
||||
- (void)yk_positionForEdge:(YKEdge)edge;
|
||||
- (void)yk_setPosition:(CGFloat)position forEdge:(YKEdge)edge;
|
||||
- (void)yk_marginForEdge:(YKEdge)edge;
|
||||
- (void)yk_setMargin:(CGFloat)margin forEdge:(YKEdge)edge;
|
||||
- (void)yk_paddingForEdge:(YKEdge)edge;
|
||||
- (void)yk_setPadding:(CGFloat)padding forEdge:(YKEdge)edge;
|
||||
|
||||
@property (nonatomic, setter=yk_setWidth:) CGFloat yk_width NS_SWIFT_NAME(layoutWidth);
|
||||
@property (nonatomic, setter=yk_setHeight:) CGFloat yk_height NS_SWIFT_NAME(layoutHeight);
|
||||
@property (nonatomic, setter=yk_setMinWidth:) CGFloat yk_minWidth NS_SWIFT_NAME(layoutMinWidth);
|
||||
@property (nonatomic, setter=yk_setMinHeight:) CGFloat yk_minHeight NS_SWIFT_NAME(layoutMinHeight);
|
||||
@property (nonatomic, setter=yk_setMaxWidth:) CGFloat yk_maxWidth NS_SWIFT_NAME(layoutMaxWidth);
|
||||
@property (nonatomic, setter=yk_setMaxHeight:) CGFloat yk_maxHeight NS_SWIFT_NAME(layoutMaxHeight);
|
||||
|
||||
// Yoga specific properties, not compatible with flexbox specification
|
||||
@property (nonatomic, setter=yk_setAspectRatio:) CGFloat yk_aspectRatio NS_SWIFT_NAME(layoutAspectRatio);
|
||||
|
||||
/**
|
||||
Get the resolved direction of this node. This won't be YGDirectionInherit
|
||||
*/
|
||||
@property (nonatomic, readonly) CGFloat yk_resolvedDirection NS_SWIFT_NAME(layoutResolvedDirection);
|
||||
|
||||
/**
|
||||
Perform a layout calculation and update the frames of the views in the hierarchy with the results
|
||||
*/
|
||||
- (void)yk_applyLayout NS_SWIFT_NAME(applyLayout());
|
||||
|
||||
/**
|
||||
Returns the size of the view if no constraints were given. This could equivalent to calling [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
|
||||
*/
|
||||
@property (nonatomic, readonly) CGSize yk_intrinsicSize NS_SWIFT_NAME(layoutIntrinsicSize);
|
||||
|
||||
/**
|
||||
Returns the number of children that are using Flexbox.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger yk_numberOfChildren NS_SWIFT_NAME(layoutNumberOfChildren);
|
||||
@property (nonatomic, readonly) YKLayout* layout;
|
||||
|
||||
@end
|
||||
|
@@ -7,478 +7,22 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <YogaKit/UIView+Yoga.h>
|
||||
#import <YogaKit/yoga.h>
|
||||
#import <YogaKit/UIView+YogaKit.h>
|
||||
#import <YogaKit/YKLayout+Private.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@interface YGNodeBridge : NSObject
|
||||
@property (nonatomic, assign, readonly) YGNodeRef cnode;
|
||||
@end
|
||||
|
||||
@implementation YGNodeBridge
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
YGSetExperimentalFeatureEnabled(YGExperimentalFeatureWebFlexBasis, true);
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ([super init]) {
|
||||
_cnode = YGNodeNew();
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
YGNodeFree(_cnode);
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation UIView (YogaKit)
|
||||
|
||||
- (BOOL)yk_usesYoga
|
||||
- (YKLayout *)layout
|
||||
{
|
||||
NSNumber *usesYoga = objc_getAssociatedObject(self, @selector(yk_usesYoga));
|
||||
return [usesYoga boolValue];
|
||||
YKLayout *layout = objc_getAssociatedObject(self, @selector(layout));
|
||||
if (!layout) {
|
||||
layout = [[YKLayout alloc] initWithView:self];
|
||||
objc_setAssociatedObject(self, @selector(layout), layout, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (BOOL)yk_includeInLayout
|
||||
{
|
||||
NSNumber *includeInLayout = objc_getAssociatedObject(self, @selector(yk_includeInLayout));
|
||||
return (includeInLayout != nil) ? [includeInLayout boolValue] : YES;
|
||||
return layout;
|
||||
}
|
||||
|
||||
- (NSUInteger)yk_numberOfChildren
|
||||
{
|
||||
return YGNodeGetChildCount([self ygNode]);
|
||||
}
|
||||
|
||||
#pragma mark - Setters
|
||||
|
||||
- (void)yk_setIncludeInLayout:(BOOL)includeInLayout
|
||||
{
|
||||
objc_setAssociatedObject(
|
||||
self,
|
||||
@selector(yk_includeInLayout),
|
||||
@(includeInLayout),
|
||||
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (void)yk_setUsesYoga:(BOOL)enabled
|
||||
{
|
||||
objc_setAssociatedObject(
|
||||
self,
|
||||
@selector(yk_usesYoga),
|
||||
@(enabled),
|
||||
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (YKDirection)yk_direction
|
||||
{
|
||||
return (YKDirection)YGNodeStyleGetDirection([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setDirection:(YKDirection)direction
|
||||
{
|
||||
YGNodeStyleSetDirection([self ygNode], (YGDirection)direction);
|
||||
}
|
||||
|
||||
- (YKFlexDirection)yk_flexDirection
|
||||
{
|
||||
return (YKFlexDirection)YGNodeStyleGetFlexDirection([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setFlexDirection:(YKFlexDirection)flexDirection
|
||||
{
|
||||
YGNodeStyleSetFlexDirection([self ygNode], (YGFlexDirection)flexDirection);
|
||||
}
|
||||
|
||||
- (YKJustify)yk_justifyContent
|
||||
{
|
||||
return (YKJustify)YGNodeStyleGetJustifyContent([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setJustifyContent:(YKJustify)justifyContent
|
||||
{
|
||||
YGNodeStyleSetJustifyContent([self ygNode], (YGJustify)justifyContent);
|
||||
}
|
||||
|
||||
- (YKAlign)yk_alignContent
|
||||
{
|
||||
return (YKAlign)YGNodeStyleGetAlignContent([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setAlignContent:(YKAlign)alignContent
|
||||
{
|
||||
YGNodeStyleSetAlignContent([self ygNode], (YGAlign)alignContent);
|
||||
}
|
||||
|
||||
- (YKAlign)yk_alignItems
|
||||
{
|
||||
return (YKAlign)YGNodeStyleGetAlignItems([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setAlignItems:(YKAlign)alignItems
|
||||
{
|
||||
YGNodeStyleSetAlignItems([self ygNode], (YGAlign)alignItems);
|
||||
}
|
||||
|
||||
- (YKAlign)yk_alignSelf
|
||||
{
|
||||
return (YKAlign)YGNodeStyleGetAlignSelf([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setAlignSelf:(YKAlign)alignSelf
|
||||
{
|
||||
YGNodeStyleSetAlignSelf([self ygNode], (YGAlign)alignSelf);
|
||||
}
|
||||
|
||||
- (YKPositionType)yk_positionType
|
||||
{
|
||||
return (YKPositionType)YGNodeStyleGetPositionType([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setPositionType:(YKPositionType)positionType
|
||||
{
|
||||
YGNodeStyleSetPositionType([self ygNode], (YGPositionType)positionType);
|
||||
}
|
||||
|
||||
- (YKWrap)yk_flexWrap
|
||||
{
|
||||
return (YKWrap)YGNodeStyleGetFlexWrap([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setFlexWrap:(YKWrap)flexWrap
|
||||
{
|
||||
YGNodeStyleSetFlexWrap([self ygNode], (YGWrap)flexWrap);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_flexGrow
|
||||
{
|
||||
return YGNodeStyleGetFlexGrow([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setFlexGrow:(CGFloat)flexGrow
|
||||
{
|
||||
YGNodeStyleSetFlexGrow([self ygNode], flexGrow);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_flexShrink
|
||||
{
|
||||
return YGNodeStyleGetFlexShrink([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setFlexShrink:(CGFloat)flexShrink
|
||||
{
|
||||
YGNodeStyleSetFlexShrink([self ygNode], flexShrink);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_flexBasis
|
||||
{
|
||||
return YGNodeStyleGetFlexBasis([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setFlexBasis:(CGFloat)flexBasis
|
||||
{
|
||||
YGNodeStyleSetFlexBasis([self ygNode], flexBasis);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_positionForEdge:(YKEdge)edge
|
||||
{
|
||||
return YGNodeStyleGetPosition([self ygNode], (YGEdge)edge);
|
||||
}
|
||||
|
||||
- (void)yk_setPosition:(CGFloat)position forEdge:(YKEdge)edge
|
||||
{
|
||||
YGNodeStyleSetPosition([self ygNode], (YGEdge)edge, position);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_marginForEdge:(YKEdge)edge
|
||||
{
|
||||
return YGNodeStyleGetMargin([self ygNode], (YGEdge)edge);
|
||||
}
|
||||
|
||||
- (void)yk_setMargin:(CGFloat)margin forEdge:(YKEdge)edge
|
||||
{
|
||||
YGNodeStyleSetMargin([self ygNode], (YGEdge)edge, margin);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_paddingForEdge:(YKEdge)edge
|
||||
{
|
||||
return YGNodeStyleGetPadding([self ygNode], (YGEdge)edge);
|
||||
}
|
||||
|
||||
- (void)yk_setPadding:(CGFloat)padding forEdge:(YKEdge)edge
|
||||
{
|
||||
YGNodeStyleSetPadding([self ygNode], (YGEdge)edge, padding);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_width
|
||||
{
|
||||
return YGNodeStyleGetWidth([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setWidth:(CGFloat)width
|
||||
{
|
||||
YGNodeStyleSetWidth([self ygNode], width);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_height
|
||||
{
|
||||
return YGNodeStyleGetHeight([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setHeight:(CGFloat)height
|
||||
{
|
||||
YGNodeStyleSetHeight([self ygNode], height);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_minWidth
|
||||
{
|
||||
return YGNodeStyleGetMinWidth([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setMinWidth:(CGFloat)minWidth
|
||||
{
|
||||
YGNodeStyleSetMinWidth([self ygNode], minWidth);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_minHeight
|
||||
{
|
||||
return YGNodeStyleGetMinHeight([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setMinHeight:(CGFloat)minHeight
|
||||
{
|
||||
YGNodeStyleSetMinHeight([self ygNode], minHeight);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_maxWidth
|
||||
{
|
||||
return YGNodeStyleGetMaxWidth([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setMaxWidth:(CGFloat)maxWidth
|
||||
{
|
||||
YGNodeStyleSetMaxWidth([self ygNode], maxWidth);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_maxHeight
|
||||
{
|
||||
return YGNodeStyleGetMaxHeight([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setMaxHeight:(CGFloat)maxHeight
|
||||
{
|
||||
YGNodeStyleSetMaxHeight([self ygNode], maxHeight);
|
||||
}
|
||||
|
||||
- (CGFloat)yk_aspectRatio
|
||||
{
|
||||
return YGNodeStyleGetAspectRatio([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_setAspectRatio:(CGFloat)aspectRatio
|
||||
{
|
||||
YGNodeStyleSetAspectRatio([self ygNode], aspectRatio);
|
||||
}
|
||||
|
||||
#pragma mark - Layout and Sizing
|
||||
|
||||
- (YKDirection)yk_resolvedDirection
|
||||
{
|
||||
return (YKDirection)YGNodeLayoutGetDirection([self ygNode]);
|
||||
}
|
||||
|
||||
- (void)yk_applyLayout
|
||||
{
|
||||
[self calculateLayoutWithSize:self.bounds.size];
|
||||
YKApplyLayoutToViewHierarchy(self);
|
||||
}
|
||||
|
||||
- (CGSize)yk_intrinsicSize
|
||||
{
|
||||
const CGSize constrainedSize = {
|
||||
.width = YGUndefined,
|
||||
.height = YGUndefined,
|
||||
};
|
||||
return [self calculateLayoutWithSize:constrainedSize];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (YGNodeRef)ygNode
|
||||
{
|
||||
YGNodeBridge *node = objc_getAssociatedObject(self, @selector(ygNode));
|
||||
if (!node) {
|
||||
node = [YGNodeBridge new];
|
||||
YGNodeSetContext(node.cnode, (__bridge void *) self);
|
||||
objc_setAssociatedObject(self, @selector(ygNode), node, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
return node.cnode;
|
||||
}
|
||||
|
||||
- (CGSize)calculateLayoutWithSize:(CGSize)size
|
||||
{
|
||||
NSAssert([NSThread isMainThread], @"YG Layout calculation must be done on main.");
|
||||
NSAssert([self yk_usesYoga], @"YG Layout is not enabled for this view.");
|
||||
|
||||
YKAttachNodesFromViewHierachy(self);
|
||||
|
||||
const YGNodeRef node = [self ygNode];
|
||||
YGNodeCalculateLayout(
|
||||
node,
|
||||
size.width,
|
||||
size.height,
|
||||
YGNodeStyleGetDirection(node));
|
||||
|
||||
return (CGSize) {
|
||||
.width = YGNodeLayoutGetWidth(node),
|
||||
.height = YGNodeLayoutGetHeight(node),
|
||||
};
|
||||
}
|
||||
|
||||
static YGSize YKMeasureView(
|
||||
YGNodeRef node,
|
||||
float width,
|
||||
YGMeasureMode widthMode,
|
||||
float height,
|
||||
YGMeasureMode heightMode)
|
||||
{
|
||||
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
|
||||
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height;
|
||||
|
||||
UIView *view = (__bridge UIView*) YGNodeGetContext(node);
|
||||
const CGSize sizeThatFits = [view sizeThatFits:(CGSize) {
|
||||
.width = constrainedWidth,
|
||||
.height = constrainedHeight,
|
||||
}];
|
||||
|
||||
return (YGSize) {
|
||||
.width = YKSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode),
|
||||
.height = YKSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode),
|
||||
};
|
||||
}
|
||||
|
||||
static CGFloat YKSanitizeMeasurement(
|
||||
CGFloat constrainedSize,
|
||||
CGFloat measuredSize,
|
||||
YGMeasureMode measureMode)
|
||||
{
|
||||
CGFloat result;
|
||||
if (measureMode == YGMeasureModeExactly) {
|
||||
result = constrainedSize;
|
||||
} else if (measureMode == YGMeasureModeAtMost) {
|
||||
result = MIN(constrainedSize, measuredSize);
|
||||
} else {
|
||||
result = measuredSize;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void YKAttachNodesFromViewHierachy(UIView *view) {
|
||||
YGNodeRef node = [view ygNode];
|
||||
|
||||
// Only leaf nodes should have a measure function
|
||||
if (![view yk_usesYoga] || view.subviews.count == 0) {
|
||||
YGNodeSetMeasureFunc(node, YKMeasureView);
|
||||
YKRemoveAllChildren(node);
|
||||
} else {
|
||||
YGNodeSetMeasureFunc(node, NULL);
|
||||
|
||||
// Create a list of all the subviews that we are going to use for layout.
|
||||
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
|
||||
for (UIView *subview in view.subviews) {
|
||||
if ([subview yk_includeInLayout]) {
|
||||
[subviewsToInclude addObject:subview];
|
||||
}
|
||||
}
|
||||
|
||||
BOOL shouldReconstructChildList = NO;
|
||||
if (YGNodeGetChildCount(node) != subviewsToInclude.count) {
|
||||
shouldReconstructChildList = YES;
|
||||
} else {
|
||||
for (int i = 0; i < subviewsToInclude.count; i++) {
|
||||
if (YGNodeGetChild(node, i) != [subviewsToInclude[i] ygNode]) {
|
||||
shouldReconstructChildList = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldReconstructChildList) {
|
||||
YKRemoveAllChildren(node);
|
||||
|
||||
for (int i = 0 ; i < subviewsToInclude.count; i++) {
|
||||
UIView *const subview = subviewsToInclude[i];
|
||||
YGNodeInsertChild(node, [subview ygNode], i);
|
||||
YKAttachNodesFromViewHierachy(subview);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void YKRemoveAllChildren(const YGNodeRef node)
|
||||
{
|
||||
if (node == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (YGNodeGetChildCount(node) > 0) {
|
||||
YGNodeRemoveChild(node, YGNodeGetChild(node, YGNodeGetChildCount(node) - 1));
|
||||
}
|
||||
}
|
||||
|
||||
static CGFloat YKRoundPixelValue(CGFloat value)
|
||||
{
|
||||
static CGFloat scale;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^(){
|
||||
scale = [UIScreen mainScreen].scale;
|
||||
});
|
||||
|
||||
return round(value * scale) / scale;
|
||||
}
|
||||
|
||||
static void YKApplyLayoutToViewHierarchy(UIView *view) {
|
||||
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread.");
|
||||
if (![view yk_includeInLayout]) {
|
||||
return;
|
||||
}
|
||||
|
||||
YGNodeRef node = [view ygNode];
|
||||
const CGPoint topLeft = {
|
||||
YGNodeLayoutGetLeft(node),
|
||||
YGNodeLayoutGetTop(node),
|
||||
};
|
||||
|
||||
const CGPoint bottomRight = {
|
||||
topLeft.x + YGNodeLayoutGetWidth(node),
|
||||
topLeft.y + YGNodeLayoutGetHeight(node),
|
||||
};
|
||||
|
||||
view.frame = (CGRect) {
|
||||
.origin = {
|
||||
.x = YKRoundPixelValue(topLeft.x),
|
||||
.y = YKRoundPixelValue(topLeft.y),
|
||||
},
|
||||
.size = {
|
||||
.width = YKRoundPixelValue(bottomRight.x) - YKRoundPixelValue(topLeft.x),
|
||||
.height = YKRoundPixelValue(bottomRight.y) - YKRoundPixelValue(topLeft.y),
|
||||
},
|
||||
};
|
||||
|
||||
const BOOL isLeaf = ![view yk_usesYoga] || view.subviews.count == 0;
|
||||
if (!isLeaf) {
|
||||
for (NSUInteger i = 0; i < view.subviews.count; i++) {
|
||||
YKApplyLayoutToViewHierarchy(view.subviews[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
@@ -12,24 +12,12 @@ typedef NS_ENUM(NSInteger, YKFlexDirection) {
|
||||
YKFlexDirectionColumnReverse,
|
||||
YKFlexDirectionRow,
|
||||
YKFlexDirectionRowReverse,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, YKEdge) {
|
||||
YKEdgeLeft,
|
||||
YKEdgeTop,
|
||||
YKEdgeRight,
|
||||
YKEdgeBottom,
|
||||
YKEdgeStart,
|
||||
YKEdgeEnd,
|
||||
YKEdgeHorizontal,
|
||||
YKEdgeVertical,
|
||||
YKEdgeAll,
|
||||
};
|
||||
} NS_SWIFT_NAME(FlexDirection);
|
||||
|
||||
typedef NS_ENUM(NSInteger, YKPositionType) {
|
||||
YKPositionTypeRelative,
|
||||
YKPositionTypeAbsolute,
|
||||
};
|
||||
} NS_SWIFT_NAME(PositionType);
|
||||
|
||||
typedef NS_ENUM(NSInteger, YKJustify) {
|
||||
YKJustifyFlexStart,
|
||||
@@ -37,18 +25,18 @@ typedef NS_ENUM(NSInteger, YKJustify) {
|
||||
YKJustifyFlexEnd,
|
||||
YKJustifySpaceBetween,
|
||||
YKJustifySpaceAround,
|
||||
};
|
||||
} NS_SWIFT_NAME(Justify);
|
||||
|
||||
typedef NS_ENUM(NSInteger, YKDirection) {
|
||||
YKDirectionInherit,
|
||||
YKDirectionLeftToRight,
|
||||
YKDirectionRightToLeft,
|
||||
};
|
||||
} NS_SWIFT_NAME(Direction);
|
||||
|
||||
typedef NS_ENUM(NSInteger, YKWrap) {
|
||||
YKWrapNoWrap,
|
||||
YKWrapWrap,
|
||||
};
|
||||
} NS_SWIFT_NAME(Wrap);
|
||||
|
||||
typedef NS_ENUM(NSInteger, YKAlign) {
|
||||
YKAlignAuto,
|
||||
@@ -56,5 +44,5 @@ typedef NS_ENUM(NSInteger, YKAlign) {
|
||||
YKAlignCenter,
|
||||
YKAlignFlexEnd,
|
||||
YKAlignStretch,
|
||||
};
|
||||
} NS_SWIFT_NAME(Align);
|
||||
|
||||
|
16
YogaKit/YKLayout+Private.h
Normal file
16
YogaKit/YKLayout+Private.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <YogaKit/YKLayout.h>
|
||||
|
||||
@interface YKLayout ()
|
||||
|
||||
- (instancetype)initWithView:(UIView*)view;
|
||||
|
||||
@end
|
97
YogaKit/YKLayout.h
Normal file
97
YogaKit/YKLayout.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "YKEnums.h"
|
||||
|
||||
@interface YKLayout : NSObject
|
||||
|
||||
/**
|
||||
The property that decides if we should include this view when calculating layout. Defaults to YES.
|
||||
*/
|
||||
@property (nonatomic, setter=setIncluded:) BOOL isIncluded;
|
||||
|
||||
/**
|
||||
The property that decides during layout/sizing whether or not yk_* properties should be applied. Defaults to NO.
|
||||
*/
|
||||
@property (nonatomic, setter=setEnabled:) BOOL isEnabled;
|
||||
|
||||
@property (nonatomic) YKDirection direction;
|
||||
@property (nonatomic) YKFlexDirection flexDirection;
|
||||
@property (nonatomic) YKJustify justifyContent;
|
||||
@property (nonatomic) YKAlign alignContent;
|
||||
@property (nonatomic) YKAlign alignItems;
|
||||
@property (nonatomic) YKAlign alignSelf;
|
||||
@property (nonatomic) YKPositionType positionType;
|
||||
@property (nonatomic) YKWrap flexWrap;
|
||||
|
||||
@property (nonatomic) CGFloat flexGrow;
|
||||
@property (nonatomic) CGFloat flexShrink;
|
||||
@property (nonatomic) CGFloat flexBasis;
|
||||
|
||||
@property (nonatomic) CGFloat positionLeft;
|
||||
@property (nonatomic) CGFloat positionTop;
|
||||
@property (nonatomic) CGFloat positionRight;
|
||||
@property (nonatomic) CGFloat positionBottom;
|
||||
@property (nonatomic) CGFloat positionStart;
|
||||
@property (nonatomic) CGFloat positionEnd;
|
||||
@property (nonatomic) CGFloat positionHorizontal;
|
||||
@property (nonatomic) CGFloat positionVertical;
|
||||
@property (nonatomic) CGFloat positionAll;
|
||||
|
||||
@property (nonatomic) CGFloat marginLeft;
|
||||
@property (nonatomic) CGFloat marginTop;
|
||||
@property (nonatomic) CGFloat marginRight;
|
||||
@property (nonatomic) CGFloat marginBottom;
|
||||
@property (nonatomic) CGFloat marginStart;
|
||||
@property (nonatomic) CGFloat marginEnd;
|
||||
@property (nonatomic) CGFloat marginHorizontal;
|
||||
@property (nonatomic) CGFloat marginVertical;
|
||||
@property (nonatomic) CGFloat marginAll;
|
||||
|
||||
@property (nonatomic) CGFloat paddingLeft;
|
||||
@property (nonatomic) CGFloat paddingTop;
|
||||
@property (nonatomic) CGFloat paddingRight;
|
||||
@property (nonatomic) CGFloat paddingBottom;
|
||||
@property (nonatomic) CGFloat paddingStart;
|
||||
@property (nonatomic) CGFloat paddingEnd;
|
||||
@property (nonatomic) CGFloat paddingHorizontal;
|
||||
@property (nonatomic) CGFloat paddingVertical;
|
||||
@property (nonatomic) CGFloat paddingAll;
|
||||
|
||||
@property (nonatomic) CGFloat width;
|
||||
@property (nonatomic) CGFloat height;
|
||||
@property (nonatomic) CGFloat minWidth;
|
||||
@property (nonatomic) CGFloat minHeight;
|
||||
@property (nonatomic) CGFloat maxWidth;
|
||||
@property (nonatomic) CGFloat maxHeight;
|
||||
|
||||
// Yoga specific properties, not compatible with flexbox specification
|
||||
@property (nonatomic) CGFloat aspectRatio;
|
||||
|
||||
/**
|
||||
Get the resolved direction of this node. This won't be YGDirectionInherit
|
||||
*/
|
||||
@property (nonatomic, readonly) YKDirection resolvedDirection;
|
||||
|
||||
/**
|
||||
Perform a layout calculation and update the frames of the views in the hierarchy with the results
|
||||
*/
|
||||
- (void)apply;
|
||||
|
||||
/**
|
||||
Returns the size of the view if no constraints were given. This could equivalent to calling [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
|
||||
*/
|
||||
@property (nonatomic, readonly) CGSize intrinsicSize;
|
||||
|
||||
/**
|
||||
Returns the number of children that are using Flexbox.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger numberOfChildren;
|
||||
|
||||
@end
|
294
YogaKit/YKLayout.m
Normal file
294
YogaKit/YKLayout.m
Normal file
@@ -0,0 +1,294 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <YogaKit/UIView+YogaKit.h>
|
||||
#import <YogaKit/YKLayout.h>
|
||||
#import <YogaKit/yoga.h>
|
||||
|
||||
#define YK_STYLE_PROPERTY_IMPL(objc_type, c_type, lowercased_name, capitalized_name) \
|
||||
- (objc_type)lowercased_name \
|
||||
{ \
|
||||
return (objc_type)YGNodeStyleGet##capitalized_name(_node); \
|
||||
} \
|
||||
\
|
||||
- (void)set##capitalized_name:(objc_type)lowercased_name \
|
||||
{ \
|
||||
YGNodeStyleSet##capitalized_name(_node, (c_type)lowercased_name); \
|
||||
}
|
||||
|
||||
#define _YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, edge) \
|
||||
- (CGFloat)lowercased_name##edge \
|
||||
{ \
|
||||
return YGNodeStyleGet##capitalized_name(_node, YGEdge##edge); \
|
||||
} \
|
||||
\
|
||||
- (void)set##capitalized_name##edge:(CGFloat)lowercased_name##edge \
|
||||
{ \
|
||||
YGNodeStyleSet##capitalized_name(_node, YGEdge##edge, lowercased_name##edge); \
|
||||
}
|
||||
|
||||
#define YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name) \
|
||||
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Left) \
|
||||
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Top) \
|
||||
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Right) \
|
||||
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Bottom) \
|
||||
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Start) \
|
||||
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, End) \
|
||||
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Horizontal) \
|
||||
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, Vertical) \
|
||||
_YK_STYLE_EDGE_PROPERTY_IMPL(lowercased_name, capitalized_name, All)
|
||||
|
||||
@interface YKLayout ()
|
||||
@property (nonatomic, weak, readonly) UIView* view;
|
||||
@property (nonatomic, assign, readonly) YGNodeRef node;
|
||||
@end
|
||||
|
||||
@implementation YKLayout
|
||||
|
||||
@synthesize isEnabled=_isEnabled;
|
||||
@synthesize isIncluded=_isIncluded;
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
YGSetExperimentalFeatureEnabled(YGExperimentalFeatureWebFlexBasis, true);
|
||||
}
|
||||
|
||||
- (instancetype)initWithView:(UIView*)view
|
||||
{
|
||||
if ([super init]) {
|
||||
_view = view;
|
||||
_node = YGNodeNew();
|
||||
YGNodeSetContext(_node, (__bridge void *) view);
|
||||
_isEnabled = NO;
|
||||
_isIncluded = YES;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
YGNodeFree(_node);
|
||||
}
|
||||
|
||||
- (NSUInteger)numberOfChildren
|
||||
{
|
||||
return YGNodeGetChildCount(_node);
|
||||
}
|
||||
|
||||
YK_STYLE_PROPERTY_IMPL(YKDirection, YGDirection, direction, Direction)
|
||||
YK_STYLE_PROPERTY_IMPL(YKFlexDirection, YGFlexDirection, flexDirection, FlexDirection)
|
||||
YK_STYLE_PROPERTY_IMPL(YKJustify, YGJustify, justifyContent, JustifyContent)
|
||||
YK_STYLE_PROPERTY_IMPL(YKAlign, YGAlign, alignContent, AlignContent)
|
||||
YK_STYLE_PROPERTY_IMPL(YKAlign, YGAlign, alignItems, AlignItems)
|
||||
YK_STYLE_PROPERTY_IMPL(YKAlign, YGAlign, alignSelf, AlignSelf)
|
||||
YK_STYLE_PROPERTY_IMPL(YKPositionType, YGPositionType, positionType, PositionType)
|
||||
YK_STYLE_PROPERTY_IMPL(YKWrap, YGWrap, flexWrap, FlexWrap)
|
||||
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, flexGrow, FlexGrow)
|
||||
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, flexShrink, FlexShrink)
|
||||
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, flexBasis, FlexBasis)
|
||||
YK_STYLE_EDGE_PROPERTY_IMPL(position, Position)
|
||||
YK_STYLE_EDGE_PROPERTY_IMPL(margin, Margin)
|
||||
YK_STYLE_EDGE_PROPERTY_IMPL(padding, Padding)
|
||||
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, width, Width)
|
||||
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, height, Height)
|
||||
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, minWidth, MinWidth)
|
||||
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, minHeight, MinHeight)
|
||||
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, maxWidth, MaxWidth)
|
||||
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, maxHeight, MaxHeight)
|
||||
YK_STYLE_PROPERTY_IMPL(CGFloat, CGFloat, aspectRatio, AspectRatio)
|
||||
|
||||
#pragma mark - Layout and Sizing
|
||||
|
||||
- (YKDirection)resolvedDirection
|
||||
{
|
||||
return (YKDirection)YGNodeLayoutGetDirection(_node);
|
||||
}
|
||||
|
||||
- (void)apply
|
||||
{
|
||||
[self calculateLayoutWithSize:self.view.bounds.size];
|
||||
YKApplyLayoutToViewHierarchy(self);
|
||||
}
|
||||
|
||||
- (CGSize)intrinsicSize
|
||||
{
|
||||
const CGSize constrainedSize = {
|
||||
.width = YGUndefined,
|
||||
.height = YGUndefined,
|
||||
};
|
||||
return [self calculateLayoutWithSize:constrainedSize];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (CGSize)calculateLayoutWithSize:(CGSize)size
|
||||
{
|
||||
NSAssert([NSThread isMainThread], @"YG Layout calculation must be done on main.");
|
||||
NSAssert([self isEnabled], @"YG Layout is not enabled for this view.");
|
||||
|
||||
YKAttachNodesFromViewHierachy(self);
|
||||
|
||||
const YGNodeRef node = _node;
|
||||
YGNodeCalculateLayout(
|
||||
node,
|
||||
size.width,
|
||||
size.height,
|
||||
YGNodeStyleGetDirection(node));
|
||||
|
||||
return (CGSize) {
|
||||
.width = YGNodeLayoutGetWidth(node),
|
||||
.height = YGNodeLayoutGetHeight(node),
|
||||
};
|
||||
}
|
||||
|
||||
static YGSize YKMeasureView(
|
||||
YGNodeRef node,
|
||||
float width,
|
||||
YGMeasureMode widthMode,
|
||||
float height,
|
||||
YGMeasureMode heightMode)
|
||||
{
|
||||
const CGFloat constrainedWidth = (widthMode == YGMeasureModeUndefined) ? CGFLOAT_MAX : width;
|
||||
const CGFloat constrainedHeight = (heightMode == YGMeasureModeUndefined) ? CGFLOAT_MAX: height;
|
||||
|
||||
UIView *view = (__bridge UIView*) YGNodeGetContext(node);
|
||||
const CGSize sizeThatFits = [view sizeThatFits:(CGSize) {
|
||||
.width = constrainedWidth,
|
||||
.height = constrainedHeight,
|
||||
}];
|
||||
|
||||
return (YGSize) {
|
||||
.width = YKSanitizeMeasurement(constrainedWidth, sizeThatFits.width, widthMode),
|
||||
.height = YKSanitizeMeasurement(constrainedHeight, sizeThatFits.height, heightMode),
|
||||
};
|
||||
}
|
||||
|
||||
static CGFloat YKSanitizeMeasurement(
|
||||
CGFloat constrainedSize,
|
||||
CGFloat measuredSize,
|
||||
YGMeasureMode measureMode)
|
||||
{
|
||||
CGFloat result;
|
||||
if (measureMode == YGMeasureModeExactly) {
|
||||
result = constrainedSize;
|
||||
} else if (measureMode == YGMeasureModeAtMost) {
|
||||
result = MIN(constrainedSize, measuredSize);
|
||||
} else {
|
||||
result = measuredSize;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void YKAttachNodesFromViewHierachy(YKLayout *layout) {
|
||||
YGNodeRef node = layout.node;
|
||||
UIView *view = layout.view;
|
||||
|
||||
// Only leaf nodes should have a measure function
|
||||
if (![layout isEnabled] || view.subviews.count == 0) {
|
||||
YGNodeSetMeasureFunc(node, YKMeasureView);
|
||||
YKRemoveAllChildren(node);
|
||||
} else {
|
||||
YGNodeSetMeasureFunc(node, NULL);
|
||||
|
||||
// Create a list of all the subviews that we are going to use for layout.
|
||||
NSMutableArray<UIView *> *subviewsToInclude = [[NSMutableArray alloc] initWithCapacity:view.subviews.count];
|
||||
for (UIView *subview in view.subviews) {
|
||||
if (subview.layout.isIncluded) {
|
||||
[subviewsToInclude addObject:subview];
|
||||
}
|
||||
}
|
||||
|
||||
BOOL shouldReconstructChildList = NO;
|
||||
if (YGNodeGetChildCount(node) != subviewsToInclude.count) {
|
||||
shouldReconstructChildList = YES;
|
||||
} else {
|
||||
for (int i = 0; i < subviewsToInclude.count; i++) {
|
||||
if (YGNodeGetChild(node, i) != subviewsToInclude[i].layout.node) {
|
||||
shouldReconstructChildList = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldReconstructChildList) {
|
||||
YKRemoveAllChildren(node);
|
||||
|
||||
for (int i = 0 ; i < subviewsToInclude.count; i++) {
|
||||
UIView *const subview = subviewsToInclude[i];
|
||||
YGNodeInsertChild(node, subview.layout.node, i);
|
||||
YKAttachNodesFromViewHierachy(subview.layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void YKRemoveAllChildren(const YGNodeRef node)
|
||||
{
|
||||
if (node == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (YGNodeGetChildCount(node) > 0) {
|
||||
YGNodeRemoveChild(node, YGNodeGetChild(node, YGNodeGetChildCount(node) - 1));
|
||||
}
|
||||
}
|
||||
|
||||
static CGFloat YKRoundPixelValue(CGFloat value)
|
||||
{
|
||||
static CGFloat scale;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^(){
|
||||
scale = [UIScreen mainScreen].scale;
|
||||
});
|
||||
|
||||
return round(value * scale) / scale;
|
||||
}
|
||||
|
||||
static void YKApplyLayoutToViewHierarchy(YKLayout *layout) {
|
||||
NSCAssert([NSThread isMainThread], @"Framesetting should only be done on the main thread.");
|
||||
|
||||
if (!layout.isIncluded) {
|
||||
return;
|
||||
}
|
||||
|
||||
YGNodeRef node = layout.node;
|
||||
const CGPoint topLeft = {
|
||||
YGNodeLayoutGetLeft(node),
|
||||
YGNodeLayoutGetTop(node),
|
||||
};
|
||||
|
||||
const CGPoint bottomRight = {
|
||||
topLeft.x + YGNodeLayoutGetWidth(node),
|
||||
topLeft.y + YGNodeLayoutGetHeight(node),
|
||||
};
|
||||
|
||||
UIView *view = layout.view;
|
||||
view.frame = (CGRect) {
|
||||
.origin = {
|
||||
.x = YKRoundPixelValue(topLeft.x),
|
||||
.y = YKRoundPixelValue(topLeft.y),
|
||||
},
|
||||
.size = {
|
||||
.width = YKRoundPixelValue(bottomRight.x) - YKRoundPixelValue(topLeft.x),
|
||||
.height = YKRoundPixelValue(bottomRight.y) - YKRoundPixelValue(topLeft.y),
|
||||
},
|
||||
};
|
||||
|
||||
const BOOL isLeaf = !layout.isEnabled || view.subviews.count == 0;
|
||||
if (!isLeaf) {
|
||||
for (NSUInteger i = 0; i < view.subviews.count; i++) {
|
||||
YKApplyLayoutToViewHierarchy(view.subviews[i].layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@@ -25,6 +25,9 @@
|
||||
63EE08511E06EECB00EE5F9A /* UIView+YogaKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 13687D691DF8778F00E7C260 /* UIView+YogaKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
63EE08531E06F3D100EE5F9A /* YKEnums.h in Headers */ = {isa = PBXBuildFile; fileRef = 63EE08521E06F3D100EE5F9A /* YKEnums.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
63EE08551E072EF800EE5F9A /* SwiftViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63EE08541E072EF800EE5F9A /* SwiftViewController.swift */; };
|
||||
63EE08571E07590C00EE5F9A /* YKLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 63EE08561E07590C00EE5F9A /* YKLayout.m */; };
|
||||
63EE08591E07598A00EE5F9A /* YKLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 63EE08581E07591A00EE5F9A /* YKLayout.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
63EE085B1E075B0B00EE5F9A /* YKLayout+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 63EE085A1E075AAA00EE5F9A /* YKLayout+Private.h */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -74,6 +77,9 @@
|
||||
63EE08401E06ED3D00EE5F9A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
63EE08521E06F3D100EE5F9A /* YKEnums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YKEnums.h; path = ../../YKEnums.h; sourceTree = "<group>"; };
|
||||
63EE08541E072EF800EE5F9A /* SwiftViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftViewController.swift; sourceTree = "<group>"; };
|
||||
63EE08561E07590C00EE5F9A /* YKLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = YKLayout.m; path = ../../YKLayout.m; sourceTree = "<group>"; };
|
||||
63EE08581E07591A00EE5F9A /* YKLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = YKLayout.h; path = ../../YKLayout.h; sourceTree = "<group>"; };
|
||||
63EE085A1E075AAA00EE5F9A /* YKLayout+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "YKLayout+Private.h"; path = "../../YKLayout+Private.h"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -169,6 +175,9 @@
|
||||
63EE08521E06F3D100EE5F9A /* YKEnums.h */,
|
||||
13687D691DF8778F00E7C260 /* UIView+YogaKit.h */,
|
||||
13687D6A1DF8778F00E7C260 /* UIView+YogaKit.m */,
|
||||
63EE08581E07591A00EE5F9A /* YKLayout.h */,
|
||||
63EE085A1E075AAA00EE5F9A /* YKLayout+Private.h */,
|
||||
63EE08561E07590C00EE5F9A /* YKLayout.m */,
|
||||
63EE08401E06ED3D00EE5F9A /* Info.plist */,
|
||||
);
|
||||
path = YogaKit;
|
||||
@@ -181,6 +190,8 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
63EE085B1E075B0B00EE5F9A /* YKLayout+Private.h in Headers */,
|
||||
63EE08591E07598A00EE5F9A /* YKLayout.h in Headers */,
|
||||
63EE08411E06ED3D00EE5F9A /* YogaKit.h in Headers */,
|
||||
63EE08531E06F3D100EE5F9A /* YKEnums.h in Headers */,
|
||||
63EE08511E06EECB00EE5F9A /* UIView+YogaKit.h in Headers */,
|
||||
@@ -306,6 +317,7 @@
|
||||
63EE084A1E06EEB700EE5F9A /* YGNodeList.c in Sources */,
|
||||
63EE084B1E06EEB700EE5F9A /* Yoga.c in Sources */,
|
||||
63EE084C1E06EEB700EE5F9A /* UIView+YogaKit.m in Sources */,
|
||||
63EE08571E07590C00EE5F9A /* YKLayout.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
Binary file not shown.
@@ -13,17 +13,17 @@ class SwiftViewController : UIViewController {
|
||||
override func viewDidLoad() {
|
||||
let root = view!
|
||||
root.backgroundColor = .red
|
||||
root.usesYoga = true
|
||||
root.layoutWidth = view.bounds.size.width
|
||||
root.layoutHeight = view.bounds.size.height
|
||||
root.layoutAlignItems = .center
|
||||
root.layoutJustifyContent = .center
|
||||
root.layout.isEnabled = true
|
||||
root.layout.width = view.bounds.size.width
|
||||
root.layout.height = view.bounds.size.height
|
||||
root.layout.alignItems = .center
|
||||
root.layout.justifyContent = .center
|
||||
|
||||
let child1 = UIView()
|
||||
child1.backgroundColor = .blue
|
||||
child1.usesYoga = true
|
||||
child1.layoutWidth = 100
|
||||
child1.layoutHeight = 100
|
||||
child1.layout.isEnabled = true
|
||||
child1.layout.width = 100
|
||||
child1.layout.height = 100
|
||||
|
||||
let child2 = UIView()
|
||||
child2.backgroundColor = .green
|
||||
@@ -36,6 +36,6 @@ class SwiftViewController : UIViewController {
|
||||
child2.addSubview(child3)
|
||||
root.addSubview(child1)
|
||||
root.addSubview(child2)
|
||||
root.applyLayout()
|
||||
root.layout.apply()
|
||||
}
|
||||
}
|
||||
|
@@ -19,17 +19,17 @@
|
||||
{
|
||||
UIView *root = self.view;
|
||||
root.backgroundColor = [UIColor redColor];
|
||||
[root yk_setUsesYoga:YES];
|
||||
[root yk_setWidth:self.view.bounds.size.width];
|
||||
[root yk_setHeight:self.view.bounds.size.height];
|
||||
[root yk_setAlignItems:YKAlignCenter];
|
||||
[root yk_setJustifyContent:YKJustifyCenter];
|
||||
root.layout.isEnabled = YES;
|
||||
root.layout.width = self.view.bounds.size.width;
|
||||
root.layout.height = self.view.bounds.size.height;
|
||||
root.layout.alignItems = YKAlignCenter;
|
||||
root.layout.justifyContent = YKJustifyCenter;
|
||||
|
||||
UIView *child1 = [UIView new];
|
||||
child1.backgroundColor = [UIColor blueColor];
|
||||
[child1 yk_setUsesYoga:YES];
|
||||
[child1 yk_setWidth:100];
|
||||
[child1 yk_setHeight:100];
|
||||
child1.layout.isEnabled = YES;
|
||||
child1.layout.width = 100;
|
||||
child1.layout.height = 100;
|
||||
|
||||
UIView *child2 = [UIView new];
|
||||
child2.backgroundColor = [UIColor greenColor];
|
||||
@@ -52,7 +52,7 @@
|
||||
[child2 addSubview:child3];
|
||||
[root addSubview:child1];
|
||||
[root addSubview:child2];
|
||||
[root yk_applyLayout];
|
||||
[root.layout apply];
|
||||
}
|
||||
|
||||
|
||||
|
3
enums.py
3
enums.py
@@ -95,6 +95,7 @@ OBJC_ENUMS = {
|
||||
'LeftToRight',
|
||||
'RightToLeft',
|
||||
],
|
||||
'Edge': None,
|
||||
'MeasureMode': None,
|
||||
'PrintOptions': None,
|
||||
'Dimension': None,
|
||||
@@ -215,5 +216,5 @@ with open(root + '/YogaKit/YKEnums.h', 'w') as f:
|
||||
f.write(' YK%s%s = %d,\n' % (name, value[0], value[1]))
|
||||
else:
|
||||
f.write(' YK%s%s,\n' % (name, value))
|
||||
f.write('};\n')
|
||||
f.write('} NS_SWIFT_NAME(%s);\n' % name)
|
||||
f.write('\n')
|
||||
|
Reference in New Issue
Block a user