@@ -35,15 +35,22 @@ import {
35
35
ItemSeparatorComponent ,
36
36
PlainInput ,
37
37
SeparatorComponent ,
38
+ LoadingComponent ,
38
39
Spindicator ,
39
- genItemData ,
40
+ genNewerItems ,
41
+ genOlderItems ,
40
42
getItemLayout ,
41
43
pressItem ,
42
44
renderSmallSwitchOption ,
43
45
} from '../../components/ListExampleShared' ;
44
46
45
47
import type { Item } from '../../components/ListExampleShared' ;
46
48
49
+ const PAGE_SIZE = 100 ;
50
+ const NUM_PAGES = 10 ;
51
+ const INITIAL_PAGE_OFFSET = Math . floor ( NUM_PAGES / 2 ) ;
52
+ const LOAD_TIME = 2000 ;
53
+
47
54
const VIEWABILITY_CONFIG = {
48
55
minimumViewTime : 3000 ,
49
56
viewAreaCoveragePercentThreshold : 100 ,
@@ -53,6 +60,8 @@ const VIEWABILITY_CONFIG = {
53
60
type Props = $ReadOnly < { || } > ;
54
61
type State = { |
55
62
data : Array < Item > ,
63
+ first : number ,
64
+ last : number ,
56
65
debug : boolean ,
57
66
horizontal : boolean ,
58
67
inverted : boolean ,
@@ -66,13 +75,18 @@ type State = {|
66
75
onPressDisabled : boolean ,
67
76
textSelectable : boolean ,
68
77
isRTL : boolean ,
78
+ maintainVisibleContentPosition : boolean ,
79
+ previousLoading : boolean ,
80
+ nextLoading : boolean ,
69
81
| } ;
70
82
71
83
const IS_RTL = I18nManager . isRTL ;
72
84
73
85
class FlatListExample extends React . PureComponent < Props , State > {
74
86
state : State = {
75
- data : genItemData ( 100 ) ,
87
+ data : genNewerItems ( PAGE_SIZE , PAGE_SIZE * INITIAL_PAGE_OFFSET ) ,
88
+ first : PAGE_SIZE * INITIAL_PAGE_OFFSET ,
89
+ last : PAGE_SIZE + PAGE_SIZE * INITIAL_PAGE_OFFSET ,
76
90
debug : false ,
77
91
horizontal : false ,
78
92
inverted : false ,
@@ -86,6 +100,9 @@ class FlatListExample extends React.PureComponent<Props, State> {
86
100
onPressDisabled : false ,
87
101
textSelectable : true ,
88
102
isRTL : IS_RTL ,
103
+ maintainVisibleContentPosition : true ,
104
+ previousLoading : false ,
105
+ nextLoading : false ,
89
106
} ;
90
107
91
108
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
@@ -209,6 +226,11 @@ class FlatListExample extends React.PureComponent<Props, State> {
209
226
this . state . isRTL ,
210
227
this . _setIsRTL ,
211
228
) }
229
+ { renderSmallSwitchOption (
230
+ 'Maintain content position' ,
231
+ this . state . maintainVisibleContentPosition ,
232
+ this . _setBooleanValue ( 'maintainVisibleContentPosition' ) ,
233
+ ) }
212
234
{ Platform . OS === 'android' && (
213
235
< View >
214
236
< TextInput
@@ -230,8 +252,12 @@ class FlatListExample extends React.PureComponent<Props, State> {
230
252
< Animated . FlatList
231
253
fadingEdgeLength = { this . state . fadingEdgeLength }
232
254
ItemSeparatorComponent = { ItemSeparatorComponent }
233
- ListHeaderComponent = { < HeaderComponent /> }
234
- ListFooterComponent = { FooterComponent }
255
+ ListHeaderComponent = {
256
+ this . state . previousLoading ? LoadingComponent : HeaderComponent
257
+ }
258
+ ListFooterComponent = {
259
+ this . state . nextLoading ? LoadingComponent : FooterComponent
260
+ }
235
261
ListEmptyComponent = { ListEmptyComponent }
236
262
// $FlowFixMe[missing-empty-array-annot]
237
263
data = { this . state . empty ? [ ] : filteredData }
@@ -250,6 +276,8 @@ class FlatListExample extends React.PureComponent<Props, State> {
250
276
keyboardShouldPersistTaps = "always"
251
277
keyboardDismissMode = "on-drag"
252
278
numColumns = { 1 }
279
+ onStartReached = { this . _onStartReached }
280
+ initialScrollIndex = { Math . floor ( PAGE_SIZE / 2 ) }
253
281
onEndReached = { this . _onEndReached }
254
282
onRefresh = { this . _onRefresh }
255
283
onScroll = {
@@ -260,6 +288,11 @@ class FlatListExample extends React.PureComponent<Props, State> {
260
288
refreshing = { false }
261
289
contentContainerStyle = { styles . list }
262
290
viewabilityConfig = { VIEWABILITY_CONFIG }
291
+ maintainVisibleContentPosition = {
292
+ this . state . maintainVisibleContentPosition
293
+ ? { minIndexForVisible : 2 }
294
+ : undefined
295
+ }
263
296
{ ...flatListItemRendererProps }
264
297
/>
265
298
</ View >
@@ -280,13 +313,33 @@ class FlatListExample extends React.PureComponent<Props, State> {
280
313
_getItemLayout = ( data : any , index : number ) => {
281
314
return getItemLayout ( data , index , this . state . horizontal ) ;
282
315
} ;
316
+ _onStartReached = ( ) => {
317
+ if ( this . state . first <= 0 || this . state . previousLoading ) {
318
+ return ;
319
+ }
320
+
321
+ this . setState ( { previousLoading : true } ) ;
322
+ setTimeout ( ( ) => {
323
+ this . setState ( state => ( {
324
+ previousLoading : false ,
325
+ data : genOlderItems ( PAGE_SIZE , state . first ) . concat ( state . data ) ,
326
+ first : state . first - PAGE_SIZE ,
327
+ } ) ) ;
328
+ } , LOAD_TIME ) ;
329
+ } ;
283
330
_onEndReached = ( ) => {
284
- if ( this . state . data . length >= 1000 ) {
331
+ if ( this . state . last >= PAGE_SIZE * NUM_PAGES || this . state . nextLoading ) {
285
332
return ;
286
333
}
287
- this . setState ( state => ( {
288
- data : state . data . concat ( genItemData ( 100 , state . data . length ) ) ,
289
- } ) ) ;
334
+
335
+ this . setState ( { nextLoading : true } ) ;
336
+ setTimeout ( ( ) => {
337
+ this . setState ( state => ( {
338
+ nextLoading : false ,
339
+ data : state . data . concat ( genNewerItems ( PAGE_SIZE , state . last ) ) ,
340
+ last : state . last + PAGE_SIZE ,
341
+ } ) ) ;
342
+ } , LOAD_TIME ) ;
290
343
} ;
291
344
// $FlowFixMe[missing-local-annot]
292
345
_onPressCallback = ( ) => {
@@ -343,7 +396,7 @@ class FlatListExample extends React.PureComponent<Props, State> {
343
396
344
397
_pressItem = ( key : string ) => {
345
398
this . _listRef ?. recordInteraction ( ) ;
346
- const index = Number ( key ) ;
399
+ const index = this . state . data . findIndex ( item => item . key === key ) ;
347
400
const itemState = pressItem ( this . state . data [ index ] ) ;
348
401
this . setState ( state => ( {
349
402
...state ,
0 commit comments