iOS: align DoricLayout to LinearLayout logic

This commit is contained in:
pengfei.zhou 2022-08-23 17:50:46 +08:00 committed by osborn
parent 060e821687
commit 95a16435f3
2 changed files with 102 additions and 16 deletions

View File

@ -108,6 +108,8 @@ typedef NS_ENUM(NSInteger, DoricGravity) {
@property(nonatomic, assign) CGFloat contentWidth; @property(nonatomic, assign) CGFloat contentWidth;
@property(nonatomic, assign) CGFloat contentHeight; @property(nonatomic, assign) CGFloat contentHeight;
@property(nonatomic, assign) CGFloat contentWeight;
- (instancetype)init; - (instancetype)init;
- (void)measure:(CGSize)targetSize; - (void)measure:(CGSize)targetSize;

View File

@ -137,6 +137,10 @@ - (void)measure:(CGSize)targetSize {
#pragma helper #pragma helper
- (BOOL)remeasuring {
return _remeasuring || [self.superLayout remeasuring];
}
- (BOOL)hasWidthWeight { - (BOOL)hasWidthWeight {
return self.inHLayout && self.weight > 0; return self.inHLayout && self.weight > 0;
} }
@ -212,6 +216,10 @@ - (BOOL)inHLayout {
return self.superLayout.layoutType == DoricHLayout; return self.superLayout.layoutType == DoricHLayout;
} }
- (BOOL)inStack {
return self.superLayout.layoutType == DoricStack;
}
- (CGFloat)takenWidth { - (CGFloat)takenWidth {
return self.measuredWidth + self.marginLeft + self.marginRight; return self.measuredWidth + self.marginLeft + self.marginRight;
} }
@ -287,17 +295,65 @@ - (CGFloat)addHeightPadding:(CGFloat)size {
} }
- (BOOL)needFitWidth { - (BOOL)needFitWidth {
return self.widthSpec == DoricLayoutFit if (self.widthSpec == DoricLayoutFit) {
|| (self.widthSpec == DoricLayoutMost && self.superLayout.needFitWidth return YES;
&& (!self.superLayout.remeasuring || self.inHLayout)) }
|| (self.widthSpec == DoricLayoutJust && self.hasWidthWeight); if (self.widthSpec == DoricLayoutJust) {
return self.hasWidthWeight;
}
if (self.widthSpec == DoricLayoutMost) {
if (self.superLayout.needFitWidth) {
if (!self.remeasuring) {
return YES;
}
if (self.inHLayout) {
if (self.superLayout.fitWidth) {
return YES;
}
if (!self.superLayout.inHLayout) {
return YES;
}
if (self.superLayout.superLayout.inStack) {
return YES;
}
if (self.superLayout.superLayout.superMostHeight) {
return YES;
}
}
}
}
return NO;
} }
- (BOOL)needFitHeight { - (BOOL)needFitHeight {
return self.heightSpec == DoricLayoutFit if (self.heightSpec == DoricLayoutFit) {
|| (self.heightSpec == DoricLayoutMost && self.superLayout.needFitHeight return YES;
&& (!self.superLayout.remeasuring || self.inVLayout)) }
|| (self.heightSpec == DoricLayoutJust && self.hasHeightWeight); if (self.heightSpec == DoricLayoutJust) {
return self.hasHeightWeight;
}
if (self.heightSpec == DoricLayoutMost) {
if (self.superLayout.needFitHeight) {
if (!self.remeasuring) {
return YES;
}
if (self.inVLayout) {
if (self.superLayout.fitHeight) {
return YES;
}
if (!self.superLayout.inVLayout) {
return YES;
}
if (self.superLayout.superLayout.inStack) {
return YES;
}
if (self.superLayout.superLayout.superMostWidth) {
return YES;
}
}
}
}
return NO;
} }
@ -555,10 +611,10 @@ - (void)measureVLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
had = YES; had = YES;
CGSize childRemaining = [layout removeMargin:CGSizeMake( CGSize childRemaining = [layout removeMargin:CGSizeMake(
remaining.width, remaining.width,
layout.hasHeightWeight ? remaining.height : remaining.height - contentHeight)]; (self.contentWeight > 0 || layout.hasHeightWeight) ? remaining.height : remaining.height - contentHeight)];
CGSize childLimit = [layout removeMargin:CGSizeMake( CGSize childLimit = [layout removeMargin:CGSizeMake(
limit.width, limit.width,
layout.hasHeightWeight ? limit.height : limit.height - contentHeight)]; (self.contentWeight > 0 || layout.hasHeightWeight) ? limit.height : limit.height - contentHeight)];
[layout measureSelf:childRemaining limitTo:childLimit]; [layout measureSelf:childRemaining limitTo:childLimit];
if (!(layout.mostWidth && self.fitWidth)) { if (!(layout.mostWidth && self.fitWidth)) {
existsContent = YES; existsContent = YES;
@ -567,6 +623,7 @@ - (void)measureVLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
contentHeight += layout.takenHeight + self.spacing; contentHeight += layout.takenHeight + self.spacing;
contentWeight += layout.weight; contentWeight += layout.weight;
} }
self.contentWeight = contentWeight;
if (!existsContent) { if (!existsContent) {
for (__kindof UIView *subview in self.view.subviews) { for (__kindof UIView *subview in self.view.subviews) {
DoricLayout *layout = subview.doricLayout; DoricLayout *layout = subview.doricLayout;
@ -579,7 +636,22 @@ - (void)measureVLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
if (had) { if (had) {
contentHeight -= self.spacing; contentHeight -= self.spacing;
} }
if (contentWeight > 0 && !self.fitHeight && !self.hasHeightWeight) { BOOL reassign = NO;
if (contentWeight > 0) {
if (self.needFitHeight && self.inVLayout) {
if (self.remeasuring) {
reassign = YES;
} else {
self.superLayout.needRemeasure = YES;
}
}
if (!self.needFitHeight && !self.hasHeightWeight) {
reassign = YES;
}
}
if (reassign) {
CGFloat extra = remaining.height - contentHeight; CGFloat extra = remaining.height - contentHeight;
contentWidth = 0; contentWidth = 0;
contentHeight = 0; contentHeight = 0;
@ -607,7 +679,6 @@ - (void)measureVLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
contentHeight -= self.spacing; contentHeight -= self.spacing;
} }
} }
self.contentWidth = contentWidth; self.contentWidth = contentWidth;
self.contentHeight = contentHeight; self.contentHeight = contentHeight;
@ -624,10 +695,10 @@ - (void)measureHLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
} }
had = YES; had = YES;
CGSize childRemaining = [layout removeMargin:CGSizeMake( CGSize childRemaining = [layout removeMargin:CGSizeMake(
layout.hasWidthWeight ? remaining.width : remaining.width - contentWidth, (self.contentWeight > 0 || layout.hasWidthWeight) ? remaining.width : remaining.width - contentWidth,
remaining.height)]; remaining.height)];
CGSize childLimit = [layout removeMargin:CGSizeMake( CGSize childLimit = [layout removeMargin:CGSizeMake(
layout.hasWidthWeight ? limit.width : limit.width - contentWidth, (self.contentWeight > 0 || layout.hasWidthWeight) ? limit.width : limit.width - contentWidth,
limit.height)]; limit.height)];
[layout measureSelf:childRemaining limitTo:childLimit]; [layout measureSelf:childRemaining limitTo:childLimit];
contentWidth += layout.takenWidth + self.spacing; contentWidth += layout.takenWidth + self.spacing;
@ -637,6 +708,7 @@ - (void)measureHLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
} }
contentWeight += layout.weight; contentWeight += layout.weight;
} }
self.contentWeight = contentWeight;
if (!existsContent) { if (!existsContent) {
for (__kindof UIView *subview in self.view.subviews) { for (__kindof UIView *subview in self.view.subviews) {
DoricLayout *layout = subview.doricLayout; DoricLayout *layout = subview.doricLayout;
@ -649,8 +721,20 @@ - (void)measureHLayoutContent:(CGSize)remaining limitTo:(CGSize)limit {
if (had) { if (had) {
contentWidth -= self.spacing; contentWidth -= self.spacing;
} }
BOOL reassign = NO;
if (contentWeight > 0 && !self.fitWidth) { if (contentWeight > 0) {
if (self.needFitWidth && self.inHLayout) {
if (self.remeasuring) {
reassign = YES;
} else {
self.superLayout.needRemeasure = YES;
}
}
if (!self.needFitWidth && !self.hasWidthWeight) {
reassign = YES;
}
}
if (reassign) {
CGFloat extra = remaining.width - contentWidth; CGFloat extra = remaining.width - contentWidth;
contentWidth = 0; contentWidth = 0;
contentHeight = 0; contentHeight = 0;