iOS: Scroller support fit width or height
This commit is contained in:
		| @@ -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