Size flexibility modes for RCTRootView

Reviewed By: javache

Differential Revision: D2526355

fb-gh-sync-id: 095a43bc01f883fdfdad3a086a35682c20c05597
This commit is contained in:
Pawel Sienkowski 2015-10-26 15:39:04 -07:00 committed by facebook-github-bot-7
parent 3a92f2017f
commit 46803f0617
6 changed files with 78 additions and 12 deletions

View File

@ -87,11 +87,7 @@ function renderApplication<D, P, S>(
var styles = StyleSheet.create({
appContainer: {
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0,
flex: 1,
},
});

View File

@ -11,6 +11,20 @@
#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
* 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;
/**
* The size flexibility mode of the root view.
*/
@property (nonatomic, assign) RCTRootViewSizeFlexibility sizeFlexibility;
/**
* The backing view controller of the root view.
*/

View File

@ -72,6 +72,7 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
_initialProperties = [initialProperties copy];
_loadingViewFadeDelay = 0.25;
_loadingViewFadeDuration = 0.25;
_sizeFlexibility = RCTRootViewSizeFlexibilityNone;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(javaScriptDidLoad:)
@ -189,6 +190,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
args:@[moduleName, appParameters]];
}
- (void)setSizeFlexibility:(RCTRootViewSizeFlexibility)sizeFlexibility
{
_sizeFlexibility = sizeFlexibility;
[self setNeedsLayout];
}
- (void)layoutSubviews
{
[super layoutSubviews];

View File

@ -347,11 +347,26 @@ extern NSString *RCTBridgeModuleNameForClass(Class cls);
{
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;
dispatch_async(_shadowQueue, ^{
RCTShadowView *rootShadowView = _shadowViewRegistry[reactTag];
RCTAssert(rootShadowView != nil, @"Could not locate root view with tag #%@", reactTag);
rootShadowView.frame = frame;
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.sizeFlexibility = sizeFlexibility;
} else {
rootShadowView.frame = frame;
}
[rootShadowView updateLayout];
[self batchDidComplete];
@ -437,8 +452,7 @@ extern NSString *RCTBridgeModuleNameForClass(Class cls);
// 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
// the main thread.
[rootShadowView collectRootUpdatedFrames:viewsWithNewFrames
parentConstraint:(CGSize){CSS_UNDEFINED, CSS_UNDEFINED}];
[rootShadowView collectRootUpdatedFrames:viewsWithNewFrames];
// Parallel arrays are built and then handed off to main thread
NSMutableArray *frameReactTags = [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count];

View File

@ -11,6 +11,7 @@
#import "Layout.h"
#import "RCTComponent.h"
#import "RCTRootView.h"
@class RCTSparseArray;
@ -64,6 +65,12 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *viewRegistry);
- (void)setTopLeft:(CGPoint)topLeft;
- (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 }.
*/
@ -127,8 +134,7 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *viewRegistry);
* Calculate all views whose frame needs updating after layout has been calculated.
* The viewsWithNewFrame set contains the reactTags of the views that need updating.
*/
- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame
parentConstraint:(CGSize)parentConstraint;
- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame;
/**
* Recursively apply layout to children.

View File

@ -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];
layoutNode(_cssNode, CSS_UNDEFINED, CSS_DIRECTION_INHERIT);
[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])) {
_frame = CGRectMake(0, 0, CSS_UNDEFINED, CSS_UNDEFINED);
_sizeFlexibility = RCTRootViewSizeFlexibilityNone;
for (unsigned int ii = 0; ii < META_PROP_COUNT; ii++) {
_paddingMetaProps[ii] = CSS_UNDEFINED;