Fixed root view background color propagation

This commit is contained in:
Nick Lockwood 2015-05-26 04:14:31 -07:00
parent 81401064e5
commit b7c669aa73
7 changed files with 85 additions and 47 deletions

View File

@ -51,11 +51,7 @@ RCT_EXPORT_SHADOW_PROPERTY(maximumNumberOfLines, NSInteger)
RCT_EXPORT_SHADOW_PROPERTY(shadowOffset, CGSize)
RCT_EXPORT_SHADOW_PROPERTY(textAlign, NSTextAlignment)
RCT_REMAP_SHADOW_PROPERTY(backgroundColor, textBackgroundColor, UIColor)
RCT_CUSTOM_SHADOW_PROPERTY(containerBackgroundColor, UIColor, RCTShadowText)
{
view.backgroundColor = json ? [RCTConvert UIColor:json] : defaultView.backgroundColor;
view.isBGColorExplicitlySet = json ? YES : defaultView.isBGColorExplicitlySet;
}
RCT_REMAP_SHADOW_PROPERTY(containerBackgroundColor, backgroundColor, UIColor)
RCT_CUSTOM_SHADOW_PROPERTY(numberOfLines, NSInteger, RCTShadowText)
{
NSLineBreakMode truncationMode = NSLineBreakByClipping;

View File

@ -48,10 +48,11 @@
RCTBridge *_bridge;
NSString *_moduleName;
NSDictionary *_launchOptions;
UIColor *_backgroundColor;
RCTRootContentView *_contentView;
}
- (instancetype)initWithBridge:(RCTBridge *)bridge
- (instancetype)initWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
{
RCTAssertMainThread();
@ -87,6 +88,17 @@
return [self initWithBridge:bridge moduleName:moduleName];
}
- (void)setBackgroundColor:(UIColor *)backgroundColor
{
_backgroundColor = backgroundColor;
_contentView.backgroundColor = backgroundColor;
}
- (UIColor *)backgroundColor
{
return _backgroundColor;
}
- (UIViewController *)backingViewController
{
return _backingViewController ?: [super backingViewController];
@ -100,7 +112,6 @@
RCT_IMPORT_METHOD(AppRegistry, runApplication)
RCT_IMPORT_METHOD(ReactNative, unmountComponentAtNodeAndRemoveContainer)
- (void)javaScriptDidLoad:(NSNotification *)notification
{
RCTBridge *bridge = notification.userInfo[@"bridge"];
@ -124,6 +135,7 @@ RCT_IMPORT_METHOD(ReactNative, unmountComponentAtNodeAndRemoveContainer)
[_contentView removeFromSuperview];
_contentView = [[RCTRootContentView alloc] initWithFrame:self.bounds
bridge:bridge];
_contentView.backgroundColor = _backgroundColor;
[self addSubview:_contentView];
NSString *moduleName = _moduleName ?: @"";
@ -187,9 +199,17 @@ RCT_IMPORT_METHOD(ReactNative, unmountComponentAtNodeAndRemoveContainer)
- (void)setFrame:(CGRect)frame
{
[super setFrame:frame];
super.frame = frame;
if (self.reactTag && _bridge.isValid) {
[_bridge.uiManager setFrame:self.bounds forRootView:self];
[_bridge.uiManager setFrame:frame forRootView:self];
}
}
- (void)setBackgroundColor:(UIColor *)backgroundColor
{
super.backgroundColor = backgroundColor;
if (self.reactTag && _bridge.isValid) {
[_bridge.uiManager setBackgroundColor:backgroundColor forRootView:self];
}
}

View File

@ -36,10 +36,16 @@
/**
* Update the frame of a root view. This might be in response to a screen rotation
* or some other layout event outsde of the React-managed view hierarchy.
* or some other layout event outside of the React-managed view hierarchy.
*/
- (void)setFrame:(CGRect)frame forRootView:(UIView *)rootView;
/**
* Update the background color of a root view. This is usually triggered by
* manually setting the background color of the root view with native code.
*/
- (void)setBackgroundColor:(UIColor *)color forRootView:(UIView *)rootView;
/**
* Schedule a block to be executed on the UI thread. Useful if you need to execute
* view logic after all currently queued view updates have completed.

View File

@ -338,17 +338,14 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewNa
_viewRegistry[reactTag] = rootView;
CGRect frame = rootView.frame;
// Register manager (TODO: should we do this, or leave it nil?)
_viewManagerRegistry[reactTag] = _viewManagers[@"RCTView"];
// Register shadow view
dispatch_async(_shadowQueue, ^{
RCTShadowView *shadowView = [[RCTShadowView alloc] init];
shadowView.reactTag = reactTag;
shadowView.frame = frame;
shadowView.backgroundColor = [UIColor whiteColor];
shadowView.backgroundColor = rootView.backgroundColor;
shadowView.viewName = NSStringFromClass([rootView class]);
_shadowViewRegistry[shadowView.reactTag] = shadowView;
[_rootViewTags addObject:reactTag];
});
}
@ -372,6 +369,22 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewNa
});
}
- (void)setBackgroundColor:(UIColor *)color forRootView:(UIView *)rootView
{
RCTAssertMainThread();
NSNumber *reactTag = rootView.reactTag;
RCTAssert(RCTIsReactRootView(reactTag), @"Specified view %@ is not a root view", reactTag);
dispatch_async(_shadowQueue, ^{
RCTShadowView *rootShadowView = _shadowViewRegistry[reactTag];
RCTAssert(rootShadowView != nil, @"Could not locate root view with tag #%@", reactTag);
rootShadowView.backgroundColor = color;
[self _amendPendingUIBlocksWithStylePropagationUpdateForRootView:rootShadowView];
[self flushUIBlocks];
});
}
/**
* Unregisters views from registries
*/
@ -799,6 +812,11 @@ RCT_EXPORT_METHOD(createView:(NSNumber *)reactTag
}
_shadowViewRegistry[reactTag] = shadowView;
// Shadow view is the source of truth for background color this is a little
// bit counter-intuitive if people try to set background color when setting up
// the view, but it's the only way that makes sense given our threading model
UIColor *backgroundColor = shadowView.backgroundColor;
[self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){
RCTAssertMainThread();
@ -807,14 +825,15 @@ RCT_EXPORT_METHOD(createView:(NSNumber *)reactTag
// Generate default view, used for resetting default props
if (!uiManager->_defaultViews[viewName]) {
// Note the default is setup after the props are read for the first time ever
// for this className - this is ok because we only use the default for restoring
// defaults, which never happens on first creation.
// Note the default is setup after the props are read for the first time
// ever for this className - this is ok because we only use the default
// for restoring defaults, which never happens on first creation.
uiManager->_defaultViews[viewName] = [manager view];
}
// Set properties
view.reactTag = reactTag;
view.backgroundColor = backgroundColor;
if ([view isKindOfClass:[UIView class]]) {
view.multipleTouchEnabled = YES;
view.userInteractionEnabled = YES; // required for touch handling

View File

@ -38,7 +38,6 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *);
@property (nonatomic, weak, readonly) RCTShadowView *superview;
@property (nonatomic, assign, readonly) css_node_t *cssNode;
@property (nonatomic, copy) NSString *viewName;
@property (nonatomic, assign) BOOL isBGColorExplicitlySet; // Used to propagate to children
@property (nonatomic, strong) UIColor *backgroundColor; // Used to propagate to children
@property (nonatomic, assign) RCTUpdateLifecycle layoutLifecycle;
@property (nonatomic, assign) BOOL hasOnLayout;

View File

@ -38,6 +38,7 @@ typedef enum {
NSMutableArray *_reactSubviews;
BOOL _recomputePadding;
BOOL _recomputeMargin;
BOOL _isBGColorExplicitlySet;
float _paddingMetaProps[META_PROP_COUNT];
float _marginMetaProps[META_PROP_COUNT];
}
@ -515,6 +516,7 @@ RCT_STYLE_PROPERTY(FlexWrap, flexWrap, flex_wrap, css_wrap_type_t)
- (void)setBackgroundColor:(UIColor *)color
{
_backgroundColor = color;
_isBGColorExplicitlySet = YES;
[self dirtyPropagation];
}

View File

@ -228,36 +228,38 @@ RCT_VIEW_BORDER_RADIUS_PROPERTY(BottomRight)
#pragma mark - ShadowView properties
RCT_EXPORT_SHADOW_PROPERTY(top, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(right, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(bottom, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(backgroundColor, UIColor)
RCT_EXPORT_SHADOW_PROPERTY(top, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(right, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(bottom, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(left, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(width, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(height, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(width, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(height, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(borderTopWidth, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(borderRightWidth, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(borderBottomWidth, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(borderLeftWidth, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(borderTopWidth, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(borderRightWidth, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(borderBottomWidth, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(borderLeftWidth, CGFloat)
RCT_CUSTOM_SHADOW_PROPERTY(borderWidth, CGFloat, RCTShadowView) {
[view setBorderWidth:[RCTConvert CGFloat:json]];
}
RCT_EXPORT_SHADOW_PROPERTY(marginTop, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(marginRight, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(marginBottom, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(marginLeft, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(marginVertical, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(marginHorizontal, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(margin, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(marginTop, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(marginRight, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(marginBottom, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(marginLeft, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(marginVertical, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(marginHorizontal, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(margin, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(paddingTop, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(paddingRight, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(paddingBottom, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(paddingLeft, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(paddingVertical, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(paddingHorizontal, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(paddingTop, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(paddingRight, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(paddingBottom, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(paddingLeft, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(paddingVertical, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(paddingHorizontal, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(padding, CGFloat);
RCT_EXPORT_SHADOW_PROPERTY(flex, CGFloat)
@ -268,12 +270,6 @@ RCT_EXPORT_SHADOW_PROPERTY(alignItems, css_align_t)
RCT_EXPORT_SHADOW_PROPERTY(alignSelf, css_align_t)
RCT_REMAP_SHADOW_PROPERTY(position, positionType, css_position_type_t)
RCT_CUSTOM_SHADOW_PROPERTY(backgroundColor, UIColor, RCTShadowView)
{
view.backgroundColor = json ? [RCTConvert UIColor:json] : defaultView.backgroundColor;
view.isBGColorExplicitlySet = json ? YES : defaultView.isBGColorExplicitlySet;
}
RCT_REMAP_SHADOW_PROPERTY(onLayout, hasOnLayout, BOOL)
@end