@@ -20,19 +20,20 @@ export default class SortableList extends Component {
20
20
contentContainerStyle : View . propTypes . style ,
21
21
sortingEnabled : PropTypes . bool ,
22
22
scrollEnabled : PropTypes . bool ,
23
+ horizontal : PropTypes . bool ,
23
24
24
25
renderRow : PropTypes . func . isRequired ,
25
26
26
27
onChangeOrder : PropTypes . func ,
27
28
onActivateRow : PropTypes . func ,
28
29
onReleaseRow : PropTypes . func ,
29
- autoscrollAreaHeight : PropTypes . number ,
30
+ autoscrollAreaSize : PropTypes . number ,
30
31
} ;
31
32
32
33
static defaultProps = {
33
34
sortingEnabled : true ,
34
35
scrollEnabled : true ,
35
- autoscrollAreaHeight : 60 ,
36
+ autoscrollAreaSize : 60 ,
36
37
}
37
38
38
39
/**
@@ -97,62 +98,79 @@ export default class SortableList extends Component {
97
98
}
98
99
}
99
100
100
- scrollBy ( { dy = 0 , animated = false } ) {
101
- this . _contentOffset = {
102
- x : this . _contentOffset . x ,
103
- y : this . _contentOffset . y + dy ,
104
- } ;
101
+ scrollBy ( { dx = 0 , dy = 0 , animated = false } ) {
102
+ if ( this . props . horizontal ) {
103
+ this . _contentOffset . x += dx ;
104
+ } else {
105
+ this . _contentOffset . y += dy ;
106
+ }
107
+
105
108
this . _scroll ( animated ) ;
106
109
}
107
110
108
- scrollTo ( { y = 0 , animated = false } ) {
109
- this . _contentOffset = {
110
- x : this . _contentOffset . x ,
111
- y,
112
- } ;
111
+ scrollTo ( { x = 0 , y = 0 , animated = false } ) {
112
+ if ( this . props . horizontal ) {
113
+ this . _contentOffset . x = x ;
114
+ } else {
115
+ this . _contentOffset . y = y ;
116
+ }
117
+
113
118
this . _scroll ( animated ) ;
114
119
}
115
120
116
121
scrollToRowKey ( { key, animated = false } ) {
117
122
const { order, containerLayout, rowsLayouts} = this . state ;
118
123
124
+ let keyX = 0 ;
119
125
let keyY = 0 ;
120
126
121
- for ( let rowKey of order ) {
127
+ for ( const rowKey of order ) {
122
128
if ( rowKey === key ) {
123
129
break ;
124
130
}
125
131
132
+ keyX += rowsLayouts [ rowKey ] . width ;
126
133
keyY += rowsLayouts [ rowKey ] . height ;
127
134
}
128
135
129
136
// Scroll if the row is not visible.
130
137
if (
131
- keyY < this . _contentOffset . y ||
132
- keyY > this . _contentOffset . y + containerLayout . height
138
+ this . props . horizontal
139
+ ? ( keyX < this . _contentOffset . x || keyX > this . _contentOffset . x + containerLayout . width )
140
+ : ( keyY < this . _contentOffset . y || keyY > this . _contentOffset . y + containerLayout . height )
133
141
) {
134
- this . _contentOffset = {
135
- x : this . _contentOffset . x ,
136
- y : keyY ,
137
- } ;
142
+ if ( this . props . horizontal ) {
143
+ this . _contentOffset . x = keyX ;
144
+ } else {
145
+ this . _contentOffset . y = keyY ;
146
+ }
147
+
138
148
this . _scroll ( animated ) ;
139
149
}
140
150
}
141
151
142
152
render ( ) {
143
- const { contentContainerStyle} = this . props ;
144
- const { contentHeight, scrollEnabled} = this . state ;
145
- const containerStyle = StyleSheet . flatten ( [ styles . container , this . props . style , this . state . style ] ) ;
153
+ const { contentContainerStyle, horizontal} = this . props ;
154
+ const { contentHeight, contentWidth, scrollEnabled} = this . state ;
155
+ const containerStyle = StyleSheet . flatten ( [ this . props . style , this . state . style ] ) ;
156
+ const innerContainerStyle = [ styles . container ] ;
157
+
158
+ if ( horizontal ) {
159
+ innerContainerStyle . push ( { width : contentWidth } ) ;
160
+ } else {
161
+ innerContainerStyle . push ( { height : contentHeight } ) ;
162
+ }
146
163
147
164
return (
148
165
< Animated . View style = { containerStyle } ref = { this . _onRefContainer } >
149
166
< ScrollView
150
167
ref = { this . _onRefScrollView }
168
+ horizontal = { horizontal }
151
169
contentContainerStyle = { contentContainerStyle }
152
170
scrollEventThrottle = { 2 }
153
171
scrollEnabled = { scrollEnabled }
154
172
onScroll = { this . _onScroll } >
155
- < View style = { [ styles . container , { height : contentHeight } ] } >
173
+ < View style = { innerContainerStyle } >
156
174
{ this . _renderRows ( ) }
157
175
</ View >
158
176
</ ScrollView >
@@ -161,12 +179,20 @@ export default class SortableList extends Component {
161
179
}
162
180
163
181
_renderRows ( ) {
164
- const { sortingEnabled, renderRow} = this . props ;
182
+ const { horizontal , sortingEnabled, renderRow} = this . props ;
165
183
const { order, data, activeRowKey, releasedRowKey, rowsLayouts} = this . state ;
166
184
167
- const rowWidth = rowsLayouts && Math . max (
168
- ...Object . keys ( rowsLayouts ) . map ( ( key ) => rowsLayouts [ key ] . width )
169
- ) ;
185
+ let rowHeight = 0 ;
186
+ let rowWidth = 0 ;
187
+
188
+ if ( rowsLayouts ) {
189
+ Object . keys ( rowsLayouts ) . forEach ( ( key ) => {
190
+ rowHeight = Math . max ( rowHeight , rowsLayouts [ key ] . height ) ;
191
+ rowWidth = Math . max ( rowWidth , rowsLayouts [ key ] . width ) ;
192
+ } ) ;
193
+ }
194
+
195
+ let nextX = 0 ;
170
196
let nextY = 0 ;
171
197
172
198
return order . map ( ( key , index ) => {
@@ -175,9 +201,15 @@ export default class SortableList extends Component {
175
201
let resolveLayout ;
176
202
177
203
if ( rowsLayouts ) {
178
- style . width = rowWidth ;
179
- location . y = nextY ;
180
- nextY += rowsLayouts [ key ] . height ;
204
+ if ( horizontal ) {
205
+ style . height = rowHeight ;
206
+ location . x = nextX ;
207
+ nextX += rowsLayouts [ key ] . width ;
208
+ } else {
209
+ style . width = rowWidth ;
210
+ location . y = nextY ;
211
+ nextY += rowsLayouts [ key ] . height ;
212
+ }
181
213
} else {
182
214
this . _rowsLayouts . push ( new Promise ( ( resolve ) => ( resolveLayout = resolve ) ) ) ;
183
215
}
@@ -193,6 +225,7 @@ export default class SortableList extends Component {
193
225
< Row
194
226
key = { uniqueRowKey ( key ) }
195
227
ref = { this . _onRefRow . bind ( this , key ) }
228
+ horizontal = { horizontal }
196
229
animated = { this . _areRowsAnimated && ! active }
197
230
disabled = { ! sortingEnabled }
198
231
style = { style }
@@ -221,16 +254,19 @@ export default class SortableList extends Component {
221
254
this . _container . measure ( ( x , y , width , height , pageX , pageY ) => {
222
255
const rowsLayoutsByKey = { } ;
223
256
let contentHeight = 0 ;
257
+ let contentWidth = 0 ;
224
258
225
259
rowsLayouts . forEach ( ( { rowKey, layout} ) => {
226
260
rowsLayoutsByKey [ rowKey ] = layout ;
227
261
contentHeight += layout . height ;
262
+ contentWidth += layout . width ;
228
263
} ) ;
229
264
230
265
this . setState ( {
231
266
containerLayout : { x, y, width, height, pageX, pageY} ,
232
267
rowsLayouts : rowsLayoutsByKey ,
233
268
contentHeight,
269
+ contentWidth,
234
270
} , ( ) => {
235
271
this . _animateRowsAppearance ( ( ) => ( this . _areRowsAnimated = true ) ) ;
236
272
} ) ;
@@ -304,13 +340,16 @@ export default class SortableList extends Component {
304
340
* Finds a row, which was covered with the moving row’s half.
305
341
*/
306
342
_findRowUnderActiveRow ( ) {
343
+ const { horizontal} = this . props ;
307
344
const { rowsLayouts, activeRowKey, activeRowIndex, order} = this . state ;
308
345
const movingRowLayout = rowsLayouts [ activeRowKey ] ;
346
+ const rowLeftX = this . _activeRowLocation . x
347
+ const rowRightX = rowLeftX + movingRowLayout . width ;
309
348
const rowTopY = this . _activeRowLocation . y ;
310
349
const rowBottomY = rowTopY + movingRowLayout . height ;
311
350
312
351
for (
313
- let currentRowIndex = 0 , y = 0 , rowsCount = order . length ;
352
+ let currentRowIndex = 0 , x = 0 , y = 0 , rowsCount = order . length ;
314
353
currentRowIndex < rowsCount - 1 ;
315
354
currentRowIndex ++
316
355
) {
@@ -319,20 +358,23 @@ export default class SortableList extends Component {
319
358
const nextRowIndex = currentRowIndex + 1 ;
320
359
const nextRowLayout = rowsLayouts [ order [ nextRowIndex ] ] ;
321
360
322
- y = y + currentRowLayout . height ;
361
+ x += currentRowLayout . width ;
362
+ y += currentRowLayout . height ;
323
363
324
- if ( currentRowKey !== activeRowKey &&
325
- ( y - currentRowLayout . height <= rowTopY || currentRowIndex === 0 ) &&
326
- rowTopY <= y - currentRowLayout . height / 3
327
- ) {
364
+ if ( currentRowKey !== activeRowKey && (
365
+ horizontal
366
+ ? ( ( x - currentRowLayout . width <= rowLeftX || currentRowIndex === 0 ) && rowLeftX <= x - currentRowLayout . width / 3 )
367
+ : ( ( y - currentRowLayout . height <= rowTopY || currentRowIndex === 0 ) && rowTopY <= y - currentRowLayout . height / 3 )
368
+ ) ) {
328
369
return {
329
370
rowKey : order [ currentRowIndex ] ,
330
371
rowIndex : currentRowIndex ,
331
372
} ;
332
373
}
333
374
334
- if ( y + nextRowLayout . height / 3 <= rowBottomY &&
335
- ( rowBottomY <= y + nextRowLayout . height || nextRowIndex === rowsCount - 1 )
375
+ if ( horizontal
376
+ ? ( x + nextRowLayout . width / 3 <= rowRightX && ( rowRightX <= x + nextRowLayout . width || nextRowIndex === rowsCount - 1 ) )
377
+ : ( y + nextRowLayout . height / 3 <= rowBottomY && ( rowBottomY <= y + nextRowLayout . height || nextRowIndex === rowsCount - 1 ) )
336
378
) {
337
379
return {
338
380
rowKey : order [ nextRowIndex ] ,
@@ -345,13 +387,22 @@ export default class SortableList extends Component {
345
387
}
346
388
347
389
_scrollOnMove ( e ) {
348
- const { pageY} = e . nativeEvent ;
390
+ const { pageX, pageY} = e . nativeEvent ;
391
+ const { horizontal} = this . props ;
349
392
const { containerLayout} = this . state ;
350
- const inAutoScrollUpArea = pageY < containerLayout . pageY + this . props . autoscrollAreaHeight ;
351
- const inAutoScrollDownArea = pageY > containerLayout . pageY + containerLayout . height - this . props . autoscrollAreaHeight ;
393
+ let inAutoScrollBeginArea = false ;
394
+ let inAutoScrollEndArea = false ;
395
+
396
+ if ( horizontal ) {
397
+ inAutoScrollBeginArea = pageX < containerLayout . pageX + this . props . autoscrollAreaSize ;
398
+ inAutoScrollEndArea = pageX > containerLayout . pageX + containerLayout . width - this . props . autoscrollAreaSize ;
399
+ } else {
400
+ inAutoScrollBeginArea = pageY < containerLayout . pageY + this . props . autoscrollAreaSize ;
401
+ inAutoScrollEndArea = pageY > containerLayout . pageY + containerLayout . height - this . props . autoscrollAreaSize ;
402
+ }
352
403
353
- if ( ! inAutoScrollUpArea &&
354
- ! inAutoScrollDownArea &&
404
+ if ( ! inAutoScrollBeginArea &&
405
+ ! inAutoScrollEndArea &&
355
406
this . _autoScrollInterval !== null
356
407
) {
357
408
this . _stopAutoScroll ( ) ;
@@ -362,33 +413,42 @@ export default class SortableList extends Component {
362
413
return ;
363
414
}
364
415
365
- if ( inAutoScrollUpArea ) {
416
+ if ( inAutoScrollBeginArea ) {
366
417
this . _startAutoScroll ( {
367
418
direction : - 1 ,
368
- shouldScroll : ( ) => this . _contentOffset . y > 0 ,
419
+ shouldScroll : ( ) => this . _contentOffset [ horizontal ? 'x' : 'y' ] > 0 ,
369
420
getScrollStep : ( stepIndex ) => {
370
421
const nextStep = this . _getScrollStep ( stepIndex ) ;
422
+ const contentOffset = this . _contentOffset [ horizontal ? 'x' : 'y' ] ;
371
423
372
- return this . _contentOffset . y - nextStep < 0
373
- ? this . _contentOffset . y
374
- : nextStep ;
424
+ return contentOffset - nextStep < 0 ? contentOffset : nextStep ;
375
425
} ,
376
426
} ) ;
377
- } else if ( inAutoScrollDownArea ) {
427
+ } else if ( inAutoScrollEndArea ) {
378
428
this . _startAutoScroll ( {
379
429
direction : 1 ,
380
430
shouldScroll : ( ) => {
381
- const { contentHeight, containerLayout} = this . state ;
431
+ const { contentHeight, contentWidth , containerLayout} = this . state ;
382
432
383
- return this . _contentOffset . y < contentHeight - containerLayout . height ;
433
+ if ( horizontal ) {
434
+ return this . _contentOffset . x < contentWidth - containerLayout . width
435
+ } else {
436
+ return this . _contentOffset . y < contentHeight - containerLayout . height ;
437
+ }
384
438
} ,
385
439
getScrollStep : ( stepIndex ) => {
386
440
const nextStep = this . _getScrollStep ( stepIndex ) ;
387
- const { contentHeight, containerLayout} = this . state ;
388
-
389
- return this . _contentOffset . y + nextStep > contentHeight - containerLayout . height
390
- ? contentHeight - containerLayout . height - this . _contentOffset . y
391
- : nextStep ;
441
+ const { contentHeight, contentWidth, containerLayout} = this . state ;
442
+
443
+ if ( horizontal ) {
444
+ return this . _contentOffset . x + nextStep > contentWidth - containerLayout . width
445
+ ? contentWidth - containerLayout . width - this . _contentOffset . x
446
+ : nextStep ;
447
+ } else {
448
+ return this . _contentOffset . y + nextStep > contentHeight - containerLayout . height
449
+ ? contentHeight - containerLayout . height - this . _contentOffset . y
450
+ : nextStep ;
451
+ }
392
452
} ,
393
453
} ) ;
394
454
}
@@ -404,13 +464,17 @@ export default class SortableList extends Component {
404
464
}
405
465
406
466
const { activeRowKey} = this . state ;
467
+ const { horizontal} = this . props ;
407
468
let counter = 0 ;
408
469
409
470
this . _autoScrollInterval = setInterval ( ( ) => {
410
471
if ( shouldScroll ( ) ) {
411
- const dy = direction * getScrollStep ( counter ++ ) ;
412
- this . scrollBy ( { dy} ) ;
413
- this . _rows [ activeRowKey ] . moveBy ( { dy} ) ;
472
+ const movement = {
473
+ [ horizontal ? 'dx' : 'dy' ] : direction * getScrollStep ( counter ++ ) ,
474
+ } ;
475
+
476
+ this . scrollBy ( movement ) ;
477
+ this . _rows [ activeRowKey ] . moveBy ( movement ) ;
414
478
} else {
415
479
this . _stopAutoScroll ( ) ;
416
480
}
@@ -462,11 +526,14 @@ export default class SortableList extends Component {
462
526
} ;
463
527
464
528
_onMoveRow = ( e , gestureState , location ) => {
529
+ const prevMovingRowX = this . _activeRowLocation . x ;
465
530
const prevMovingRowY = this . _activeRowLocation . y ;
466
531
const prevMovingDirection = this . _movingDirection ;
467
532
468
533
this . _activeRowLocation = location ;
469
- this . _movingDirection = prevMovingRowY < this . _activeRowLocation . y ;
534
+ this . _movingDirection = this . props . horizontal
535
+ ? prevMovingRowX < this . _activeRowLocation . x
536
+ : prevMovingRowY < this . _activeRowLocation . y ;
470
537
471
538
this . _movingDirectionChanged = prevMovingDirection !== this . _movingDirection ;
472
539
this . _setOrderOnMove ( ) ;
0 commit comments