Skip to content

Commit 89ed0c5

Browse files
committed
Merge pull request #30 from CodeYellowBV/refreshcontrol
Use RefreshControl instead of own implementation for pull-to-refresh
2 parents 1736ac0 + 8590aac commit 89ed0c5

File tree

2 files changed

+37
-185
lines changed

2 files changed

+37
-185
lines changed

GiftedListView.js

Lines changed: 35 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var {
88
TouchableHighlight,
99
View,
1010
Text,
11-
PullToRefreshViewAndroid
11+
RefreshControl,
1212
} = React;
1313

1414

@@ -39,8 +39,12 @@ var GiftedListView = React.createClass({
3939
firstLoader: true,
4040
pagination: true,
4141
refreshable: true,
42-
refreshableViewHeight: 50,
43-
refreshableDistance: 40,
42+
refreshableColors: undefined,
43+
refreshableProgressBackgroundColor: undefined,
44+
refreshableSize: undefined,
45+
refreshableTitle: undefined,
46+
refreshableTintColor: undefined,
47+
renderRefreshControl: null,
4448
headerView: null,
4549
sectionHeaderView: null,
4650
withSections: false,
@@ -49,15 +53,8 @@ var GiftedListView = React.createClass({
4953
paginationFetchingView: null,
5054
paginationAllLoadedView: null,
5155
paginationWaitingView: null,
52-
refreshableFetchingView: null,
53-
refreshableWillRefreshView: null,
54-
refreshableWaitingView: null,
5556
emptyView: null,
5657
renderSeparator: null,
57-
PullToRefreshViewAndroidProps: {
58-
colors: ['#000000'],
59-
progressBackgroundColor: '#c8c7cc',
60-
},
6158
};
6259
},
6360

@@ -67,8 +64,12 @@ var GiftedListView = React.createClass({
6764
firstLoader: React.PropTypes.bool,
6865
pagination: React.PropTypes.bool,
6966
refreshable: React.PropTypes.bool,
70-
refreshableViewHeight: React.PropTypes.number,
71-
refreshableDistance: React.PropTypes.number,
67+
refreshableColors: React.PropTypes.array,
68+
refreshableProgressBackgroundColor: React.PropTypes.string,
69+
refreshableSize: React.PropTypes.string,
70+
refreshableTitle: React.PropTypes.string,
71+
refreshableTintColor: React.PropTypes.string,
72+
renderRefreshControl: React.PropTypes.func,
7273
headerView: React.PropTypes.func,
7374
sectionHeaderView: React.PropTypes.func,
7475
withSections: React.PropTypes.bool,
@@ -77,16 +78,10 @@ var GiftedListView = React.createClass({
7778
paginationFetchingView: React.PropTypes.func,
7879
paginationAllLoadedView: React.PropTypes.func,
7980
paginationWaitingView: React.PropTypes.func,
80-
refreshableFetchingView: React.PropTypes.func,
81-
refreshableWillRefreshView: React.PropTypes.func,
82-
refreshableWaitingView: React.PropTypes.func,
8381
emptyView: React.PropTypes.func,
8482
renderSeparator: React.PropTypes.func,
85-
PullToRefreshViewAndroidProps: React.PropTypes.object,
8683
},
8784

88-
_setY(y) { this._y = y; },
89-
_getY(y) { return this._y; },
9085
_setPage(page) { this._page = page; },
9186
_getPage() { return this._page; },
9287
_setRows(rows) { this._rows = rows; },
@@ -140,51 +135,6 @@ var GiftedListView = React.createClass({
140135
}
141136
return this.props.headerView();
142137
},
143-
refreshableFetchingView() {
144-
if (this.props.refreshableFetchingView) {
145-
return this.props.refreshableFetchingView();
146-
}
147-
return (
148-
<View>
149-
<View style={[this.defaultStyles.refreshableView, this.props.customStyles.refreshableView]}>
150-
<GiftedSpinner />
151-
</View>
152-
{this.headerView()}
153-
</View>
154-
);
155-
},
156-
refreshableWillRefreshView() {
157-
if (this.props.refreshableWillRefreshView) {
158-
return this.props.refreshableWillRefreshView();
159-
}
160-
161-
return (
162-
<View>
163-
<View style={[this.defaultStyles.refreshableView, this.props.customStyles.refreshableView]}>
164-
<Text style={[this.defaultStyles.actionsLabel, this.props.customStyles.actionsLabel]}>
165-
166-
</Text>
167-
</View>
168-
{this.headerView()}
169-
</View>
170-
);
171-
},
172-
refreshableWaitingView(refreshCallback) {
173-
if (this.props.refreshableWaitingView) {
174-
return this.props.refreshableWaitingView(refreshCallback);
175-
}
176-
177-
return (
178-
<View>
179-
<View style={[this.defaultStyles.refreshableView, this.props.customStyles.refreshableView]}>
180-
<Text style={[this.defaultStyles.actionsLabel, this.props.customStyles.actionsLabel]}>
181-
182-
</Text>
183-
</View>
184-
{this.headerView()}
185-
</View>
186-
);
187-
},
188138
emptyView(refreshCallback) {
189139
if (this.props.emptyView) {
190140
return this.props.emptyView(refreshCallback);
@@ -218,13 +168,6 @@ var GiftedListView = React.createClass({
218168
},
219169

220170
getInitialState() {
221-
222-
if (this.props.refreshable === true && Platform.OS !== 'android') {
223-
this._setY(this.props.refreshableViewHeight);
224-
} else {
225-
this._setY(0);
226-
}
227-
228171
this._setPage(1);
229172
this._setRows([]);
230173

@@ -236,7 +179,6 @@ var GiftedListView = React.createClass({
236179
});
237180
return {
238181
dataSource: ds.cloneWithRowsAndSections(this._getRows()),
239-
refreshStatus: 'waiting',
240182
isRefreshing: false,
241183
paginationStatus: 'firstLoad',
242184
};
@@ -246,15 +188,13 @@ var GiftedListView = React.createClass({
246188
});
247189
return {
248190
dataSource: ds.cloneWithRows(this._getRows()),
249-
refreshStatus: 'waiting',
250191
isRefreshing: false,
251192
paginationStatus: 'firstLoad',
252193
};
253194
}
254195
},
255196

256197
componentDidMount() {
257-
this._scrollResponder = this.refs.listview.getScrollResponder();
258198
this.props.onFetch(this._getPage(), this._postRefresh, {firstLoad: true});
259199
},
260200

@@ -268,24 +208,17 @@ var GiftedListView = React.createClass({
268208

269209
_onRefresh(options = {}) {
270210
if (this.isMounted()) {
271-
this._scrollResponder.scrollTo({y: 0});
272211
this.setState({
273-
refreshStatus: 'fetching',
274212
isRefreshing: true,
275213
});
276214
this._setPage(1);
277-
this.props.onFetch(this._getPage(), this._postRefresh, options);
215+
this.props.onFetch(this._getPage(), this._postRefresh, options);
278216
}
279217
},
280218

281219
_postRefresh(rows = [], options = {}) {
282220
if (this.isMounted()) {
283221
this._updateRows(rows, options);
284-
if (this.props.refreshable === true && Platform.OS !== 'android') {
285-
// @issue
286-
// if a scrolling is already in progress, this scroll will not be executed
287-
this._scrollResponder.scrollTo({y: this.props.refreshableViewHeight});
288-
}
289222
}
290223
},
291224

@@ -313,64 +246,21 @@ var GiftedListView = React.createClass({
313246
if (this.props.withSections === true) {
314247
this.setState({
315248
dataSource: this.state.dataSource.cloneWithRowsAndSections(rows),
316-
refreshStatus: 'waiting',
317249
isRefreshing: false,
318250
paginationStatus: (options.allLoaded === true ? 'allLoaded' : 'waiting'),
319251
});
320252
} else {
321253
this.setState({
322254
dataSource: this.state.dataSource.cloneWithRows(rows),
323-
refreshStatus: 'waiting',
324255
isRefreshing: false,
325256
paginationStatus: (options.allLoaded === true ? 'allLoaded' : 'waiting'),
326-
});
327-
}
257+
});
258+
}
328259
} else {
329260
this.setState({
330-
refreshStatus: 'waiting',
331261
isRefreshing: false,
332262
paginationStatus: (options.allLoaded === true ? 'allLoaded' : 'waiting'),
333-
});
334-
}
335-
},
336-
337-
_onResponderRelease() {
338-
if (this.props.refreshable === true) {
339-
if (Platform.OS !== 'android') {
340-
if (this.state.refreshStatus === 'willRefresh') {
341-
this._onRefresh();
342-
}
343-
}
344-
}
345-
},
346-
347-
_onScroll(e) {
348-
this._setY(e.nativeEvent.contentOffset.y);
349-
if (this.props.refreshable === true) {
350-
if (Platform.OS !== 'android') {
351-
if (this._getY() < this.props.refreshableViewHeight - this.props.refreshableDistance
352-
&& this.state.refreshStatus === 'waiting'
353-
&& this._scrollResponder.scrollResponderHandleScrollShouldSetResponder() === true
354-
) {
355-
this.setState({
356-
refreshStatus: 'willRefresh',
357-
isRefreshing: false,
358-
});
359-
}
360-
}
361-
}
362-
},
363-
364-
_renderRefreshView() {
365-
switch (this.state.refreshStatus) {
366-
case 'fetching':
367-
return this.refreshableFetchingView();
368-
break;
369-
case 'willRefresh':
370-
return this.refreshableWillRefreshView();
371-
break;
372-
default:
373-
return this.refreshableWaitingView(this._onRefresh);
263+
});
374264
}
375265
},
376266

@@ -388,85 +278,50 @@ var GiftedListView = React.createClass({
388278
}
389279
},
390280

391-
_calculateContentInset() {
392-
if (this.props.refreshable === true && Platform.OS !== 'android') {
393-
return {top: -1 * this.props.refreshableViewHeight, bottom: 0, left: 0, right: 0};
394-
} else {
395-
return {top: 0, bottom: 0, left: 0, right: 0};
396-
}
397-
},
398-
399-
_calculateContentOffset() {
400-
if (this.props.refreshable === true && Platform.OS !== 'android') {
401-
return {x: 0, y: this.props.refreshableViewHeight};
402-
} else {
403-
return {x: 0, y: 0};
281+
renderRefreshControl() {
282+
if (this.props.renderRefreshControl) {
283+
return this.props.renderRefreshControl({ onRefresh: this._onRefresh });
404284
}
285+
return (
286+
<RefreshControl
287+
onRefresh={this._onRefresh}
288+
refreshing={this.state.isRefreshing}
289+
colors={this.props.refreshableColors}
290+
progressBackgroundColor={this.props.refreshableProgressBackgroundColor}
291+
size={this.props.refreshableSize}
292+
tintColor={this.props.refreshableTintColor}
293+
title={this.props.refreshableTitle}
294+
/>
295+
);
405296
},
406297

407-
408-
renderListView(style = {}) {
298+
render() {
409299
return (
410300
<ListView
411301
ref="listview"
412302
dataSource={this.state.dataSource}
413303
renderRow={this.props.rowView}
414304
renderSectionHeader={this.props.sectionHeaderView}
415-
416-
renderHeader={this.props.refreshable === true && Platform.OS !== 'android' ? this._renderRefreshView : this.headerView}
417305
renderFooter={this._renderPaginationView}
418-
419-
onScroll={this.props.refreshable === true && Platform.OS !== 'android' ? this._onScroll : null}
420-
onResponderRelease={this.props.refreshable === true && Platform.OS !== 'android' ? this._onResponderRelease : null}
421-
422-
scrollEventThrottle={200}
423-
424-
contentInset={this._calculateContentInset()}
425-
contentOffset={this._calculateContentOffset()}
306+
renderSeparator={this.renderSeparator}
426307

427308
automaticallyAdjustContentInsets={false}
428309
scrollEnabled={true}
429310
canCancelContentTouches={true}
430-
431-
renderSeparator={this.renderSeparator}
311+
refreshControl={this.props.refreshable === true ? this.renderRefreshControl() : null}
432312

433313
{...this.props}
434314

435-
style={[this.props.style, style]}
315+
style={this.props.style}
436316
/>
437317
);
438318
},
439319

440-
render() {
441-
if (Platform.OS === 'android' && this.props.refreshable === true) {
442-
return (
443-
<PullToRefreshViewAndroid
444-
refreshing={this.state.isRefreshing}
445-
onRefresh={this._onRefresh}
446-
447-
{...this.props.PullToRefreshViewAndroidProps}
448-
449-
style={[this.props.PullToRefreshViewAndroidProps.style, {flex: 1}]}
450-
>
451-
{this.renderListView({flex: 1})}
452-
</PullToRefreshViewAndroid>
453-
);
454-
} else {
455-
return this.renderListView();
456-
}
457-
},
458-
459320
defaultStyles: {
460321
separator: {
461322
height: 1,
462323
backgroundColor: '#CCC'
463324
},
464-
refreshableView: {
465-
height: 50,
466-
backgroundColor: '#DDD',
467-
justifyContent: 'center',
468-
alignItems: 'center',
469-
},
470325
actionsLabel: {
471326
fontSize: 20,
472327
},

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,12 @@ var Example = React.createClass({
8383
refreshable={true} // enable pull-to-refresh for iOS and touch-to-refresh for Android
8484
withSections={false} // enable sections
8585
customStyles={{
86-
refreshableView: {
86+
paginationView: {
8787
backgroundColor: '#eee',
8888
},
8989
}}
9090

91-
PullToRefreshViewAndroidProps={{
92-
colors: ['#ff0000', '#00ff00', '#0000ff'],
93-
progressBackgroundColor: '#c8c7cc',
94-
}}
91+
refreshableTintColor="blue"
9592
/>
9693
</View>
9794
);

0 commit comments

Comments
 (0)