iOS: Fix refreshControl layouting (#28236)

Summary:
In `react-native-navigation` we allow the usage of native iOS navigationBar **largeTitle** which cause the title to "jump" when pulling to refresh.
We found that the layout calculations of the refreshControl element mess up the system behaviour.

## Changelog

[iOS] [Fixed] - Fix refreshControl messes up navigationBar largeTitles
Pull Request resolved: https://github.com/facebook/react-native/pull/28236

Test Plan:
### Before the fix:
![before](https://user-images.githubusercontent.com/10794586/75991307-f7c7ec00-5efe-11ea-8cd9-ab8c3fbe1dc1.gif)

### And after:
![after](https://user-images.githubusercontent.com/10794586/75990618-d9152580-5efd-11ea-8c72-5deb6d83a840.gif)

### How it looks like with react-native init app after the fix:
![ezgif com-video-to-gif (4)](https://user-images.githubusercontent.com/10794586/77253369-54970680-6c62-11ea-9ad6-3265e23044e6.gif)

Differential Revision: D20587945

Pulled By: shergin

fbshipit-source-id: 94f560b17e367f4ef5e789f40c052396949b51a3
This commit is contained in:
yogevbd authored and Facebook GitHub Bot committed 2020-04-27 13:32:32 -07:00
1 parent 26d3bcae72
commit 702ff6d1cd
2 files changed
+4 -20

No files matched your search

@@ -41,12 +41,6 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
{
[super layoutSubviews];
// Fix for bug #7976
// TODO: Remove when updating to use iOS 10 refreshControl UIScrollView prop.
if (self.backgroundColor == nil) {
self.backgroundColor = [UIColor clearColor];
}
// If the control is refreshing when mounted we need to call
// beginRefreshing in layoutSubview or it doesn't work.
if (_currentRefreshingState && _isInitialRender) {
+4 -14
View File
@@ -32,7 +32,7 @@
@property (nonatomic, assign) BOOL centerContent;
#if !TARGET_OS_TV
@property (nonatomic, strong) UIView<RCTCustomRefreshContolProtocol> *customRefreshControl;
@property (nonatomic, strong) UIRefreshControl<RCTCustomRefreshContolProtocol> *customRefreshControl;
@property (nonatomic, assign) BOOL pinchGestureEnabled;
#endif
@@ -224,13 +224,13 @@
}
#if !TARGET_OS_TV
- (void)setCustomRefreshControl:(UIView<RCTCustomRefreshContolProtocol> *)refreshControl
- (void)setCustomRefreshControl:(UIRefreshControl<RCTCustomRefreshContolProtocol> *)refreshControl
{
if (_customRefreshControl) {
[_customRefreshControl removeFromSuperview];
}
_customRefreshControl = refreshControl;
[self addSubview:_customRefreshControl];
self.refreshControl = refreshControl;
}
- (void)setPinchGestureEnabled:(BOOL)pinchGestureEnabled
@@ -344,7 +344,7 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(
[super insertReactSubview:view atIndex:atIndex];
#if !TARGET_OS_TV
if ([view conformsToProtocol:@protocol(RCTCustomRefreshContolProtocol)]) {
[_scrollView setCustomRefreshControl:(UIView<RCTCustomRefreshContolProtocol> *)view];
[_scrollView setCustomRefreshControl:(UIRefreshControl<RCTCustomRefreshContolProtocol> *)view];
if (![view isKindOfClass:[UIRefreshControl class]] && [view conformsToProtocol:@protocol(UIScrollViewDelegate)]) {
[self addScrollListener:(UIView<UIScrollViewDelegate> *)view];
}
@@ -418,16 +418,6 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(
[super layoutSubviews];
RCTAssert(self.subviews.count == 1, @"we should only have exactly one subview");
RCTAssert([self.subviews lastObject] == _scrollView, @"our only subview should be a scrollview");
#if !TARGET_OS_TV
// Adjust the refresh control frame if the scrollview layout changes.
UIView<RCTCustomRefreshContolProtocol> *refreshControl = _scrollView.customRefreshControl;
if (refreshControl && refreshControl.isRefreshing) {
refreshControl.frame =
(CGRect){_scrollView.contentOffset, {_scrollView.frame.size.width, refreshControl.frame.size.height}};
}
#endif
[self updateClippedSubviews];
}