iOS: Scroller support fit width or height
This commit is contained in:
parent
0c868f095d
commit
55efff976a
@ -26,12 +26,25 @@ typedef UIEdgeInsets DoricPadding;
|
|||||||
|
|
||||||
DoricMargin DoricMarginMake(CGFloat left, CGFloat top, CGFloat right, CGFloat bottom);
|
DoricMargin DoricMarginMake(CGFloat left, CGFloat top, CGFloat right, CGFloat bottom);
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, DoricMeasureSpecMode) {
|
||||||
|
DoricMeasureUnspecified = 0,
|
||||||
|
DoricMeasureExactly = 1,
|
||||||
|
DoricMeasureAtMost = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DoricMeasureSpec {
|
||||||
|
DoricMeasureSpecMode mode;
|
||||||
|
CGFloat size;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct DoricMeasureSpec DoricMeasureSpec;
|
||||||
|
|
||||||
typedef NS_ENUM(NSInteger, DoricLayoutType) {
|
typedef NS_ENUM(NSInteger, DoricLayoutType) {
|
||||||
DoricUndefined = 0,
|
DoricUndefined = 0,
|
||||||
DoricStack = 1,
|
DoricStack = 1,
|
||||||
DoricVLayout = 2,
|
DoricVLayout = 2,
|
||||||
DoricHLayout = 3,
|
DoricHLayout = 3,
|
||||||
|
DoricScroller = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NS_ENUM(NSInteger, DoricLayoutSpec) {
|
typedef NS_ENUM(NSInteger, DoricLayoutSpec) {
|
||||||
@ -121,3 +134,6 @@ typedef NS_ENUM(NSInteger, DoricGravity) {
|
|||||||
@property(nonatomic, strong) DoricLayout *doricLayout;
|
@property(nonatomic, strong) DoricLayout *doricLayout;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface DoricScrollView : UIScrollView
|
||||||
|
@property(nonatomic, strong) UIView *contentView;
|
||||||
|
@end
|
@ -91,19 +91,6 @@ - (DoricLayout *)doricLayout {
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
typedef NS_ENUM(NSInteger, DoricMeasureSpecMode) {
|
|
||||||
DoricMeasureUnspecified = 0,
|
|
||||||
DoricMeasureExactly = 1,
|
|
||||||
DoricMeasureAtMost = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DoricMeasureSpec {
|
|
||||||
DoricMeasureSpecMode mode;
|
|
||||||
CGFloat size;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct DoricMeasureSpec DoricMeasureSpec;
|
|
||||||
|
|
||||||
struct DoricSizeAndState {
|
struct DoricSizeAndState {
|
||||||
NSUInteger state;
|
NSUInteger state;
|
||||||
CGFloat size;
|
CGFloat size;
|
||||||
@ -181,7 +168,7 @@ - (DoricMeasureSpec)getRootMeasureSpec:(CGFloat)targetSize
|
|||||||
return DoricMeasureSpecMake(DoricMeasureExactly, targetSize);
|
return DoricMeasureSpecMake(DoricMeasureExactly, targetSize);
|
||||||
case DoricLayoutFit:
|
case DoricLayoutFit:
|
||||||
if ([self.view.superview isKindOfClass:UIScrollView.class]) {
|
if ([self.view.superview isKindOfClass:UIScrollView.class]) {
|
||||||
return DoricMeasureSpecMake(DoricMeasureAtMost, CGFLOAT_MAX);
|
return DoricMeasureSpecMake(DoricMeasureUnspecified, 0);
|
||||||
}
|
}
|
||||||
return DoricMeasureSpecMake(DoricMeasureAtMost, targetSize);
|
return DoricMeasureSpecMake(DoricMeasureAtMost, targetSize);
|
||||||
default:
|
default:
|
||||||
@ -481,6 +468,10 @@ - (void)measureWidth:(DoricMeasureSpec)widthSpec height:(DoricMeasureSpec)height
|
|||||||
[self horizontalMeasureWidth:widthSpec height:heightSpec];
|
[self horizontalMeasureWidth:widthSpec height:heightSpec];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DoricScroller: {
|
||||||
|
[self scrollerMeasureWidth:widthSpec height:heightSpec];
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
[self undefinedMeasureWidth:widthSpec height:heightSpec];
|
[self undefinedMeasureWidth:widthSpec height:heightSpec];
|
||||||
break;
|
break;
|
||||||
@ -1037,11 +1028,71 @@ - (void)stackMeasureWidth:(DoricMeasureSpec)widthMeasureSpec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)scrollerMeasureWidth:(DoricMeasureSpec)widthMeasureSpec
|
||||||
|
height:(DoricMeasureSpec)heightMeasureSpec {
|
||||||
|
DoricScrollView *scrollView = (DoricScrollView *) self.view;
|
||||||
|
DoricLayout *childLayout = scrollView.contentView.doricLayout;
|
||||||
|
|
||||||
|
[self measureChild:childLayout
|
||||||
|
widthSpec:widthMeasureSpec usedWidth:0
|
||||||
|
heightSpec:heightMeasureSpec usedHeight:0];
|
||||||
|
|
||||||
|
CGFloat maxWidth, maxHeight;
|
||||||
|
|
||||||
|
maxWidth = childLayout.measuredWidth
|
||||||
|
+ childLayout.marginLeft + childLayout.marginRight;
|
||||||
|
maxHeight = childLayout.measuredHeight
|
||||||
|
+ childLayout.marginTop + childLayout.marginBottom;
|
||||||
|
|
||||||
|
maxWidth += self.paddingLeft + self.paddingRight;
|
||||||
|
maxHeight += self.paddingTop + self.paddingBottom;
|
||||||
|
|
||||||
|
maxWidth = MAX(maxWidth, self.minWidth);
|
||||||
|
maxHeight = MAX(maxHeight, self.minHeight);
|
||||||
|
|
||||||
|
DoricSizeAndState widthSizeAndState = [self resolveSizeAndState:maxWidth
|
||||||
|
spec:widthMeasureSpec
|
||||||
|
childMeasuredState:0];
|
||||||
|
DoricSizeAndState heightSizeAndState = [self resolveSizeAndState:maxHeight
|
||||||
|
spec:heightMeasureSpec
|
||||||
|
childMeasuredState:0];
|
||||||
|
self.measuredWidth = widthSizeAndState.size;
|
||||||
|
self.measuredHeight = heightSizeAndState.size;
|
||||||
|
|
||||||
|
if (widthMeasureSpec.mode == DoricMeasureUnspecified
|
||||||
|
&& heightMeasureSpec.mode == DoricMeasureUnspecified) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGFloat width = self.measuredWidth - self.paddingLeft - self.paddingRight;
|
||||||
|
CGFloat height = self.measuredHeight - self.paddingTop - self.paddingBottom;
|
||||||
|
DoricMeasureSpec childWidthMeasureSpec, childHeightMeasureSpec;
|
||||||
|
if (childLayout.widthSpec == DoricLayoutMost) {
|
||||||
|
childWidthMeasureSpec = DoricMeasureSpecMake(DoricMeasureExactly, width);
|
||||||
|
} else {
|
||||||
|
widthMeasureSpec = DoricMeasureSpecMake(DoricMeasureUnspecified, 0);
|
||||||
|
childWidthMeasureSpec = [self getChildMeasureSpec:widthMeasureSpec
|
||||||
|
padding:self.paddingLeft + self.paddingRight
|
||||||
|
childLayoutSpec:childLayout.widthSpec
|
||||||
|
childSize:childLayout.width];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childLayout.heightSpec == DoricLayoutMost) {
|
||||||
|
childHeightMeasureSpec = DoricMeasureSpecMake(DoricMeasureExactly, height);
|
||||||
|
} else {
|
||||||
|
heightMeasureSpec = DoricMeasureSpecMake(DoricMeasureUnspecified, 0);
|
||||||
|
childHeightMeasureSpec = [self getChildMeasureSpec:heightMeasureSpec
|
||||||
|
padding:self.paddingTop + self.paddingBottom
|
||||||
|
childLayoutSpec:childLayout.heightSpec
|
||||||
|
childSize:childLayout.height];
|
||||||
|
}
|
||||||
|
[childLayout measureWidth:childWidthMeasureSpec height:childHeightMeasureSpec];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)undefinedMeasureWidth:(DoricMeasureSpec)widthMeasureSpec
|
- (void)undefinedMeasureWidth:(DoricMeasureSpec)widthMeasureSpec
|
||||||
height:(DoricMeasureSpec)heightMeasureSpec {
|
height:(DoricMeasureSpec)heightMeasureSpec {
|
||||||
CGSize targetSize = CGSizeMake(widthMeasureSpec.size - self.paddingLeft - self.paddingRight,
|
CGSize targetSize = CGSizeMake(widthMeasureSpec.size - self.paddingLeft - self.paddingRight,
|
||||||
heightMeasureSpec.size - self.paddingTop - self.paddingBottom);
|
heightMeasureSpec.size - self.paddingTop - self.paddingBottom);
|
||||||
//TODO should check this
|
|
||||||
CGSize measuredSize = [self.view sizeThatFits:targetSize];
|
CGSize measuredSize = [self.view sizeThatFits:targetSize];
|
||||||
|
|
||||||
CGFloat contentWidth = measuredSize.width;
|
CGFloat contentWidth = measuredSize.width;
|
||||||
@ -1107,6 +1158,10 @@ - (void)layout {
|
|||||||
[self layoutHLayout];
|
[self layoutHLayout];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DoricScroller: {
|
||||||
|
[self layoutScroller];
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1116,7 +1171,9 @@ - (void)layout {
|
|||||||
#pragma setFrame
|
#pragma setFrame
|
||||||
|
|
||||||
- (void)setFrame {
|
- (void)setFrame {
|
||||||
if (self.layoutType != DoricUndefined) {
|
if (self.layoutType == DoricScroller) {
|
||||||
|
[((DoricScrollView *) self.view).contentView.doricLayout setFrame];
|
||||||
|
} else if (self.layoutType != DoricUndefined) {
|
||||||
[self.view.subviews forEach:^(__kindof UIView *obj) {
|
[self.view.subviews forEach:^(__kindof UIView *obj) {
|
||||||
[obj.doricLayout setFrame];
|
[obj.doricLayout setFrame];
|
||||||
}];
|
}];
|
||||||
@ -1320,5 +1377,29 @@ - (void)layoutHLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)layoutScroller {
|
||||||
|
DoricScrollView *scrollView = (DoricScrollView *) self.view;
|
||||||
|
DoricLayout *layout = scrollView.contentView.doricLayout;
|
||||||
|
if (layout.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[layout layout];
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@implementation DoricScrollView
|
||||||
|
|
||||||
|
- (void)setContentView:(UIView *)contentView {
|
||||||
|
if (_contentView) {
|
||||||
|
[_contentView removeFromSuperview];
|
||||||
|
}
|
||||||
|
_contentView = contentView;
|
||||||
|
[self addSubview:contentView];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)layoutSubviews {
|
||||||
|
[super layoutSubviews];
|
||||||
|
self.contentSize = self.contentView.frame.size;
|
||||||
|
}
|
||||||
|
@end
|
@ -23,9 +23,5 @@
|
|||||||
#import "DoricSuperNode.h"
|
#import "DoricSuperNode.h"
|
||||||
#import "DoricScrollableProtocol.h"
|
#import "DoricScrollableProtocol.h"
|
||||||
|
|
||||||
@interface DoricScrollView : UIScrollView
|
|
||||||
@property(nonatomic, strong) UIView *contentView;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface DoricScrollerNode : DoricSuperNode<DoricScrollView *> <DoricScrollableProtocol>
|
@interface DoricScrollerNode : DoricSuperNode<DoricScrollView *> <DoricScrollableProtocol>
|
||||||
@end
|
@end
|
@ -25,34 +25,6 @@
|
|||||||
#import "DoricPromise.h"
|
#import "DoricPromise.h"
|
||||||
#import "DoricJSDispatcher.h"
|
#import "DoricJSDispatcher.h"
|
||||||
|
|
||||||
@implementation DoricScrollView
|
|
||||||
|
|
||||||
- (void)setContentView:(UIView *)contentView {
|
|
||||||
if (_contentView) {
|
|
||||||
[_contentView removeFromSuperview];
|
|
||||||
}
|
|
||||||
_contentView = contentView;
|
|
||||||
[self addSubview:contentView];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGSize)sizeThatFits:(CGSize)size {
|
|
||||||
if (self.contentView) {
|
|
||||||
if (!self.contentView.doricLayout.resolved) {
|
|
||||||
[self.contentView.doricLayout apply:size];
|
|
||||||
}
|
|
||||||
return CGSizeMake(
|
|
||||||
self.contentView.doricLayout.measuredWidth,
|
|
||||||
self.contentView.doricLayout.measuredHeight);
|
|
||||||
}
|
|
||||||
return CGSizeZero;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)layoutSubviews {
|
|
||||||
[super layoutSubviews];
|
|
||||||
self.contentSize = self.contentView.frame.size;
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface DoricScrollerNode () <UIScrollViewDelegate>
|
@interface DoricScrollerNode () <UIScrollViewDelegate>
|
||||||
@property(nonatomic, strong) DoricViewNode *childNode;
|
@property(nonatomic, strong) DoricViewNode *childNode;
|
||||||
@property(nonatomic, copy) NSString *childViewId;
|
@property(nonatomic, copy) NSString *childViewId;
|
||||||
@ -71,6 +43,7 @@ - (DoricScrollView *)build {
|
|||||||
if (@available(iOS 11, *)) {
|
if (@available(iOS 11, *)) {
|
||||||
it.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
it.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
||||||
}
|
}
|
||||||
|
it.doricLayout.layoutType = DoricScroller;
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +96,6 @@ - (void)afterBlended:(NSDictionary *)props {
|
|||||||
|
|
||||||
- (void)requestLayout {
|
- (void)requestLayout {
|
||||||
[self.childNode requestLayout];
|
[self.childNode requestLayout];
|
||||||
[self.view.contentView.doricLayout apply:self.view.frame.size];
|
|
||||||
[super requestLayout];
|
[super requestLayout];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user