Better support of UIKit layout stuff for RCTRootView an co.

Summary:
Now RCTRootView is much more reliable citizen of UIKit, it got:
 * Implemented `sizeThatFits:`;
 * Implemented `instrinsicContentSize`;
 * Notifying superview via `setNeedsLayout` about changed size.

All it make possible painless integration of ReactNative-powered widgets inside existing native apps.

Reviewed By: javache

Differential Revision: D4577890

fbshipit-source-id: 9897cb002c9d658a97fd436240c2ac947ba2084b
This commit is contained in:
Valentin Shergin 2017-02-27 10:47:27 -08:00 committed by Facebook Github Bot
parent b6ca952eeb
commit 9dccff0eda
1 changed files with 32 additions and 14 deletions

View File

@ -46,7 +46,6 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
NSString *_moduleName;
NSDictionary *_launchOptions;
RCTRootContentView *_contentView;
BOOL _passThroughTouches;
}
@ -60,8 +59,7 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[RCTRootView init]", nil);
if ((self = [super initWithFrame:CGRectZero])) {
if (self = [super initWithFrame:CGRectZero]) {
self.backgroundColor = [UIColor whiteColor];
_bridge = bridge;
@ -95,7 +93,7 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
#endif
if (!_bridge.loading) {
[self bundleFinishedLoading:[_bridge batchedBridge]];
[self bundleFinishedLoading:([_bridge batchedBridge] ?: _bridge)];
}
[self showLoadingView];
@ -137,6 +135,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
_contentView.backgroundColor = backgroundColor;
}
#pragma mark - passThroughTouches
- (BOOL)passThroughTouches
{
return _contentView.passThroughTouches;
@ -148,6 +148,26 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
_contentView.passThroughTouches = passThroughTouches;
}
#pragma mark - Layout
- (CGSize)sizeThatFits:(CGSize)size
{
return CGSizeMake(
_sizeFlexibility & RCTRootViewSizeFlexibilityWidth ? MIN(_intrinsicSize.width, size.width) : size.width,
_sizeFlexibility & RCTRootViewSizeFlexibilityHeight ? MIN(_intrinsicSize.height, size.height) : size.height
);
}
- (void)layoutSubviews
{
[super layoutSubviews];
_contentView.frame = self.bounds;
_loadingView.center = (CGPoint){
CGRectGetMidX(self.bounds),
CGRectGetMidY(self.bounds)
};
}
- (UIViewController *)reactViewController
{
return _reactViewController ?: [super reactViewController];
@ -278,16 +298,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
_contentView.sizeFlexibility = _sizeFlexibility;
}
- (void)layoutSubviews
{
[super layoutSubviews];
_contentView.frame = self.bounds;
_loadingView.center = (CGPoint){
CGRectGetMidX(self.bounds),
CGRectGetMidY(self.bounds)
};
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
// The root view itself should never receive touches
@ -323,6 +333,9 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
_intrinsicSize = intrinsicSize;
[self invalidateIntrinsicContentSize];
[self.superview setNeedsLayout];
// Don't notify the delegate if the content remains invisible or its size has not changed
if (bothSizesHaveAZeroDimension || sizesAreEqual) {
return;
@ -331,6 +344,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
[_delegate rootViewDidChangeIntrinsicSize:self];
}
- (CGSize)intrinsicContentSize
{
return _intrinsicSize;
}
- (void)contentViewInvalidated
{
[_contentView removeFromSuperview];