Size flexibility modes for RCTRootView
Reviewed By: javache Differential Revision: D2526355 fb-gh-sync-id: 095a43bc01f883fdfdad3a086a35682c20c05597
This commit is contained in:
parent
3a92f2017f
commit
46803f0617
|
@ -87,11 +87,7 @@ function renderApplication<D, P, S>(
|
||||||
|
|
||||||
var styles = StyleSheet.create({
|
var styles = StyleSheet.create({
|
||||||
appContainer: {
|
appContainer: {
|
||||||
position: 'absolute',
|
flex: 1,
|
||||||
left: 0,
|
|
||||||
top: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,20 @@
|
||||||
|
|
||||||
#import "RCTBridge.h"
|
#import "RCTBridge.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This enum is used to define size flexibility type of the root view.
|
||||||
|
* If a dimension is flexible, the view will recalculate that dimension
|
||||||
|
* so the content fits. Recalculations are performed when the root's frame,
|
||||||
|
* size flexibility mode or content size changes. After a recalculation,
|
||||||
|
* TODO:<DelegateName> will be called with the new size passed as an argument.
|
||||||
|
*/
|
||||||
|
typedef NS_ENUM(NSInteger, RCTRootViewSizeFlexibility) {
|
||||||
|
RCTRootViewSizeFlexibilityNone = 0,
|
||||||
|
RCTRootViewSizeFlexibilityWidth,
|
||||||
|
RCTRootViewSizeFlexibilityHeight,
|
||||||
|
RCTRootViewSizeFlexibilityWidthAndHeight,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This notification is sent when the first subviews are added to the root view
|
* This notification is sent when the first subviews are added to the root view
|
||||||
* after the application has loaded. This is used to hide the `loadingView`, and
|
* after the application has loaded. This is used to hide the `loadingView`, and
|
||||||
|
@ -71,6 +85,11 @@ extern NSString *const RCTContentDidAppearNotification;
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, strong) Class executorClass;
|
@property (nonatomic, strong) Class executorClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size flexibility mode of the root view.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) RCTRootViewSizeFlexibility sizeFlexibility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The backing view controller of the root view.
|
* The backing view controller of the root view.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -72,6 +72,7 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
|
||||||
_initialProperties = [initialProperties copy];
|
_initialProperties = [initialProperties copy];
|
||||||
_loadingViewFadeDelay = 0.25;
|
_loadingViewFadeDelay = 0.25;
|
||||||
_loadingViewFadeDuration = 0.25;
|
_loadingViewFadeDuration = 0.25;
|
||||||
|
_sizeFlexibility = RCTRootViewSizeFlexibilityNone;
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
selector:@selector(javaScriptDidLoad:)
|
selector:@selector(javaScriptDidLoad:)
|
||||||
|
@ -189,6 +190,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||||
args:@[moduleName, appParameters]];
|
args:@[moduleName, appParameters]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setSizeFlexibility:(RCTRootViewSizeFlexibility)sizeFlexibility
|
||||||
|
{
|
||||||
|
_sizeFlexibility = sizeFlexibility;
|
||||||
|
[self setNeedsLayout];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)layoutSubviews
|
- (void)layoutSubviews
|
||||||
{
|
{
|
||||||
[super layoutSubviews];
|
[super layoutSubviews];
|
||||||
|
|
|
@ -347,11 +347,26 @@ extern NSString *RCTBridgeModuleNameForClass(Class cls);
|
||||||
{
|
{
|
||||||
RCTAssertMainThread();
|
RCTAssertMainThread();
|
||||||
|
|
||||||
|
// The following variables have no meaning if the view is not a react root view
|
||||||
|
RCTRootView *rootView = (RCTRootView *)[view superview];
|
||||||
|
RCTRootViewSizeFlexibility sizeFlexibility = rootView != nil ? rootView.sizeFlexibility : RCTRootViewSizeFlexibilityNone;
|
||||||
|
|
||||||
NSNumber *reactTag = view.reactTag;
|
NSNumber *reactTag = view.reactTag;
|
||||||
dispatch_async(_shadowQueue, ^{
|
dispatch_async(_shadowQueue, ^{
|
||||||
RCTShadowView *rootShadowView = _shadowViewRegistry[reactTag];
|
RCTShadowView *rootShadowView = _shadowViewRegistry[reactTag];
|
||||||
RCTAssert(rootShadowView != nil, @"Could not locate root view with tag #%@", reactTag);
|
RCTAssert(rootShadowView != nil, @"Could not locate root view with tag #%@", reactTag);
|
||||||
|
|
||||||
|
if (RCTIsReactRootView(reactTag)) {
|
||||||
|
if (CGRectEqualToRect(frame, rootShadowView.frame) && rootShadowView.sizeFlexibility == sizeFlexibility) {
|
||||||
|
// This is to prevent infinite recursion when the frame update is trigerred by TODO(8608567):<DelegateName>
|
||||||
|
return;
|
||||||
|
}
|
||||||
rootShadowView.frame = frame;
|
rootShadowView.frame = frame;
|
||||||
|
rootShadowView.sizeFlexibility = sizeFlexibility;
|
||||||
|
} else {
|
||||||
|
rootShadowView.frame = frame;
|
||||||
|
}
|
||||||
|
|
||||||
[rootShadowView updateLayout];
|
[rootShadowView updateLayout];
|
||||||
|
|
||||||
[self batchDidComplete];
|
[self batchDidComplete];
|
||||||
|
@ -437,8 +452,7 @@ extern NSString *RCTBridgeModuleNameForClass(Class cls);
|
||||||
// these structures in the UI-thread block. `NSMutableArray` is not thread
|
// these structures in the UI-thread block. `NSMutableArray` is not thread
|
||||||
// safe so we rely on the fact that we never mutate it after it's passed to
|
// safe so we rely on the fact that we never mutate it after it's passed to
|
||||||
// the main thread.
|
// the main thread.
|
||||||
[rootShadowView collectRootUpdatedFrames:viewsWithNewFrames
|
[rootShadowView collectRootUpdatedFrames:viewsWithNewFrames];
|
||||||
parentConstraint:(CGSize){CSS_UNDEFINED, CSS_UNDEFINED}];
|
|
||||||
|
|
||||||
// Parallel arrays are built and then handed off to main thread
|
// Parallel arrays are built and then handed off to main thread
|
||||||
NSMutableArray *frameReactTags = [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count];
|
NSMutableArray *frameReactTags = [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count];
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#import "Layout.h"
|
#import "Layout.h"
|
||||||
#import "RCTComponent.h"
|
#import "RCTComponent.h"
|
||||||
|
#import "RCTRootView.h"
|
||||||
|
|
||||||
@class RCTSparseArray;
|
@class RCTSparseArray;
|
||||||
|
|
||||||
|
@ -64,6 +65,12 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *viewRegistry);
|
||||||
- (void)setTopLeft:(CGPoint)topLeft;
|
- (void)setTopLeft:(CGPoint)topLeft;
|
||||||
- (void)setSize:(CGSize)size;
|
- (void)setSize:(CGSize)size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size flexibility type used to find size constraints.
|
||||||
|
* Default to RCTRootViewSizeFlexibilityNone
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) RCTRootViewSizeFlexibility sizeFlexibility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Border. Defaults to { 0, 0, 0, 0 }.
|
* Border. Defaults to { 0, 0, 0, 0 }.
|
||||||
*/
|
*/
|
||||||
|
@ -127,8 +134,7 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *viewRegistry);
|
||||||
* Calculate all views whose frame needs updating after layout has been calculated.
|
* Calculate all views whose frame needs updating after layout has been calculated.
|
||||||
* The viewsWithNewFrame set contains the reactTags of the views that need updating.
|
* The viewsWithNewFrame set contains the reactTags of the views that need updating.
|
||||||
*/
|
*/
|
||||||
- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame
|
- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame;
|
||||||
parentConstraint:(CGSize)parentConstraint;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively apply layout to children.
|
* Recursively apply layout to children.
|
||||||
|
|
|
@ -215,9 +215,32 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame
|
|
||||||
parentConstraint:(__unused CGSize)parentConstraint
|
- (void)applySizeConstraints
|
||||||
{
|
{
|
||||||
|
switch (_sizeFlexibility) {
|
||||||
|
case RCTRootViewSizeFlexibilityNone:
|
||||||
|
break;
|
||||||
|
case RCTRootViewSizeFlexibilityWidth:
|
||||||
|
_cssNode->style.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
|
||||||
|
break;
|
||||||
|
case RCTRootViewSizeFlexibilityHeight:
|
||||||
|
_cssNode->style.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
|
||||||
|
break;
|
||||||
|
case RCTRootViewSizeFlexibilityWidthAndHeight:
|
||||||
|
_cssNode->style.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
|
||||||
|
_cssNode->style.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame
|
||||||
|
{
|
||||||
|
RCTAssert(RCTIsReactRootView(self.reactTag),
|
||||||
|
@"The method has been called on a view with react tag %@, which is not a root view", self.reactTag);
|
||||||
|
|
||||||
|
[self applySizeConstraints];
|
||||||
|
|
||||||
[self fillCSSNode:_cssNode];
|
[self fillCSSNode:_cssNode];
|
||||||
layoutNode(_cssNode, CSS_UNDEFINED, CSS_DIRECTION_INHERIT);
|
layoutNode(_cssNode, CSS_UNDEFINED, CSS_DIRECTION_INHERIT);
|
||||||
[self applyLayoutNode:_cssNode viewsWithNewFrame:viewsWithNewFrame absolutePosition:CGPointZero];
|
[self applyLayoutNode:_cssNode viewsWithNewFrame:viewsWithNewFrame absolutePosition:CGPointZero];
|
||||||
|
@ -245,6 +268,7 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
|
|
||||||
_frame = CGRectMake(0, 0, CSS_UNDEFINED, CSS_UNDEFINED);
|
_frame = CGRectMake(0, 0, CSS_UNDEFINED, CSS_UNDEFINED);
|
||||||
|
_sizeFlexibility = RCTRootViewSizeFlexibilityNone;
|
||||||
|
|
||||||
for (unsigned int ii = 0; ii < META_PROP_COUNT; ii++) {
|
for (unsigned int ii = 0; ii < META_PROP_COUNT; ii++) {
|
||||||
_paddingMetaProps[ii] = CSS_UNDEFINED;
|
_paddingMetaProps[ii] = CSS_UNDEFINED;
|
||||||
|
|
Loading…
Reference in New Issue