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