Skip to content

Commit 310a6bc

Browse files
Fix Issue 10718: Add iOS support for progressViewOffset (#30737)
Summary: Fixes #10718, bringing `progressViewOffset` support to iOS. Thanks to Taylor123 for the initial PR upon which this fix is based. ## Changelog [iOS] [Fix] - `progressViewOffset` prop of `RefreshControl` and `VirtualizedList` now works on iOS Pull Request resolved: #30737 Test Plan: Tested with quick-and-dirty sample app. ![progressViewOffset-iOS](https://user-images.githubusercontent.com/1563532/104526540-82fe1d80-55b7-11eb-9f99-e025bedf4874.gif) ## Documentation The corresponding documentation update PR can be found [here](facebook/react-native-website#2441). Reviewed By: kacieb Differential Revision: D26813977 Pulled By: sammy-SC fbshipit-source-id: 45cc5a647d70e44a29c6391b7586cb41ca011bef
1 parent 896baf7 commit 310a6bc

File tree

5 files changed

+36
-7
lines changed

5 files changed

+36
-7
lines changed

Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
* @flow strict-local
99
*/
1010

11-
import type {DirectEventHandler, WithDefault} from '../../Types/CodegenTypes';
11+
import type {
12+
DirectEventHandler,
13+
Float,
14+
WithDefault,
15+
} from '../../Types/CodegenTypes';
1216
import type {ColorValue} from '../../StyleSheet/StyleSheet';
1317
import type {ViewProps} from '../View/ViewPropTypes';
1418
import * as React from 'react';
@@ -32,6 +36,10 @@ type NativeProps = $ReadOnly<{|
3236
* The title displayed under the refresh indicator.
3337
*/
3438
title?: WithDefault<string, null>,
39+
/**
40+
* Progress view top offset
41+
*/
42+
progressViewOffset?: WithDefault<Float, 0>,
3543

3644
/**
3745
* Called when the view starts refreshing.

Libraries/Components/RefreshControl/RefreshControl.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ type AndroidProps = $ReadOnly<{|
5252
* Size of the refresh indicator.
5353
*/
5454
size?: ?('default' | 'large'),
55-
/**
56-
* Progress view top offset
57-
*/
58-
progressViewOffset?: ?number,
5955
|}>;
6056

6157
export type RefreshControlProps = $ReadOnly<{|
@@ -72,6 +68,11 @@ export type RefreshControlProps = $ReadOnly<{|
7268
* Whether the view should be indicating an active refresh.
7369
*/
7470
refreshing: boolean,
71+
72+
/**
73+
* Progress view top offset
74+
*/
75+
progressViewOffset?: ?number,
7576
|}>;
7677

7778
/**
@@ -162,7 +163,6 @@ class RefreshControl extends React.Component<RefreshControlProps> {
162163
colors,
163164
progressBackgroundColor,
164165
size,
165-
progressViewOffset,
166166
...props
167167
} = this.props;
168168
return (

Libraries/Lists/VirtualizedList.js

-1
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,6 @@ type OptionalProps = {|
246246
persistentScrollbar?: ?boolean,
247247
/**
248248
* Set this when offset is needed for the loading indicator to show correctly.
249-
* @platform android
250249
*/
251250
progressViewOffset?: number,
252251
/**

React/Views/RefreshControl/RCTRefreshControl.m

+21
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ @implementation RCTRefreshControl {
2121
BOOL _refreshingProgrammatically;
2222
NSString *_title;
2323
UIColor *_titleColor;
24+
CGFloat _progressViewOffset;
2425
}
2526

2627
- (instancetype)init
@@ -40,6 +41,7 @@ - (instancetype)init
4041
- (void)layoutSubviews
4142
{
4243
[super layoutSubviews];
44+
[self _applyProgressViewOffset];
4345

4446
// If the control is refreshing when mounted we need to call
4547
// beginRefreshing in layoutSubview or it doesn't work.
@@ -120,6 +122,19 @@ - (void)endRefreshingProgrammatically
120122
}
121123
}
122124

125+
- (void)_applyProgressViewOffset
126+
{
127+
// progressViewOffset must be converted from the ScrollView parent's coordinate space to
128+
// the coordinate space of the RefreshControl. This ensures that the control respects any
129+
// offset in the view hierarchy, and that progressViewOffset is not inadvertently applied
130+
// multiple times.
131+
UIView *scrollView = self.superview;
132+
UIView *target = scrollView.superview;
133+
CGPoint rawOffset = CGPointMake(0, _progressViewOffset);
134+
CGPoint converted = [self convertPoint:rawOffset fromView:target];
135+
self.frame = CGRectOffset(self.frame, 0, converted.y);
136+
}
137+
123138
- (NSString *)title
124139
{
125140
return _title;
@@ -172,6 +187,12 @@ - (void)setCurrentRefreshingState:(BOOL)refreshing
172187
_currentRefreshingStateTimestamp = _currentRefreshingStateClock++;
173188
}
174189

190+
- (void)setProgressViewOffset:(CGFloat)offset
191+
{
192+
_progressViewOffset = offset;
193+
[self _applyProgressViewOffset];
194+
}
195+
175196
- (void)refreshControlValueChanged
176197
{
177198
[self setCurrentRefreshingState:super.refreshing];

React/Views/RefreshControl/RCTRefreshControlManager.m

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ - (UIView *)view
2525
RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)
2626
RCT_EXPORT_VIEW_PROPERTY(title, NSString)
2727
RCT_EXPORT_VIEW_PROPERTY(titleColor, UIColor)
28+
RCT_EXPORT_VIEW_PROPERTY(progressViewOffset, CGFloat)
2829

2930
RCT_EXPORT_METHOD(setNativeRefreshing : (nonnull NSNumber *)viewTag toRefreshing : (BOOL)refreshing)
3031
{

0 commit comments

Comments
 (0)