exposed a way to trigger layout on the uimanager

Summary:
A component can be backed by native "node" that can change its internal state, which would result in a new UI after the next layout. Since js has no way of knowing that this has happened it wouldn't trigger a layout if nothing in js world has changed. Therefore we need a way how to trigger layout from native code.

This diff does it by adding methods `layoutIfNeeded` on the uimanager and `isBatchActive` on the bridge.
When `layoutIfNeeded` is called it checks whether a batch is in progress. If it is we do nothing, since at it's end layout happens. If a batch is not in progress we immidiately do layout.

I went with the easiest way how to implement this - `isBatchActive` is a public method on the bridge. It's not ideal, but consistent with other methods for modules.
public

Reviewed By: jspahrsummers, nicklockwood

Differential Revision: D2748896

fb-gh-sync-id: f3664c4af980d40a463b538e069b26c9ebad6300
This commit is contained in:
Martin Kralik 2015-12-11 06:54:56 -08:00 committed by facebook-github-bot-3
parent 302317c250
commit a86171a482
5 changed files with 39 additions and 0 deletions

View File

@ -982,6 +982,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
}]; }];
} }
- (BOOL)isBatchActive
{
return _wasBatchActive;
}
@end @end
@implementation RCTBatchedBridge(Deprecated) @implementation RCTBatchedBridge(Deprecated)

View File

@ -163,6 +163,11 @@ RCT_EXTERN BOOL RCTBridgeModuleClassIsRegistered(Class);
*/ */
- (void)reload; - (void)reload;
/**
* Says whether bridge has started recieving calls from javascript.
*/
- (BOOL)isBatchActive;
@end @end
/** /**

View File

@ -287,6 +287,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
return self.batchedBridge.valid; return self.batchedBridge.valid;
} }
- (BOOL)isBatchActive
{
return [_batchedBridge isBatchActive];
}
- (void)invalidate - (void)invalidate
{ {
RCTBatchedBridge *batchedBridge = self.batchedBridge; RCTBatchedBridge *batchedBridge = self.batchedBridge;

View File

@ -88,6 +88,12 @@ RCT_EXTERN NSString *const RCTUIManagerRootViewKey;
*/ */
@property (atomic, assign) BOOL unsafeFlushUIChangesBeforeBatchEnds; @property (atomic, assign) BOOL unsafeFlushUIChangesBeforeBatchEnds;
/**
* In some cases we might want to trigger layout from native side.
* React won't be aware of this, so we need to make sure it happens.
*/
- (void)setNeedsLayout;
@end @end
/** /**

View File

@ -888,6 +888,15 @@ RCT_EXPORT_METHOD(findSubviewIn:(nonnull NSNumber *)reactTag atPoint:(CGPoint)po
} }
- (void)batchDidComplete - (void)batchDidComplete
{
[self _layoutAndMount];
}
/**
* Sets up animations, computes layout, creates UI mounting blocks for computed layout,
* runs these blocks and all other already existing blocks.
*/
- (void)_layoutAndMount
{ {
// Gather blocks to be executed now that all view hierarchy manipulations have // Gather blocks to be executed now that all view hierarchy manipulations have
// been completed (note that these may still take place before layout has finished) // been completed (note that these may still take place before layout has finished)
@ -962,6 +971,15 @@ RCT_EXPORT_METHOD(findSubviewIn:(nonnull NSNumber *)reactTag atPoint:(CGPoint)po
} }
} }
- (void)setNeedsLayout
{
// If there is an active batch layout will happen when batch finished, so we will wait for that.
// Otherwise we immidiately trigger layout.
if (![_bridge isBatchActive]) {
[self _layoutAndMount];
}
}
RCT_EXPORT_METHOD(measure:(nonnull NSNumber *)reactTag RCT_EXPORT_METHOD(measure:(nonnull NSNumber *)reactTag
callback:(RCTResponseSenderBlock)callback) callback:(RCTResponseSenderBlock)callback)
{ {