react-native/React/Views/RCTScrollContentShadowView.m
Ramanpreet Nara 9bbc70c442 Re-render views when direction changes
Summary:
This is required for D5874536, wherein I'll be introducing direction-aware props for borders.

When a view's border changes due to a direction update, only the frames of its children update. Therefore, only the children `UIView`s get a chance to be re-rendered. This is incorrect because the view that's had its borders changed also needs to re-render. So, I keep a track of the layout direction in a property on all shadow views. Then, when I update that prop within `applyLayoutNode`, I push shadow views into the `viewsWithNewFrames` set.

Reviewed By: mmmulani

Differential Revision: D5944488

fbshipit-source-id: 3f23e9973f3555612920703cdb6cec38e6360d2d
2017-10-02 11:15:48 -07:00

56 lines
1.7 KiB
Objective-C

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "RCTScrollContentShadowView.h"
#import <yoga/Yoga.h>
#import "RCTUtils.h"
@interface RCTShadowView () {
// This will be removed after t15757916, which will remove
// side-effects from `setFrame:` method.
@public CGRect _frame;
}
@end
@implementation RCTScrollContentShadowView
- (void)applyLayoutNode:(YGNodeRef)node
viewsWithNewFrame:(NSMutableSet<RCTShadowView *> *)viewsWithNewFrame
absolutePosition:(CGPoint)absolutePosition
{
// Call super method if LTR layout is enforced.
if (self.layoutDirection == UIUserInterfaceLayoutDirectionLeftToRight) {
[super applyLayoutNode:node
viewsWithNewFrame:viewsWithNewFrame
absolutePosition:absolutePosition];
return;
}
// Motivation:
// Yoga place `contentView` on the right side of `scrollView` when RTL layout is enfoced.
// That breaks everything; it is completly pointless to (re)position `contentView`
// because it is `contentView`'s job. So, we work around it here.
// Step 1. Compensate `absolutePosition` change.
CGFloat xCompensation = YGNodeLayoutGetRight(node) - YGNodeLayoutGetLeft(node);
absolutePosition.x += xCompensation;
// Step 2. Call super method.
[super applyLayoutNode:node
viewsWithNewFrame:viewsWithNewFrame
absolutePosition:absolutePosition];
// Step 3. Reset the position.
_frame.origin.x = RCTRoundPixelValue(YGNodeLayoutGetRight(node));
}
@end