Fabric: Improvements in RCTScrollViewComponentView

Summary:
This diff contains two changes:
* The actual UIScrollView is now mounted inside the component as `contentView` which mostly means that border-props will properly affect the layout of the scroll view (the scroll view will be laid out inside borders, not on top of those). And that also simplifies the code.
* Now the component view exposes the actual scroll view, its delegate splitter, and the container view defining a single interface for all possible integration that can be done with the Scroll View Component.

Reviewed By: mdvacca

Differential Revision: D15397283

fbshipit-source-id: 35e860b8bf55fbd4d0a5f4116f79e4507df79098
This commit is contained in:
Valentin Shergin
2019-05-17 19:59:10 -07:00
committed by Facebook Github Bot
parent a982decb84
commit 64db98febf
2 changed files with 33 additions and 13 deletions
@@ -8,14 +8,37 @@
#import <UIKit/UIKit.h>
#import <React/RCTViewComponentView.h>
#import <React/RNGenericDelegateSplitter.h>
NS_ASSUME_NONNULL_BEGIN
/**
/*
* UIView class for <ScrollView> component.
*
* By design, the class does not implement any logic that contradicts to the normal behavior of UIScrollView and does
* not contain any special/custom support for things like floating headers, pull-to-refresh components,
* keyboard-avoiding functionality and so on. All that complexity must be implemented inside those components in order
* to keep the complexity of this component manageable.
*/
@interface RCTScrollViewComponentView : RCTViewComponentView
/*
* Returns an actual UIScrollView that this component uses under the hood.
*/
@property (nonatomic, strong, readonly) UIScrollView *scrollView;
/*
* Returns the subview of the scroll view that the component uses to mount all subcomponents into. That's useful to
* separate component views from auxiliary views to be able to reliably implement pull-to-refresh- and RTL-related
* functionality.
*/
@property (nonatomic, strong, readonly) UIView *containerView;
/*
* Returns a delegate splitter that can be used to subscribe for UIScrollView delegate.
*/
@property (nonatomic, strong, readonly) RNGenericDelegateSplitter<id<UIScrollViewDelegate>> *scrollViewDelegateSplitter;
@end
NS_ASSUME_NONNULL_END
@@ -8,7 +8,6 @@
#import "RCTScrollViewComponentView.h"
#import <React/RCTAssert.h>
#import <React/RNGenericDelegateSplitter.h>
#import <react/components/scrollview/ScrollViewComponentDescriptor.h>
#import <react/components/scrollview/ScrollViewEventEmitter.h>
@@ -28,11 +27,8 @@ using namespace facebook::react;
@end
@implementation RCTScrollViewComponentView {
RCTEnhancedScrollView *_Nonnull _scrollView;
UIView *_Nonnull _contentView;
ScrollViewShadowNode::ConcreteState::Shared _state;
CGSize _contentSize;
RNGenericDelegateSplitter<id<UIScrollViewDelegate>> *_scrollViewDelegateSplitter;
}
- (instancetype)initWithFrame:(CGRect)frame
@@ -42,11 +38,11 @@ using namespace facebook::react;
_props = defaultProps;
_scrollView = [[RCTEnhancedScrollView alloc] initWithFrame:self.bounds];
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_scrollView.delaysContentTouches = NO;
_contentView = [[UIView alloc] initWithFrame:_scrollView.bounds];
[_scrollView addSubview:_contentView];
[self addSubview:_scrollView];
self.contentView = _scrollView;
_containerView = [[UIView alloc] initWithFrame:CGRectZero];
[_scrollView addSubview:_containerView];
_scrollViewDelegateSplitter = [[RNGenericDelegateSplitter alloc] initWithDelegateUpdateBlock:^(id delegate) {
self->_scrollView.delegate = delegate;
@@ -79,7 +75,8 @@ using namespace facebook::react;
#define REMAP_VIEW_PROP(reactName, localName) REMAP_PROP(reactName, localName, self)
#define MAP_VIEW_PROP(name) REMAP_VIEW_PROP(name, name)
#define REMAP_SCROLL_VIEW_PROP(reactName, localName) REMAP_PROP(reactName, localName, _scrollView)
#define REMAP_SCROLL_VIEW_PROP(reactName, localName) \
REMAP_PROP(reactName, localName, ((RCTEnhancedScrollView *)_scrollView))
#define MAP_SCROLL_VIEW_PROP(name) REMAP_SCROLL_VIEW_PROP(name, name)
// FIXME: Commented props are not supported yet.
@@ -122,18 +119,18 @@ using namespace facebook::react;
}
_contentSize = contentSize;
_contentView.frame = CGRect{CGPointZero, contentSize};
_containerView.frame = CGRect{CGPointZero, contentSize};
_scrollView.contentSize = contentSize;
}
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
{
[_contentView insertSubview:childComponentView atIndex:index];
[_containerView insertSubview:childComponentView atIndex:index];
}
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
{
RCTAssert(childComponentView.superview == _contentView, @"Attempt to unmount improperly mounted component view.");
RCTAssert(childComponentView.superview == _containerView, @"Attempt to unmount improperly mounted component view.");
[childComponentView removeFromSuperview];
}