From c8365973f0b7bb9be8ee801bd8f256ef7d284a29 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Wed, 24 Aug 2022 16:09:31 +0800 Subject: [PATCH] iOS: DoricLayout add measureState --- doric-iOS/Pod/Classes/Shader/DoricLayouts.m | 277 ++++++++++++++------ 1 file changed, 198 insertions(+), 79 deletions(-) diff --git a/doric-iOS/Pod/Classes/Shader/DoricLayouts.m b/doric-iOS/Pod/Classes/Shader/DoricLayouts.m index c906ca37..1258a68b 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricLayouts.m +++ b/doric-iOS/Pod/Classes/Shader/DoricLayouts.m @@ -104,6 +104,13 @@ typedef NS_ENUM(NSInteger, DoricMeasureSpecMode) { typedef struct DoricMeasureSpec DoricMeasureSpec; +struct DoricSizeAndState { + NSUInteger state; + CGFloat size; +}; + +typedef struct DoricSizeAndState DoricSizeAndState; + DoricMeasureSpec DoricMeasureSpecMake(DoricMeasureSpecMode mode, CGFloat size) { DoricMeasureSpec spec; spec.mode = mode; @@ -111,7 +118,18 @@ DoricMeasureSpec DoricMeasureSpecMake(DoricMeasureSpecMode mode, CGFloat size) { return spec; } +NSUInteger DORIC_MEASURED_STATE_MASK = 0x11; + +NSUInteger DORIC_MEASURED_HEIGHT_STATE_SHIFT = 8; + +NSUInteger DORIC_MEASURED_STATE_TOO_SMALL = 0x01; + @interface DoricLayout () +/** + * width-height + * 0xff--ff + * */ +@property(nonatomic, assign) NSUInteger measuredState; @end @implementation DoricLayout @@ -123,6 +141,7 @@ - (instancetype)init { _maxHeight = CGFLOAT_MAX; _minWidth = -1; _minHeight = -1; + _measuredState = 0; } return self; } @@ -278,42 +297,50 @@ - (void)measureChild:(DoricLayout *)child heightSpec:(DoricMeasureSpec)heightSpec usedHeight:(CGFloat)usedHeight { - DoricMeasureSpec childWidthSpec = [self getChildMeasureSpec:widthSpec - padding:self.paddingLeft + self.paddingRight - + child.marginLeft + child.marginRight - + usedWidth - childLayoutSpec:child.widthSpec - childSize:child.width]; + DoricMeasureSpec childWidthSpec = + [self getChildMeasureSpec:widthSpec + padding:self.paddingLeft + self.paddingRight + + child.marginLeft + child.marginRight + + usedWidth + childLayoutSpec:child.widthSpec + childSize:child.width]; - DoricMeasureSpec childHeightSpec = [self getChildMeasureSpec:heightSpec - padding:self.paddingTop + self.paddingBottom - + child.marginTop + child.marginBottom - + usedHeight - childLayoutSpec:child.heightSpec - childSize:child.height]; + DoricMeasureSpec childHeightSpec = + [self getChildMeasureSpec:heightSpec + padding:self.paddingTop + self.paddingBottom + + child.marginTop + child.marginBottom + + usedHeight + childLayoutSpec:child.heightSpec + childSize:child.height]; [child measureWidth:childWidthSpec height:childHeightSpec]; } -- (CGFloat)resolveSize:(CGFloat)size spec:(DoricMeasureSpec)measureSpec { + +- (DoricSizeAndState)resolveSizeAndState:(CGFloat)size + spec:(DoricMeasureSpec)measureSpec + childMeasuredState:(NSUInteger)state { + DoricSizeAndState result; DoricMeasureSpecMode specMode = measureSpec.mode; CGFloat specSize = measureSpec.size; - CGFloat result; + result.state = 0; switch (specMode) { case DoricMeasureAtMost: if (specSize < size) { - result = specSize; + result.size = specSize; + result.state = DORIC_MEASURED_STATE_TOO_SMALL; } else { - result = size; + result.size = size; } break; case DoricMeasureExactly: - result = specSize; + result.size = specSize; break; case DoricMeasureUnspecified: default: - result = size; + result.size = size; break; } + result.state = result.state | (state & DORIC_MEASURED_STATE_MASK); return result; } @@ -334,7 +361,8 @@ - (CGFloat)getDefaultSize:(CGFloat)size spec:(DoricMeasureSpec)measureSpec { } - (void)forceUniformWidth:(DoricMeasureSpec)heightMeasureSpec { - DoricMeasureSpec uniformMeasureSpec = DoricMeasureSpecMake(DoricMeasureExactly, self.measuredWidth); + DoricMeasureSpec uniformMeasureSpec = DoricMeasureSpecMake(DoricMeasureExactly, + self.measuredWidth); for (__kindof UIView *subview in self.view.subviews) { DoricLayout *childLayout = subview.doricLayout; if (childLayout.disabled) { @@ -366,7 +394,8 @@ - (void)forceUniformHeight:(DoricMeasureSpec)widthMeasureSpec { // Pretend that the linear layout has an exact size. This is the measured height of // ourselves. The measured height should be the max height of the children, changed // to accommodate the heightMeasureSpec from the parent - DoricMeasureSpec uniformMeasureSpec = DoricMeasureSpecMake(DoricMeasureExactly, self.measuredHeight); + DoricMeasureSpec uniformMeasureSpec + = DoricMeasureSpecMake(DoricMeasureExactly, self.measuredHeight); for (__kindof UIView *subview in self.view.subviews) { DoricLayout *childLayout = subview.doricLayout; if (childLayout.disabled) { @@ -415,7 +444,8 @@ - (void)measureWidth:(DoricMeasureSpec)widthSpec height:(DoricMeasureSpec)height } } -- (void)verticalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMeasureSpec)heightMeasureSpec { +- (void)verticalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec + height:(DoricMeasureSpec)heightMeasureSpec { CGFloat maxWidth = 0, totalLength = 0; NSUInteger totalWeight = 0; BOOL hadExtraSpace = NO; @@ -429,7 +459,7 @@ - (void)verticalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMea CGFloat weightedMaxWidth = 0; CGFloat alternativeMaxWidth = 0; - + NSUInteger childState = 0; // See how tall everyone is. Also remember max width. for (__kindof UIView *subview in self.view.subviews) { @@ -448,7 +478,8 @@ - (void)verticalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMea // Optimization: don't bother measuring children who are going to use // leftover space. These views will get measured again down below if // there is any leftover space. - totalLength = MAX(totalLength, totalLength + childLayout.marginTop + childLayout.marginBottom); + totalLength = MAX(totalLength, totalLength + +childLayout.marginTop + childLayout.marginBottom); skippedMeasure = YES; } else { CGFloat oldHeight = CGFLOAT_MIN; @@ -497,15 +528,19 @@ - (void)verticalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMea CGFloat measuredWidth = childLayout.measuredWidth + margin; maxWidth = MAX(maxWidth, measuredWidth); + childState = childState | childLayout.measuredState; + allFillParent = allFillParent && childLayout.widthSpec == DoricLayoutMost; if (childLayout.weight > 0) { /* * Widths of weighted Views are bogus if we end up * remeasuring, so keep them separate. */ - weightedMaxWidth = MAX(weightedMaxWidth, matchWidthLocally ? margin : measuredWidth); + weightedMaxWidth + = MAX(weightedMaxWidth, matchWidthLocally ? margin : measuredWidth); } else { - alternativeMaxWidth = MAX(alternativeMaxWidth, matchWidthLocally ? margin : measuredWidth); + alternativeMaxWidth + = MAX(alternativeMaxWidth, matchWidthLocally ? margin : measuredWidth); } } @@ -521,7 +556,10 @@ - (void)verticalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMea heightSize = MAX(heightSize, self.minHeight); // Reconcile our calculated size with the heightMeasureSpec - heightSize = [self resolveSize:heightSize spec:heightMeasureSpec]; + DoricSizeAndState heightSizeAndState = [self resolveSizeAndState:heightSize + spec:heightMeasureSpec + childMeasuredState:0]; + heightSize = heightSizeAndState.size; // Either expand children with weight to take up available space or // shrink them if they extend beyond our current bounds. If we skipped @@ -541,11 +579,13 @@ - (void)verticalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMea CGFloat share = childExtra * delta / weightSum; weightSum -= childExtra; delta -= share; - DoricMeasureSpec childWidthMeasureSpec = [self getChildMeasureSpec:widthMeasureSpec - padding:self.paddingLeft + self.paddingRight - + childLayout.marginLeft + childLayout.marginRight - childLayoutSpec:childLayout.widthSpec - childSize:childLayout.width]; + DoricMeasureSpec childWidthMeasureSpec = + [self getChildMeasureSpec:widthMeasureSpec + padding:self.paddingLeft + self.paddingRight + + childLayout.marginLeft + + childLayout.marginRight + childLayoutSpec:childLayout.widthSpec + childSize:childLayout.width]; // TODO: Use a field like lp.isMeasured to figure out if this // child has been previously measured if (!(childLayout.heightSpec == DoricLayoutJust && childLayout.height == 0) @@ -557,13 +597,19 @@ - (void)verticalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMea childHeight = 0; } [childLayout measureWidth:childWidthMeasureSpec - height:DoricMeasureSpecMake(DoricMeasureExactly, childHeight)]; + height:DoricMeasureSpecMake(DoricMeasureExactly, + childHeight)]; } else { // child was skipped in the loop above. // Measure for this first time here [childLayout measureWidth:childWidthMeasureSpec - height:DoricMeasureSpecMake(DoricMeasureExactly, share > 0 ? share : 0)]; + height:DoricMeasureSpecMake(DoricMeasureExactly, + share > 0 ? share : 0)]; } + + // Child may now not fit in vertical dimension. + childState = childState | (childLayout.measuredState + & (DORIC_MEASURED_STATE_MASK >> DORIC_MEASURED_HEIGHT_STATE_SHIFT)); } @@ -571,9 +617,11 @@ - (void)verticalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMea CGFloat measuredWidth = childLayout.measuredWidth + margin; maxWidth = MAX(maxWidth, measuredWidth); - BOOL matchWidthLocally = widthMode != DoricMeasureExactly && childLayout.widthSpec == DoricLayoutMost; + BOOL matchWidthLocally = widthMode != DoricMeasureExactly + && childLayout.widthSpec == DoricLayoutMost; - alternativeMaxWidth = MAX(alternativeMaxWidth, matchWidthLocally ? margin : measuredWidth); + alternativeMaxWidth = MAX(alternativeMaxWidth, + matchWidthLocally ? margin : measuredWidth); allFillParent = allFillParent && childLayout.widthSpec == DoricLayoutMost; @@ -598,9 +646,16 @@ - (void)verticalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMea // Check against our minimum width maxWidth = MAX(maxWidth, self.minWidth); - self.measuredWidth = [self resolveSize:maxWidth spec:widthMeasureSpec]; + DoricSizeAndState widthSizeAndState = [self resolveSizeAndState:maxWidth + spec:widthMeasureSpec + childMeasuredState:childState]; + + self.measuredWidth = widthSizeAndState.size; + self.measuredHeight = heightSize; + self.measuredState = (widthSizeAndState.state + << DORIC_MEASURED_HEIGHT_STATE_SHIFT) | heightSizeAndState.state; if (matchWidth) { [self forceUniformWidth:heightMeasureSpec]; } @@ -608,11 +663,11 @@ - (void)verticalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMea } -- (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMeasureSpec)heightMeasureSpec { +- (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec + height:(DoricMeasureSpec)heightMeasureSpec { CGFloat maxHeight = 0, totalLength = 0; NSUInteger totalWeight = 0; BOOL hadExtraSpace = NO; - BOOL existsContent = NO; DoricMeasureSpecMode widthMode = widthMeasureSpec.mode; DoricMeasureSpecMode heightMode = heightMeasureSpec.mode; @@ -624,6 +679,9 @@ - (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricM CGFloat weightedMaxHeight = 0; CGFloat alternativeMaxHeight = 0; BOOL isExactly = widthMode == DoricMeasureExactly; + + NSUInteger childState = 0; + // See how wide everyone is. Also remember max height. for (__kindof UIView *subview in self.view.subviews) { DoricLayout *childLayout = subview.doricLayout; @@ -644,7 +702,8 @@ - (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricM if (isExactly) { totalLength += childLayout.marginLeft + childLayout.marginRight; } else { - totalLength = MAX(totalLength, totalLength + childLayout.marginLeft + childLayout.marginRight); + totalLength = MAX(totalLength, totalLength + +childLayout.marginLeft + childLayout.marginRight); } skippedMeasure = YES; } else { @@ -695,6 +754,9 @@ - (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricM CGFloat margin = childLayout.marginTop + childLayout.marginBottom; CGFloat childHeight = childLayout.measuredHeight + margin; + + childState = childState | childLayout.measuredState; + maxHeight = MAX(maxHeight, childHeight); allFillParent = allFillParent && childLayout.heightSpec == DoricLayoutMost; @@ -706,7 +768,8 @@ - (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricM */ weightedMaxHeight = MAX(weightedMaxHeight, matchHeightLocally ? margin : childHeight); } else { - alternativeMaxHeight = MAX(alternativeMaxHeight, matchHeightLocally ? margin : childHeight); + alternativeMaxHeight = MAX(alternativeMaxHeight, + matchHeightLocally ? margin : childHeight); } } @@ -722,7 +785,10 @@ - (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricM widthSize = MAX(widthSize, self.minWidth); // Reconcile our calculated size with the widthMeasureSpec - widthSize = [self resolveSize:widthSize spec:widthMeasureSpec]; + DoricSizeAndState widthSizeAndState = [self resolveSizeAndState:widthSize + spec:widthMeasureSpec + childMeasuredState:0]; + widthSize = widthSizeAndState.size; // Either expand children with weight to take up available space or // shrink them if they extend beyond our current bounds. If we skipped @@ -743,11 +809,13 @@ - (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricM weightSum -= childExtra; delta -= share; - DoricMeasureSpec childHeightMeasureSpec = [self getChildMeasureSpec:heightMeasureSpec - padding:self.paddingTop + self.paddingBottom - + childLayout.marginTop + childLayout.marginBottom - childLayoutSpec:childLayout.heightSpec - childSize:childLayout.height]; + DoricMeasureSpec childHeightMeasureSpec + = [self getChildMeasureSpec:heightMeasureSpec + padding:self.paddingTop + self.paddingBottom + + childLayout.marginTop + + childLayout.marginBottom + childLayoutSpec:childLayout.heightSpec + childSize:childLayout.height]; // TODO: Use a field like lp.isMeasured to figure out if this // child has been previously measured @@ -763,19 +831,24 @@ - (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricM height:childHeightMeasureSpec]; } else { // child was skipped in the loop above. Measure for this first time here - [childLayout measureWidth:DoricMeasureSpecMake(DoricMeasureExactly, share > 0 ? share : 0) + [childLayout measureWidth:DoricMeasureSpecMake(DoricMeasureExactly, + share > 0 ? share : 0) height:childHeightMeasureSpec]; } + // Child may now not fit in horizontal dimension. + childState = childState | (childLayout.measuredState & DORIC_MEASURED_STATE_MASK); } if (isExactly) { - totalLength += childLayout.measuredWidth + childLayout.marginLeft + childLayout.marginRight; + totalLength += childLayout.measuredWidth + + childLayout.marginLeft + childLayout.marginRight; } else { totalLength = MAX(totalLength, totalLength + childLayout.measuredWidth + childLayout.marginLeft + childLayout.marginRight); } totalLength += self.spacing; - BOOL matchHeightLocally = heightMode != DoricMeasureExactly && childLayout.heightSpec == DoricLayoutMost; + BOOL matchHeightLocally = heightMode != DoricMeasureExactly + && childLayout.heightSpec == DoricLayoutMost; CGFloat margin = childLayout.marginTop + childLayout.marginBottom; @@ -783,7 +856,8 @@ - (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricM maxHeight = MAX(maxHeight, childHeight); - alternativeMaxHeight = MAX(alternativeMaxHeight, matchHeightLocally ? margin : childHeight); + alternativeMaxHeight = MAX(alternativeMaxHeight, + matchHeightLocally ? margin : childHeight); allFillParent = allFillParent && childLayout.heightSpec == DoricLayoutMost; } @@ -809,7 +883,15 @@ - (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricM maxHeight = MAX(maxHeight, self.minHeight); self.measuredWidth = widthSize; - self.measuredHeight = [self resolveSize:maxHeight spec:heightMeasureSpec]; + DoricSizeAndState heightSizeAndState = [self resolveSizeAndState:maxHeight + spec:heightMeasureSpec + childMeasuredState:childState + << DORIC_MEASURED_HEIGHT_STATE_SHIFT]; + + self.measuredHeight = heightSizeAndState.size; + + self.measuredState = ((widthSizeAndState.state | (childState & DORIC_MEASURED_STATE_MASK)) + << DORIC_MEASURED_HEIGHT_STATE_SHIFT) | heightSizeAndState.state; if (matchHeight) { [self forceUniformHeight:widthMeasureSpec]; @@ -817,12 +899,14 @@ - (void)horizontalMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricM self.totalLength = totalLength; } -- (void)stackMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMeasureSpec)heightMeasureSpec { +- (void)stackMeasureWidth:(DoricMeasureSpec)widthMeasureSpec + height:(DoricMeasureSpec)heightMeasureSpec { CGFloat maxWidth = 0; CGFloat maxHeight = 0; BOOL measureMatchParentChildren = widthMeasureSpec.mode != DoricMeasureExactly || heightMeasureSpec.mode != DoricMeasureExactly; NSMutableArray *matchParentChildren = [NSMutableArray new]; + NSUInteger childState = 0; for (__kindof UIView *subview in self.view.subviews) { DoricLayout *childLayout = subview.doricLayout; if (childLayout.disabled) { @@ -831,10 +915,14 @@ - (void)stackMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMeasur [self measureChild:childLayout widthSpec:widthMeasureSpec usedWidth:0 heightSpec:heightMeasureSpec usedHeight:0]; - maxWidth = MAX(maxWidth, childLayout.measuredWidth + childLayout.marginLeft + childLayout.marginRight); - maxHeight = MAX(maxHeight, childLayout.measuredHeight + childLayout.marginTop + childLayout.marginBottom); + maxWidth = MAX(maxWidth, childLayout.measuredWidth + + childLayout.marginLeft + childLayout.marginRight); + maxHeight = MAX(maxHeight, childLayout.measuredHeight + + childLayout.marginTop + childLayout.marginBottom); + childState = childState | childLayout.measuredState; if (measureMatchParentChildren) { - if (childLayout.widthSpec == DoricLayoutMost || childLayout.heightSpec == DoricLayoutMost) { + if (childLayout.widthSpec == DoricLayoutMost + || childLayout.heightSpec == DoricLayoutMost) { [matchParentChildren addObject:childLayout]; } } @@ -848,46 +936,69 @@ - (void)stackMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMeasur maxWidth = MAX(maxWidth, self.minWidth); maxHeight = MAX(maxHeight, self.minHeight); - self.measuredWidth = [self resolveSize:maxWidth spec:widthMeasureSpec]; - self.measuredHeight = [self resolveSize:maxHeight spec:heightMeasureSpec]; + DoricSizeAndState widthSizeAndState = [self resolveSizeAndState:maxWidth + spec:widthMeasureSpec + childMeasuredState:childState]; + DoricSizeAndState heightSizeAndState = [self resolveSizeAndState:maxHeight + spec:heightMeasureSpec + childMeasuredState:childState + << DORIC_MEASURED_HEIGHT_STATE_SHIFT]; + self.measuredWidth = widthSizeAndState.size; + self.measuredHeight = heightSizeAndState.size; + + self.measuredState = (widthSizeAndState.state + << DORIC_MEASURED_HEIGHT_STATE_SHIFT) | heightSizeAndState.state; if (matchParentChildren.count > 1) { for (DoricLayout *child in matchParentChildren) { DoricMeasureSpec childWidthMeasureSpec; if (child.widthSpec == DoricLayoutMost) { - childWidthMeasureSpec.size = MAX(0, self.measuredWidth - self.paddingLeft - self.paddingRight - - child.marginLeft - child.marginRight); + childWidthMeasureSpec.size = MAX(0, + self.measuredWidth - self.paddingLeft - self.paddingRight + - child.marginLeft - child.marginRight); childWidthMeasureSpec.mode = DoricMeasureExactly; } else { - childWidthMeasureSpec = [self getChildMeasureSpec:widthMeasureSpec - padding:self.paddingLeft + self.paddingRight - + child.marginLeft + child.marginRight - childLayoutSpec:child.widthSpec - childSize:child.width]; + childWidthMeasureSpec + = [self getChildMeasureSpec:widthMeasureSpec + padding:self.paddingLeft + self.paddingRight + + child.marginLeft + child.marginRight + childLayoutSpec:child.widthSpec + childSize:child.width]; } DoricMeasureSpec childHeightMeasureSpec; if (child.heightSpec == DoricLayoutMost) { - childHeightMeasureSpec.size = MAX(0, self.measuredHeight - self.paddingTop - self.paddingBottom + childHeightMeasureSpec.size + = MAX(0, self.measuredHeight - self.paddingTop - self.paddingBottom - child.marginTop - child.marginBottom); childHeightMeasureSpec.mode = DoricMeasureExactly; } else { - childHeightMeasureSpec = [self getChildMeasureSpec:heightMeasureSpec - padding:self.paddingTop + self.paddingBottom - + child.marginTop + child.marginBottom - childLayoutSpec:child.heightSpec - childSize:child.height]; + childHeightMeasureSpec + = [self getChildMeasureSpec:heightMeasureSpec + padding:self.paddingTop + self.paddingBottom + + child.marginTop + child.marginBottom + childLayoutSpec:child.heightSpec + childSize:child.height]; } [child measureWidth:childWidthMeasureSpec height:childHeightMeasureSpec]; } } } -- (void)undefinedMeasureWidth:(DoricMeasureSpec)widthMeasureSpec height:(DoricMeasureSpec)heightMeasureSpec { +- (void)undefinedMeasureWidth:(DoricMeasureSpec)widthMeasureSpec + height:(DoricMeasureSpec)heightMeasureSpec { CGSize targetSize = CGSizeMake(widthMeasureSpec.size, heightMeasureSpec.size); //TODO should check this CGSize measuredSize = [self.view sizeThatFits:targetSize]; - self.measuredWidth = [self resolveSize:measuredSize.width spec:widthMeasureSpec]; - self.measuredHeight = [self resolveSize:measuredSize.height spec:heightMeasureSpec]; + DoricSizeAndState widthSizeAndState = [self resolveSizeAndState:measuredSize.width + spec:widthMeasureSpec + childMeasuredState:0]; + DoricSizeAndState heightSizeAndState = [self resolveSizeAndState:measuredSize.height + spec:heightMeasureSpec + childMeasuredState:0]; + self.measuredWidth = widthSizeAndState.size; + self.measuredHeight = heightSizeAndState.size; + self.measuredState = (widthSizeAndState.state + << DORIC_MEASURED_HEIGHT_STATE_SHIFT) | heightSizeAndState.state; } #pragma layout @@ -920,12 +1031,17 @@ - (void)setFrame { [obj.doricLayout setFrame]; }]; } - CGRect originFrame = CGRectMake(self.measuredX, self.measuredY, self.measuredWidth, self.measuredHeight); + CGRect originFrame = CGRectMake(self.measuredX, self.measuredY, + self.measuredWidth, self.measuredHeight); if (!CGAffineTransformEqualToTransform(self.view.transform, CGAffineTransformIdentity)) { CGPoint anchor = self.view.layer.anchorPoint; - originFrame = CGRectOffset(originFrame, -anchor.x * self.measuredWidth - self.measuredX, -anchor.y * self.measuredHeight - self.measuredY); + originFrame = CGRectOffset(originFrame, + -anchor.x * self.measuredWidth - self.measuredX, + -anchor.y * self.measuredHeight - self.measuredY); originFrame = CGRectApplyAffineTransform(originFrame, self.view.transform); - originFrame = CGRectOffset(originFrame, anchor.x * self.measuredWidth + self.measuredX, anchor.y * self.measuredHeight + self.measuredY); + originFrame = CGRectOffset(originFrame, + anchor.x * self.measuredWidth + self.measuredX, + anchor.y * self.measuredHeight + self.measuredY); } BOOL isFrameChange = ![self rect:originFrame equalTo:self.view.frame]; if (isFrameChange) { @@ -975,7 +1091,8 @@ - (void)configMaskWithLayer:(CAShapeLayer *)shapeLayer { lineLayer.path = path; lineLayer.fillColor = nil; [[self.view.layer sublayers] forEach:^(__kindof CALayer *obj) { - if ([obj isKindOfClass:CAShapeLayer.class] && ((CAShapeLayer *) obj).lineWidth > CGFLOAT_MIN) { + if ([obj isKindOfClass:CAShapeLayer.class] + && ((CAShapeLayer *) obj).lineWidth > CGFLOAT_MIN) { [obj removeFromSuperlayer]; } }]; @@ -1038,7 +1155,8 @@ - (void)layoutVLayout { } else if ((self.gravity & DoricGravityBottom) == DoricGravityBottom) { yStart = self.measuredHeight - self.totalLength - self.paddingBottom; } else if ((self.gravity & DoricGravityCenterY) == DoricGravityCenterY) { - yStart = (self.measuredHeight - self.totalLength - self.paddingTop - self.paddingBottom) / 2 + self.paddingTop; + yStart = (self.measuredHeight - self.totalLength + - self.paddingTop - self.paddingBottom) / 2 + self.paddingTop; } for (UIView *child in self.view.subviews) { DoricLayout *layout = child.doricLayout; @@ -1077,7 +1195,8 @@ - (void)layoutHLayout { } else if ((self.gravity & DoricGravityRight) == DoricGravityRight) { xStart = self.measuredWidth - self.totalLength - self.paddingRight; } else if ((self.gravity & DoricGravityCenterX) == DoricGravityCenterX) { - xStart = (self.measuredWidth - self.totalLength - self.paddingLeft - self.paddingRight) / 2 + self.paddingLeft; + xStart = (self.measuredWidth - self.totalLength + - self.paddingLeft - self.paddingRight) / 2 + self.paddingLeft; } for (UIView *child in self.view.subviews) { DoricLayout *layout = child.doricLayout;