Skip to content

Commit

Permalink
Fabric: Improvements in RCTScrollViewComponentView
Browse files Browse the repository at this point in the history
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
  • Loading branch information
shergin authored and facebook-github-bot committed May 18, 2019
1 parent a982dec commit 64db98f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -28,11 +27,8 @@ @interface RCTScrollViewComponentView () <UIScrollViewDelegate>
@end

@implementation RCTScrollViewComponentView {
RCTEnhancedScrollView *_Nonnull _scrollView;
UIView *_Nonnull _contentView;
ScrollViewShadowNode::ConcreteState::Shared _state;
CGSize _contentSize;
RNGenericDelegateSplitter<id<UIScrollViewDelegate>> *_scrollViewDelegateSplitter;
}

- (instancetype)initWithFrame:(CGRect)frame
Expand All @@ -42,11 +38,11 @@ - (instancetype)initWithFrame:(CGRect)frame
_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;
Expand Down Expand Up @@ -79,7 +75,8 @@ - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps

#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.
Expand Down Expand Up @@ -122,18 +119,18 @@ - (void)updateState:(State::Shared)state oldState:(State::Shared)oldState
}

_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];
}

Expand Down

0 comments on commit 64db98f

Please sign in to comment.