iOS: refact layout fix when need fit on one dimension size change cannot cause another dimension size change
This commit is contained in:
parent
8d5350898a
commit
060e821687
@ -92,8 +92,8 @@ - (DoricLayout *)doricLayout {
|
||||
@end
|
||||
|
||||
@interface DoricLayout ()
|
||||
@property(nonatomic, assign) bool needRemeasure;
|
||||
@property(nonatomic, assign) bool remeasuring;
|
||||
@property(nonatomic, assign) BOOL needRemeasure;
|
||||
@property(nonatomic, assign) BOOL remeasuring;
|
||||
@end
|
||||
|
||||
@implementation DoricLayout
|
||||
@ -137,36 +137,36 @@ - (void)measure:(CGSize)targetSize {
|
||||
|
||||
#pragma helper
|
||||
|
||||
- (bool)hasWidthWeight {
|
||||
- (BOOL)hasWidthWeight {
|
||||
return self.inHLayout && self.weight > 0;
|
||||
}
|
||||
|
||||
- (bool)hasHeightWeight {
|
||||
- (BOOL)hasHeightWeight {
|
||||
return self.inVLayout && self.weight > 0;
|
||||
}
|
||||
|
||||
|
||||
- (bool)fitWidth {
|
||||
- (BOOL)fitWidth {
|
||||
return self.widthSpec == DoricLayoutFit;
|
||||
}
|
||||
|
||||
- (bool)fitHeight {
|
||||
- (BOOL)fitHeight {
|
||||
return self.heightSpec == DoricLayoutFit;
|
||||
}
|
||||
|
||||
- (bool)justWidth {
|
||||
- (BOOL)justWidth {
|
||||
return self.widthSpec == DoricLayoutJust;
|
||||
}
|
||||
|
||||
- (bool)justHeight {
|
||||
- (BOOL)justHeight {
|
||||
return self.heightSpec == DoricLayoutJust;
|
||||
}
|
||||
|
||||
- (bool)mostWidth {
|
||||
- (BOOL)mostWidth {
|
||||
return self.widthSpec == DoricLayoutMost;
|
||||
}
|
||||
|
||||
- (bool)mostHeight {
|
||||
- (BOOL)mostHeight {
|
||||
return self.heightSpec == DoricLayoutMost;
|
||||
}
|
||||
|
||||
@ -175,27 +175,27 @@ - (DoricLayout *)superLayout {
|
||||
}
|
||||
|
||||
|
||||
- (bool)superFitWidth {
|
||||
- (BOOL)superFitWidth {
|
||||
return self.superLayout.fitWidth;
|
||||
}
|
||||
|
||||
- (bool)superFitHeight {
|
||||
- (BOOL)superFitHeight {
|
||||
return self.superLayout.fitHeight;
|
||||
}
|
||||
|
||||
- (bool)superJustWidth {
|
||||
- (BOOL)superJustWidth {
|
||||
return self.superLayout.justWidth;
|
||||
}
|
||||
|
||||
- (bool)superJustHeight {
|
||||
- (BOOL)superJustHeight {
|
||||
return self.superLayout.justHeight;
|
||||
}
|
||||
|
||||
- (bool)superMostWidth {
|
||||
- (BOOL)superMostWidth {
|
||||
return self.superLayout.mostWidth;
|
||||
}
|
||||
|
||||
- (bool)superMostHeight {
|
||||
- (BOOL)superMostHeight {
|
||||
return self.superLayout.mostHeight;
|
||||
}
|
||||
|
||||
@ -286,14 +286,14 @@ - (CGFloat)addHeightPadding:(CGFloat)size {
|
||||
return size + self.paddingTop + self.paddingBottom;
|
||||
}
|
||||
|
||||
- (bool)needFitWidth {
|
||||
- (BOOL)needFitWidth {
|
||||
return self.widthSpec == DoricLayoutFit
|
||||
|| (self.widthSpec == DoricLayoutMost && self.superLayout.needFitWidth
|
||||
&& (!self.superLayout.remeasuring || self.inHLayout))
|
||||
|| (self.widthSpec == DoricLayoutJust && self.hasWidthWeight);
|
||||
}
|
||||
|
||||
- (bool)needFitHeight {
|
||||
- (BOOL)needFitHeight {
|
||||
return self.heightSpec == DoricLayoutFit
|
||||
|| (self.heightSpec == DoricLayoutMost && self.superLayout.needFitHeight
|
||||
&& (!self.superLayout.remeasuring || self.inVLayout))
|
||||
@ -374,22 +374,16 @@ - (void)measureSelf:(CGSize)remainingSize limitTo:(CGSize)limitSize {
|
||||
restrain:YES];
|
||||
}
|
||||
|
||||
- (void)measureSelf:(CGSize)remainingSize limitTo:(CGSize)limitSize restrain:(bool)needRestrain {
|
||||
- (void)measureSelf:(CGSize)remainingSize limitTo:(CGSize)limitSize restrain:(BOOL)needRestrain {
|
||||
self.needRemeasure = NO;
|
||||
self.remeasuring = NO;
|
||||
[self measureContent:[self removeSizePadding:remainingSize]
|
||||
limitTo:[self removeSizePadding:limitSize]];
|
||||
|
||||
if (self.needFitWidth) {
|
||||
if ([self.view isKindOfClass:[UIImageView class]]
|
||||
&& self.heightSpec != DoricLayoutFit && self.contentHeight > 0) {
|
||||
self.measuredWidth = self.contentWidth / self.contentHeight * self.measuredHeight
|
||||
+ self.paddingLeft + self.paddingRight;
|
||||
} else {
|
||||
self.measuredWidth = self.contentWidth
|
||||
+ self.paddingLeft + self.paddingRight
|
||||
+ (self.justWidth ? self.width : 0);
|
||||
}
|
||||
} else if (self.mostWidth) {
|
||||
self.measuredWidth = remainingSize.width;
|
||||
} else {
|
||||
@ -397,21 +391,26 @@ - (void)measureSelf:(CGSize)remainingSize limitTo:(CGSize)limitSize restrain:(bo
|
||||
}
|
||||
|
||||
if (self.needFitHeight) {
|
||||
if ([self.view isKindOfClass:[UIImageView class]]
|
||||
&& self.widthSpec != DoricLayoutFit && self.contentHeight > 0) {
|
||||
self.measuredHeight = self.contentHeight / self.contentWidth * self.measuredWidth
|
||||
+ self.paddingLeft + self.paddingRight;
|
||||
} else {
|
||||
self.measuredHeight = self.contentHeight
|
||||
+ self.paddingTop + self.paddingBottom
|
||||
+ (self.justHeight ? self.height : 0);
|
||||
}
|
||||
} else if (self.mostHeight) {
|
||||
self.measuredHeight = remainingSize.height;
|
||||
} else {
|
||||
self.measuredHeight = self.height;
|
||||
}
|
||||
|
||||
if ([self.view isKindOfClass:[UIImageView class]]) {
|
||||
if (self.needFitWidth && self.heightSpec != DoricLayoutFit && self.contentWidth > 0) {
|
||||
self.measuredWidth = self.contentWidth / self.contentHeight * self.measuredHeight
|
||||
+ self.paddingLeft + self.paddingRight;
|
||||
}
|
||||
if (self.needFitHeight && self.widthSpec != DoricLayoutFit && self.contentHeight > 0) {
|
||||
self.measuredHeight = self.contentHeight / self.contentWidth * self.measuredWidth
|
||||
+ self.paddingLeft + self.paddingRight;
|
||||
}
|
||||
}
|
||||
|
||||
if (needRestrain
|
||||
&& [self restrain:limitSize]
|
||||
&& self.layoutType != DoricUndefined
|
||||
@ -423,12 +422,44 @@ - (void)measureSelf:(CGSize)remainingSize limitTo:(CGSize)limitSize restrain:(bo
|
||||
}
|
||||
|
||||
if (self.needRemeasure) {
|
||||
CGSize size = [self removeSizePadding:CGSizeMake(
|
||||
self.measuredWidth,
|
||||
self.measuredHeight)];
|
||||
self.remeasuring = YES;
|
||||
[self measureContent:size
|
||||
limitTo:size];
|
||||
CGFloat width, limitWidth;
|
||||
width = limitWidth = [self removeWidthPadding:self.measuredWidth];
|
||||
CGFloat height, limitHeight;
|
||||
height = limitHeight = [self removeHeightPadding:self.measuredHeight];
|
||||
if (self.needFitWidth) {
|
||||
limitWidth = limitSize.width;
|
||||
}
|
||||
if (self.needFitHeight) {
|
||||
limitHeight = limitSize.height;
|
||||
}
|
||||
[self measureContent:CGSizeMake(width, height)
|
||||
limitTo:CGSizeMake(limitWidth, limitHeight)];
|
||||
|
||||
if (self.needFitWidth) {
|
||||
if ([self.view isKindOfClass:[UIImageView class]]
|
||||
&& self.heightSpec != DoricLayoutFit && self.contentHeight > 0) {
|
||||
self.measuredWidth = self.contentWidth / self.contentHeight * self.measuredHeight
|
||||
+ self.paddingLeft + self.paddingRight;
|
||||
} else {
|
||||
self.measuredWidth = self.contentWidth
|
||||
+ self.paddingLeft + self.paddingRight
|
||||
+ (self.justWidth ? self.width : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (self.needFitHeight) {
|
||||
if ([self.view isKindOfClass:[UIImageView class]]
|
||||
&& self.widthSpec != DoricLayoutFit && self.contentHeight > 0) {
|
||||
self.measuredHeight = self.contentHeight / self.contentWidth * self.measuredWidth
|
||||
+ self.paddingLeft + self.paddingRight;
|
||||
} else {
|
||||
self.measuredHeight = self.contentHeight
|
||||
+ self.paddingTop + self.paddingBottom
|
||||
+ (self.justHeight ? self.height : 0);
|
||||
}
|
||||
}
|
||||
|
||||
self.remeasuring = NO;
|
||||
}
|
||||
|
||||
@ -471,6 +502,7 @@ - (void)measureUndefinedContent:(CGSize)targetSize {
|
||||
|
||||
- (void)measureStackContent:(CGSize)remaining limitTo:(CGSize)limit {
|
||||
CGFloat contentWidth = 0, contentHeight = 0;
|
||||
BOOL existsWidthContent = NO, existsHeightContent = NO;
|
||||
for (__kindof UIView *subview in self.view.subviews) {
|
||||
DoricLayout *layout = subview.doricLayout;
|
||||
if (layout.disabled) {
|
||||
@ -479,10 +511,33 @@ - (void)measureStackContent:(CGSize)remaining limitTo:(CGSize)limit {
|
||||
CGSize childRemaining = [layout removeMargin:remaining];
|
||||
CGSize childLimit = [layout removeMargin:limit];
|
||||
[layout measureSelf:childRemaining limitTo:childLimit];
|
||||
if (!(layout.mostWidth && self.fitWidth)) {
|
||||
existsWidthContent = YES;
|
||||
contentWidth = MAX(contentWidth, layout.takenWidth);
|
||||
}
|
||||
if (!(layout.mostHeight && self.fitHeight)) {
|
||||
existsHeightContent = YES;
|
||||
contentHeight = MAX(contentHeight, layout.takenHeight);
|
||||
}
|
||||
|
||||
}
|
||||
if (!existsWidthContent) {
|
||||
for (__kindof UIView *subview in self.view.subviews) {
|
||||
DoricLayout *layout = subview.doricLayout;
|
||||
if (layout.disabled) {
|
||||
continue;
|
||||
}
|
||||
contentWidth = MAX(contentWidth, layout.takenWidth);
|
||||
}
|
||||
}
|
||||
if (!existsHeightContent) {
|
||||
for (__kindof UIView *subview in self.view.subviews) {
|
||||
DoricLayout *layout = subview.doricLayout;
|
||||
if (layout.disabled) {
|
||||
continue;
|
||||
}
|
||||
contentHeight = MAX(contentHeight, layout.takenHeight);
|
||||
}
|
||||
}
|
||||
self.contentWidth = contentWidth;
|
||||
|
||||
self.contentHeight = contentHeight;
|
||||
@ -491,6 +546,7 @@ - (void)measureStackContent:(CGSize)remaining limitTo:(CGSize)limit {
|
||||
- (void)measureVLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
|
||||
CGFloat contentWidth = 0, contentHeight = 0, contentWeight = 0;
|
||||
BOOL had = NO;
|
||||
BOOL existsContent = NO;
|
||||
for (__kindof UIView *subview in self.view.subviews) {
|
||||
DoricLayout *layout = subview.doricLayout;
|
||||
if (layout.disabled) {
|
||||
@ -504,12 +560,22 @@ - (void)measureVLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
|
||||
limit.width,
|
||||
layout.hasHeightWeight ? limit.height : limit.height - contentHeight)];
|
||||
[layout measureSelf:childRemaining limitTo:childLimit];
|
||||
|
||||
if (!(layout.mostWidth && self.fitWidth)) {
|
||||
existsContent = YES;
|
||||
contentWidth = MAX(contentWidth, layout.takenWidth);
|
||||
}
|
||||
contentHeight += layout.takenHeight + self.spacing;
|
||||
contentWeight += layout.weight;
|
||||
}
|
||||
|
||||
if (!existsContent) {
|
||||
for (__kindof UIView *subview in self.view.subviews) {
|
||||
DoricLayout *layout = subview.doricLayout;
|
||||
if (layout.disabled) {
|
||||
continue;
|
||||
}
|
||||
contentWidth = MAX(contentWidth, layout.takenWidth);
|
||||
}
|
||||
}
|
||||
if (had) {
|
||||
contentHeight -= self.spacing;
|
||||
}
|
||||
@ -532,7 +598,9 @@ - (void)measureVLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
|
||||
[layout removeWidthPadding:layout.measuredWidth],
|
||||
[layout removeHeightPadding:measuredHeight]);
|
||||
[layout measureContent:childRemaining limitTo:childRemaining];
|
||||
if (!(layout.mostWidth && self.fitWidth)) {
|
||||
contentWidth = MAX(contentWidth, layout.takenWidth);
|
||||
}
|
||||
contentHeight += layout.takenHeight + self.spacing;
|
||||
}
|
||||
if (had) {
|
||||
@ -548,6 +616,7 @@ - (void)measureVLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
|
||||
- (void)measureHLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
|
||||
CGFloat contentWidth = 0, contentHeight = 0, contentWeight = 0;;
|
||||
BOOL had = NO;
|
||||
BOOL existsContent = NO;
|
||||
for (__kindof UIView *subview in self.view.subviews) {
|
||||
DoricLayout *layout = subview.doricLayout;
|
||||
if (layout.disabled) {
|
||||
@ -562,10 +631,21 @@ - (void)measureHLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
|
||||
limit.height)];
|
||||
[layout measureSelf:childRemaining limitTo:childLimit];
|
||||
contentWidth += layout.takenWidth + self.spacing;
|
||||
if (!(layout.mostHeight && self.fitHeight)) {
|
||||
existsContent = YES;
|
||||
contentHeight = MAX(contentHeight, layout.takenHeight);
|
||||
}
|
||||
contentWeight += layout.weight;
|
||||
}
|
||||
|
||||
if (!existsContent) {
|
||||
for (__kindof UIView *subview in self.view.subviews) {
|
||||
DoricLayout *layout = subview.doricLayout;
|
||||
if (layout.disabled) {
|
||||
continue;
|
||||
}
|
||||
contentHeight = MAX(contentHeight, layout.takenHeight);
|
||||
}
|
||||
}
|
||||
if (had) {
|
||||
contentWidth -= self.spacing;
|
||||
}
|
||||
@ -589,8 +669,10 @@ - (void)measureHLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
|
||||
[layout removeHeightPadding:layout.measuredHeight]);
|
||||
[layout measureContent:childRemaining limitTo:childRemaining];
|
||||
contentWidth += layout.takenWidth + self.spacing;
|
||||
if (!(layout.mostHeight && self.fitHeight)) {
|
||||
contentHeight = MAX(contentHeight, layout.takenHeight);
|
||||
}
|
||||
}
|
||||
if (had) {
|
||||
contentWidth -= self.spacing;
|
||||
}
|
||||
|
Reference in New Issue
Block a user