Skip to content

Commit

Permalink
#1673 - Re-render Clipping Corners when User Interface Style Changes (#…
Browse files Browse the repository at this point in the history
…1674)

* This PR addresses an issue I raised with #1673 where the clipping corner layer doesn't get re-rendered when going from a dark to light user interface style. The fix is to add code in the `-asyncTraitCollectionDidChangeWithPreviousTraitCollection:` method that calls through to `-_updateClipCornerLayerContentsWithRadius:backgroundColor:` if the user interface style changes.

I've also added snapshot tests to verify that using clipping corners with a dynamic background color updates when the user interface style changes.
  • Loading branch information
shamanskyh authored and rahul-malik committed Sep 16, 2019
1 parent 712efc4 commit 0b02e8b
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 7 deletions.
27 changes: 20 additions & 7 deletions Source/ASDisplayNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -442,16 +442,29 @@ - (void)asyncTraitCollectionDidChangeWithPreviousTraitCollection:(ASPrimitiveTra
if (self.primitiveTraitCollection.userInterfaceStyle != previousTraitCollection.userInterfaceStyle) {
// When changing between light and dark mode, often the entire node needs to re-render.
// This change doesn't happen frequently so it's fairly safe to render nodes again
if (_loaded(self) && self.isLayerBacked) {
// Background colors do not dynamically update for layer backed nodes since they utilize CGColorRef
// instead of UIColor. We utilize the _backgroundColor instance variable to track the full dynamic color
// and apply any changes here when trait collection updates occur.
CGColorRef cgBackgroundColor = _backgroundColor.CGColor;
if (!CGColorEqualToColor(_layer.backgroundColor, cgBackgroundColor)) {
_layer.backgroundColor = cgBackgroundColor;
BOOL needsClippingCornerUpdate = NO;
CGFloat cornerRadius = _cornerRadius;
ASCornerRoundingType cornerRoundingType = _cornerRoundingType;
UIColor *backgroundColor = self.backgroundColor;
if (_loaded(self)) {
if (self.isLayerBacked) {
// Background colors do not dynamically update for layer backed nodes since they utilize CGColorRef
// instead of UIColor. We utilize the _backgroundColor instance variable to track the full dynamic color
// and apply any changes here when trait collection updates occur.
CGColorRef cgBackgroundColor = backgroundColor.CGColor;
if (!CGColorEqualToColor(_layer.backgroundColor, cgBackgroundColor)) {
_layer.backgroundColor = cgBackgroundColor;
}
}
// If we have clipping corners, re-render the clipping corner layer upon user interface style change
if (cornerRoundingType == ASCornerRoundingTypeClipping && cornerRadius > 0.0f) {
needsClippingCornerUpdate = YES;
}
}
__instanceLock__.unlock();
if (needsClippingCornerUpdate) {
[self _updateClipCornerLayerContentsWithRadius:cornerRadius backgroundColor:backgroundColor];
}
[self setNeedsDisplay];
return;
}
Expand Down
31 changes: 31 additions & 0 deletions Tests/ASDisplayNodeSnapshotTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,49 @@ - (void)testPrecompositedCornerRounding

- (void)testClippingCornerRounding
{
#if AS_AT_LEAST_IOS13
if (@available(iOS 13.0, *)) {
ASConfiguration *config = [ASConfiguration new];
config.experimentalFeatures = ASExperimentalTraitCollectionDidChangeWithPreviousCollection;
[ASConfigurationManager test_resetWithConfiguration:config];
}
#endif

for (CACornerMask c = 1; c <= kASCACornerAllCorners; c |= (c << 1)) {
auto node = [[ASImageNode alloc] init];
auto bounds = CGRectMake(0, 0, 100, 100);
node.image = BlueImageMake(bounds);
node.frame = bounds;
node.cornerRoundingType = ASCornerRoundingTypeClipping;
#if AS_AT_LEAST_IOS13
if (@available(iOS 13.0, *)) {
node.backgroundColor = UIColor.systemBackgroundColor;
} else {
node.backgroundColor = UIColor.greenColor;
}
#else
node.backgroundColor = UIColor.greenColor;
#endif
node.maskedCorners = c;
node.cornerRadius = 15;
// A layout pass is required, because that's where we lay out the clip layers.
[node.layer layoutIfNeeded];

#if AS_AT_LEAST_IOS13
if (@available(iOS 13.0, *)) {
[[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight] performAsCurrentTraitCollection:^{
ASSnapshotVerifyNode(node, ([NSString stringWithFormat:@"%d-light", (int)c]));
}];

[[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark] performAsCurrentTraitCollection:^{
ASSnapshotVerifyNode(node, ([NSString stringWithFormat:@"%d-dark", (int)c]));
}];
} else {
ASSnapshotVerifyNode(node, ([NSString stringWithFormat:@"%d", (int)c]));
}
#else
ASSnapshotVerifyNode(node, ([NSString stringWithFormat:@"%d", (int)c]));
#endif
}
}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0b02e8b

Please sign in to comment.