iOS SwipeLayout
This commit is contained in:
parent
74cee4f91b
commit
deada07e8d
File diff suppressed because one or more lines are too long
@ -1,59 +1,34 @@
|
|||||||
import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, scroller } from "doric";
|
import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, scroller, layoutConfig } from "doric";
|
||||||
const colors = [
|
import { label } from "./utils";
|
||||||
"#f0932b",
|
|
||||||
"#eb4d4b",
|
|
||||||
"#6ab04c",
|
|
||||||
"#e056fd",
|
|
||||||
"#686de0",
|
|
||||||
"#30336b",
|
|
||||||
]
|
|
||||||
@Entry
|
@Entry
|
||||||
class ScrollerPanel extends Panel {
|
class ScrollerPanel extends Panel {
|
||||||
build(rootView: Group): void {
|
build(rootView: Group): void {
|
||||||
rootView.addChild(scroller(vlayout(
|
scroller(
|
||||||
[
|
vlayout([
|
||||||
// ...[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5].map(e => text({
|
scroller(
|
||||||
// text: colors[e % colors.length],
|
vlayout(new Array(100).fill(1).map(e => label('Scroll Content')))
|
||||||
// textColor: Color.parse('#ffffff'),
|
).apply({
|
||||||
// textSize: 20,
|
layoutConfig: layoutConfig().exactly(),
|
||||||
// bgColor: Color.parse(colors[e % colors.length]),
|
width: 300,
|
||||||
// layoutConfig: {
|
height: 500,
|
||||||
// widthSpec: LayoutSpec.EXACTLY,
|
bgColor: Color.RED,
|
||||||
// heightSpec: LayoutSpec.EXACTLY,
|
}),
|
||||||
// },
|
scroller(
|
||||||
// width: 200,
|
vlayout(new Array(100).fill(1).map(e => label('Scroll Content')))
|
||||||
// height: 50,
|
).apply({
|
||||||
// })),
|
layoutConfig: layoutConfig().exactly(),
|
||||||
...[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5].map(i => hlayout([
|
width: 300,
|
||||||
...[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5].map(j => text({
|
height: 500,
|
||||||
text: colors[(i + j) % colors.length],
|
bgColor: Color.BLUE,
|
||||||
textColor: Color.parse('#ffffff'),
|
})
|
||||||
textSize: 20,
|
])
|
||||||
bgColor: Color.parse(colors[(i + j) % colors.length]),
|
)
|
||||||
layoutConfig: {
|
.apply({
|
||||||
widthSpec: LayoutSpec.EXACTLY,
|
layoutConfig: layoutConfig().atmost().h(LayoutSpec.EXACTLY),
|
||||||
heightSpec: LayoutSpec.EXACTLY,
|
height: 500,
|
||||||
},
|
bgColor: Color.YELLOW,
|
||||||
width: 80,
|
})
|
||||||
height: 50,
|
.in(rootView)
|
||||||
})),
|
|
||||||
]).also(it => it.space = 20)),
|
|
||||||
hlayout([
|
|
||||||
...[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5].map(e => text({
|
|
||||||
text: colors[e % colors.length],
|
|
||||||
textColor: Color.parse('#ffffff'),
|
|
||||||
textSize: 20,
|
|
||||||
bgColor: Color.parse(colors[e % colors.length]),
|
|
||||||
layoutConfig: {
|
|
||||||
widthSpec: LayoutSpec.EXACTLY,
|
|
||||||
heightSpec: LayoutSpec.EXACTLY,
|
|
||||||
},
|
|
||||||
width: 200,
|
|
||||||
height: 50,
|
|
||||||
})),
|
|
||||||
]
|
|
||||||
),
|
|
||||||
]
|
|
||||||
).also(it => it.space = 20)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
2
demo/src/image_base64.ts
Normal file
2
demo/src/image_base64.ts
Normal file
File diff suppressed because one or more lines are too long
@ -37,6 +37,7 @@
|
|||||||
#import "DoricStoragePlugin.h"
|
#import "DoricStoragePlugin.h"
|
||||||
#import "DoricNavigatorPlugin.h"
|
#import "DoricNavigatorPlugin.h"
|
||||||
#import "DoricNavBarPlugin.h"
|
#import "DoricNavBarPlugin.h"
|
||||||
|
#import "DoricRefreshableNode.h"
|
||||||
|
|
||||||
@interface DoricRegistry ()
|
@interface DoricRegistry ()
|
||||||
|
|
||||||
@ -76,6 +77,7 @@ - (void)innerRegister {
|
|||||||
[self registerViewNode:DoricScrollerNode.class withName:@"Scroller"];
|
[self registerViewNode:DoricScrollerNode.class withName:@"Scroller"];
|
||||||
[self registerViewNode:DoricSliderNode.class withName:@"Slider"];
|
[self registerViewNode:DoricSliderNode.class withName:@"Slider"];
|
||||||
[self registerViewNode:DoricSlideItemNode.class withName:@"SlideItem"];
|
[self registerViewNode:DoricSlideItemNode.class withName:@"SlideItem"];
|
||||||
|
[self registerViewNode:DoricRefreshableNode.class withName:@"Refreshable"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)registerJSBundle:(NSString *)bundle withName:(NSString *)name {
|
- (void)registerJSBundle:(NSString *)bundle withName:(NSString *)name {
|
||||||
|
10
iOS/Pod/Classes/Refresh/DoricRefreshableNode.h
Normal file
10
iOS/Pod/Classes/Refresh/DoricRefreshableNode.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//
|
||||||
|
// Created by pengfei.zhou on 2019/11/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "DoricSuperNode.h"
|
||||||
|
#import "DoricSwipeRefreshLayout.h"
|
||||||
|
|
||||||
|
@interface DoricRefreshableNode : DoricSuperNode<DoricSwipeRefreshLayout *>
|
||||||
|
@end
|
128
iOS/Pod/Classes/Refresh/DoricRefreshableNode.m
Normal file
128
iOS/Pod/Classes/Refresh/DoricRefreshableNode.m
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
//
|
||||||
|
// Created by pengfei.zhou on 2019/11/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "DoricRefreshableNode.h"
|
||||||
|
#import "Doric.h"
|
||||||
|
|
||||||
|
@interface DoricRefreshableNode ()
|
||||||
|
@property(nonatomic, strong) DoricViewNode *contentNode;
|
||||||
|
@property(nonatomic, copy) NSString *contentViewId;
|
||||||
|
@property(nonatomic, strong) DoricViewNode *headerNode;
|
||||||
|
@property(nonatomic, copy) NSString *headerViewId;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation DoricRefreshableNode
|
||||||
|
- (DoricSwipeRefreshLayout *)build {
|
||||||
|
return [DoricSwipeRefreshLayout new];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)blendView:(DoricSwipeRefreshLayout *)view forPropName:(NSString *)name propValue:(id)prop {
|
||||||
|
if ([@"content" isEqualToString:name]) {
|
||||||
|
self.contentViewId = prop;
|
||||||
|
} else if ([@"header" isEqualToString:name]) {
|
||||||
|
self.headerViewId = prop;
|
||||||
|
} else if ([@"onRefresh" isEqualToString:name]) {
|
||||||
|
__weak typeof(self) _self = self;
|
||||||
|
NSString *funcId = prop;
|
||||||
|
self.view.onRefreshBlock = ^{
|
||||||
|
__strong typeof(_self) self = _self;
|
||||||
|
[self callJSResponse:funcId, nil];
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
[super blendView:view forPropName:name propValue:prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (DoricViewNode *)subNodeWithViewId:(NSString *)viewId {
|
||||||
|
if ([viewId isEqualToString:self.contentViewId]) {
|
||||||
|
return self.contentNode;
|
||||||
|
} else if ([viewId isEqualToString:self.headerViewId]) {
|
||||||
|
return self.headerNode;
|
||||||
|
} else {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)blend:(NSDictionary *)props {
|
||||||
|
[super blend:props];
|
||||||
|
[self blendHeader];
|
||||||
|
[self blendContent];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)blendContent {
|
||||||
|
NSDictionary *contentModel = [self subModelOf:self.contentViewId];
|
||||||
|
if (!contentModel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSString *viewId = contentModel[@"id"];
|
||||||
|
NSString *type = contentModel[@"type"];
|
||||||
|
NSDictionary *childProps = contentModel[@"props"];
|
||||||
|
if (self.contentNode) {
|
||||||
|
if ([self.contentNode.viewId isEqualToString:viewId]) {
|
||||||
|
//skip
|
||||||
|
} else {
|
||||||
|
if (self.reusable && [type isEqualToString:self.contentNode.type]) {
|
||||||
|
[self.contentNode also:^(DoricViewNode *it) {
|
||||||
|
it.viewId = viewId;
|
||||||
|
[it blend:childProps];
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
self.contentNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
||||||
|
it.viewId = viewId;
|
||||||
|
[it initWithSuperNode:self];
|
||||||
|
[it blend:childProps];
|
||||||
|
self.view.contentView = it.view;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.contentNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
||||||
|
it.viewId = viewId;
|
||||||
|
[it initWithSuperNode:self];
|
||||||
|
[it blend:childProps];
|
||||||
|
self.view.contentView = it.view;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)blendHeader {
|
||||||
|
NSDictionary *headerModel = [self subModelOf:self.headerViewId];
|
||||||
|
if (!headerModel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSString *viewId = headerModel[@"id"];
|
||||||
|
NSString *type = headerModel[@"type"];
|
||||||
|
NSDictionary *childProps = headerModel[@"props"];
|
||||||
|
if (self.headerNode) {
|
||||||
|
if ([self.headerNode.viewId isEqualToString:viewId]) {
|
||||||
|
//skip
|
||||||
|
} else {
|
||||||
|
if (self.reusable && [type isEqualToString:self.headerNode.type]) {
|
||||||
|
[self.headerNode also:^(DoricViewNode *it) {
|
||||||
|
it.viewId = viewId;
|
||||||
|
[it blend:childProps];
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
self.headerNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
||||||
|
it.viewId = viewId;
|
||||||
|
[it initWithSuperNode:self];
|
||||||
|
[it blend:childProps];
|
||||||
|
self.view.headerView = it.view;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.headerNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
||||||
|
it.viewId = viewId;
|
||||||
|
[it initWithSuperNode:self];
|
||||||
|
[it blend:childProps];
|
||||||
|
self.view.headerView = it.view;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)blendSubNode:(NSDictionary *)subModel {
|
||||||
|
[[self subNodeWithViewId:subModel[@"id"]] blend:subModel[@"props"]];
|
||||||
|
}
|
||||||
|
@end
|
22
iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.h
Normal file
22
iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by pengfei.zhou on 2019/11/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@protocol DoricSwipePullingDelegate <NSObject>
|
||||||
|
- (void)startAnimation;
|
||||||
|
|
||||||
|
- (void)stopAnimation;
|
||||||
|
|
||||||
|
- (void)setProgressRotation:(CGFloat)rotation;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface DoricSwipeRefreshLayout : UIScrollView
|
||||||
|
@property(nonatomic, strong) UIView *contentView;
|
||||||
|
@property(nonatomic, strong) UIView *headerView;
|
||||||
|
@property(nonatomic, assign) BOOL refreshable;
|
||||||
|
@property(nonatomic, assign) BOOL refreshing;
|
||||||
|
@property(nonatomic, strong) void (^onRefreshBlock)(void);
|
||||||
|
@property(nonatomic, weak) id <DoricSwipePullingDelegate> swipePullingDelegate;
|
||||||
|
@end
|
118
iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.m
Normal file
118
iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.m
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
//
|
||||||
|
// Created by pengfei.zhou on 2019/11/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "DoricSwipeRefreshLayout.h"
|
||||||
|
#import "UIView+Doric.h"
|
||||||
|
#import "DoricLayouts.h"
|
||||||
|
#import "Doric.h"
|
||||||
|
|
||||||
|
@interface DoricSwipeRefreshLayout () <UIScrollViewDelegate>
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation DoricSwipeRefreshLayout
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame {
|
||||||
|
if (self = [super initWithFrame:frame]) {
|
||||||
|
self.showsHorizontalScrollIndicator = NO;
|
||||||
|
self.showsVerticalScrollIndicator = NO;
|
||||||
|
self.delegate = self;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
if (self = [super init]) {
|
||||||
|
self.showsHorizontalScrollIndicator = NO;
|
||||||
|
self.showsVerticalScrollIndicator = NO;
|
||||||
|
self.delegate = self;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)sizeThatFits:(CGSize)size {
|
||||||
|
if (self.contentView) {
|
||||||
|
CGSize childSize = [self.contentView sizeThatFits:size];
|
||||||
|
return CGSizeMake(MIN(size.width, childSize.width), MIN(size.height, childSize.height));
|
||||||
|
}
|
||||||
|
return CGSizeZero;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setContentView:(UIView *)contentView {
|
||||||
|
if (_contentView) {
|
||||||
|
[_contentView removeFromSuperview];
|
||||||
|
}
|
||||||
|
_contentView = contentView;
|
||||||
|
[self addSubview:contentView];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setHeaderView:(UIView *)headerView {
|
||||||
|
if (_headerView) {
|
||||||
|
[_headerView removeFromSuperview];
|
||||||
|
}
|
||||||
|
_headerView = headerView;
|
||||||
|
[self addSubview:headerView];
|
||||||
|
self.refreshable = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)layoutSubviews {
|
||||||
|
[super layoutSubviews];
|
||||||
|
[self layoutSelf];
|
||||||
|
[self.contentView also:^(UIView *it) {
|
||||||
|
[it layoutSubviews];
|
||||||
|
it.x = it.y = 0;
|
||||||
|
}];
|
||||||
|
[self.headerView also:^(UIView *it) {
|
||||||
|
[it layoutSubviews];
|
||||||
|
it.bottom = it.centerX = 0;
|
||||||
|
}];
|
||||||
|
self.contentSize = self.frame.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
|
||||||
|
if (-scrollView.contentOffset.y >= self.headerView.height) {
|
||||||
|
self.refreshing = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
|
||||||
|
if (scrollView.contentOffset.y <= 0) {
|
||||||
|
[self.swipePullingDelegate setProgressRotation:-scrollView.contentOffset.y / self.headerView.height];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setRefreshing:(BOOL)refreshing {
|
||||||
|
if (_refreshing == refreshing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (refreshing) {
|
||||||
|
[UIView animateWithDuration:0.3f
|
||||||
|
animations:^{
|
||||||
|
self.contentInset = UIEdgeInsetsMake(self.headerView.height, 0, 0, 0);
|
||||||
|
}
|
||||||
|
completion:^(BOOL finished) {
|
||||||
|
[self.swipePullingDelegate startAnimation];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
[UIView animateWithDuration:0.3f
|
||||||
|
animations:^{
|
||||||
|
self.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
completion:^(BOOL finished) {
|
||||||
|
[self.swipePullingDelegate stopAnimation];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
_refreshing = refreshing;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setRefreshable:(BOOL)refreshable {
|
||||||
|
self.scrollEnabled = refreshable;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)refreshable {
|
||||||
|
return self.scrollEnabled;
|
||||||
|
}
|
||||||
|
@end
|
@ -94,4 +94,8 @@ typedef NS_ENUM(NSInteger, DoricGravity) {
|
|||||||
@property(nonatomic, copy) NSString *tagString;
|
@property(nonatomic, copy) NSString *tagString;
|
||||||
|
|
||||||
- (UIView *)viewWithTagString:(NSString *)tagString;
|
- (UIView *)viewWithTagString:(NSString *)tagString;
|
||||||
|
|
||||||
|
- (CGSize)targetLayoutSize;
|
||||||
|
|
||||||
|
- (void)layoutSelf;
|
||||||
@end
|
@end
|
||||||
|
@ -70,7 +70,7 @@ - (void)layoutSubviews {
|
|||||||
if ([self.superview isKindOfClass:[DoricLayoutContainer class]]) {
|
if ([self.superview isKindOfClass:[DoricLayoutContainer class]]) {
|
||||||
[self.superview layoutSubviews];
|
[self.superview layoutSubviews];
|
||||||
} else {
|
} else {
|
||||||
CGSize size = [self sizeThatFits:CGSizeMake(self.superview.width, self.superview.height)];
|
CGSize size = [self sizeThatFits:self.targetLayoutSize];
|
||||||
[self layout:size];
|
[self layout:size];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,6 +160,8 @@ - (CGSize)sizeContent:(CGSize)size {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)layout:(CGSize)targetSize {
|
- (void)layout:(CGSize)targetSize {
|
||||||
|
self.width = targetSize.width;
|
||||||
|
self.height = targetSize.height;
|
||||||
for (UIView *child in self.subviews) {
|
for (UIView *child in self.subviews) {
|
||||||
if (child.isHidden) {
|
if (child.isHidden) {
|
||||||
continue;
|
continue;
|
||||||
@ -223,8 +225,6 @@ - (void)layout:(CGSize)targetSize {
|
|||||||
[(DoricLayoutContainer *) child layout:size];
|
[(DoricLayoutContainer *) child layout:size];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.width = targetSize.width;
|
|
||||||
self.height = targetSize.height;
|
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@ -278,6 +278,8 @@ - (CGSize)sizeContent:(CGSize)size {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)layout:(CGSize)targetSize {
|
- (void)layout:(CGSize)targetSize {
|
||||||
|
self.width = targetSize.width;
|
||||||
|
self.height = targetSize.height;
|
||||||
CGFloat yStart = 0;
|
CGFloat yStart = 0;
|
||||||
if ((self.gravity & TOP) == TOP) {
|
if ((self.gravity & TOP) == TOP) {
|
||||||
yStart = 0;
|
yStart = 0;
|
||||||
@ -350,8 +352,6 @@ - (void)layout:(CGSize)targetSize {
|
|||||||
[(DoricLayoutContainer *) child layout:size];
|
[(DoricLayoutContainer *) child layout:size];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.width = targetSize.width;
|
|
||||||
self.height = targetSize.height;
|
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@ -403,6 +403,8 @@ - (CGSize)sizeContent:(CGSize)size {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)layout:(CGSize)targetSize {
|
- (void)layout:(CGSize)targetSize {
|
||||||
|
self.width = targetSize.width;
|
||||||
|
self.height = targetSize.height;
|
||||||
CGFloat xStart = 0;
|
CGFloat xStart = 0;
|
||||||
if (self.contentWeight) {
|
if (self.contentWeight) {
|
||||||
xStart = 0;
|
xStart = 0;
|
||||||
@ -477,8 +479,6 @@ - (void)layout:(CGSize)targetSize {
|
|||||||
[(DoricLayoutContainer *) child layout:size];
|
[(DoricLayoutContainer *) child layout:size];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.width = targetSize.width;
|
|
||||||
self.height = targetSize.height;
|
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@ -511,6 +511,33 @@ - (UIView *)viewWithTagString:(NSString *)tagString {
|
|||||||
return [self viewWithTag:[tagString hash]];
|
return [self viewWithTag:[tagString hash]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (CGSize)targetLayoutSize {
|
||||||
|
CGFloat width = self.width;
|
||||||
|
CGFloat height = self.height;
|
||||||
|
if (self.layoutConfig.widthSpec == DoricLayoutAtMost
|
||||||
|
|| self.layoutConfig.widthSpec == DoricLayoutWrapContent) {
|
||||||
|
width = self.superview.width;
|
||||||
|
}
|
||||||
|
if (self.layoutConfig.heightSpec == DoricLayoutAtMost
|
||||||
|
|| self.layoutConfig.widthSpec == DoricLayoutWrapContent) {
|
||||||
|
height = self.superview.height;
|
||||||
|
}
|
||||||
|
return CGSizeMake(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)layoutSelf {
|
||||||
|
CGSize contentSize = [self sizeThatFits:self.targetLayoutSize];
|
||||||
|
if (self.layoutConfig.widthSpec == DoricLayoutAtMost) {
|
||||||
|
self.width = self.superview.width;
|
||||||
|
} else if (self.layoutConfig.widthSpec == DoricLayoutWrapContent) {
|
||||||
|
self.width = contentSize.width;
|
||||||
|
}
|
||||||
|
if (self.layoutConfig.heightSpec == DoricLayoutAtMost) {
|
||||||
|
self.height = self.superview.height;
|
||||||
|
} else if (self.layoutConfig.heightSpec == DoricLayoutWrapContent) {
|
||||||
|
self.height = contentSize.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
DoricVLayoutView *vLayout(NSArray <__kindof UIView *> *views) {
|
DoricVLayoutView *vLayout(NSArray <__kindof UIView *> *views) {
|
||||||
|
@ -22,5 +22,9 @@
|
|||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "DoricSuperNode.h"
|
#import "DoricSuperNode.h"
|
||||||
|
|
||||||
@interface DoricScrollerNode : DoricSuperNode<UIScrollView *>
|
@interface DoricScrollView : UIScrollView
|
||||||
|
@property(nonatomic, strong) UIView *contentView;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface DoricScrollerNode : DoricSuperNode<DoricScrollView *>
|
||||||
@end
|
@end
|
@ -22,19 +22,25 @@
|
|||||||
#import "DoricScrollerNode.h"
|
#import "DoricScrollerNode.h"
|
||||||
#import "DoricExtensions.h"
|
#import "DoricExtensions.h"
|
||||||
|
|
||||||
@interface DoricScrollView : UIScrollView
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation DoricScrollView
|
@implementation DoricScrollView
|
||||||
|
|
||||||
|
- (void)setContentView:(UIView *)contentView {
|
||||||
|
if (_contentView) {
|
||||||
|
[_contentView removeFromSuperview];
|
||||||
|
}
|
||||||
|
_contentView = contentView;
|
||||||
|
[self addSubview:contentView];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)layoutSubviews {
|
- (void)layoutSubviews {
|
||||||
[super layoutSubviews];
|
[super layoutSubviews];
|
||||||
|
[self layoutSelf];
|
||||||
|
[self.contentView layoutSubviews];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGSize)sizeThatFits:(CGSize)size {
|
- (CGSize)sizeThatFits:(CGSize)size {
|
||||||
if (self.subviews.count > 0) {
|
if (self.contentView) {
|
||||||
UIView *child = self.subviews[0];
|
CGSize childSize = [self.contentView sizeThatFits:size];
|
||||||
CGSize childSize = [child sizeThatFits:size];
|
|
||||||
return CGSizeMake(MIN(size.width, childSize.width), MIN(size.height, childSize.height));
|
return CGSizeMake(MIN(size.width, childSize.width), MIN(size.height, childSize.height));
|
||||||
}
|
}
|
||||||
return CGSizeZero;
|
return CGSizeZero;
|
||||||
@ -47,7 +53,7 @@ @interface DoricScrollerNode ()
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation DoricScrollerNode
|
@implementation DoricScrollerNode
|
||||||
- (UIScrollView *)build {
|
- (DoricScrollView *)build {
|
||||||
return [DoricScrollView new];
|
return [DoricScrollView new];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,12 +76,11 @@ - (void)blend:(NSDictionary *)props {
|
|||||||
[it blend:childProps];
|
[it blend:childProps];
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
[self.childNode.view removeFromSuperview];
|
|
||||||
self.childNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
self.childNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
||||||
it.viewId = viewId;
|
it.viewId = viewId;
|
||||||
[it initWithSuperNode:self];
|
[it initWithSuperNode:self];
|
||||||
[it blend:childProps];
|
[it blend:childProps];
|
||||||
[self.view addSubview:it.view];
|
self.view.contentView = it.view;
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,13 +89,12 @@ - (void)blend:(NSDictionary *)props {
|
|||||||
it.viewId = viewId;
|
it.viewId = viewId;
|
||||||
[it initWithSuperNode:self];
|
[it initWithSuperNode:self];
|
||||||
[it blend:childProps];
|
[it blend:childProps];
|
||||||
[self.view addSubview:it.view];
|
self.view.contentView = it.view;
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
[self.view also:^(UIScrollView *it) {
|
[self.view also:^(DoricScrollView *it) {
|
||||||
if (it.subviews.count > 0) {
|
if (it.contentView) {
|
||||||
UIView *child = it.subviews[0];
|
CGSize size = [it.contentView sizeThatFits:it.frame.size];
|
||||||
CGSize size = [child sizeThatFits:it.frame.size];
|
|
||||||
[it setContentSize:size];
|
[it setContentSize:size];
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
Reference in New Issue
Block a user