@@ -10,7 +10,6 @@ import Text from '../text';
10
10
import PageControl from '../pageControl' ;
11
11
import * as presenter from './CarouselPresenter' ;
12
12
13
-
14
13
const PAGE_CONTROL_POSITIONS = {
15
14
OVER : 'over' ,
16
15
UNDER : 'under'
@@ -40,6 +39,15 @@ export default class Carousel extends BaseComponent {
40
39
* the spacing between the items
41
40
*/
42
41
itemSpacings : PropTypes . number ,
42
+ /**
43
+ * Horizontal margin for the container
44
+ */
45
+ containerMarginHorizontal : PropTypes . number ,
46
+ /**
47
+ * Vertical padding for the container.
48
+ * Sometimes needed when there are overflows that are cut in Android.
49
+ */
50
+ containerPaddingVertical : PropTypes . number ,
43
51
/**
44
52
* if true, will have infinite scroll
45
53
*/
@@ -84,7 +92,6 @@ export default class Carousel extends BaseComponent {
84
92
85
93
static defaultProps = {
86
94
initialPage : 0 ,
87
- itemSpacings : 16 ,
88
95
pagingEnabled : true
89
96
} ;
90
97
@@ -95,7 +102,7 @@ export default class Carousel extends BaseComponent {
95
102
96
103
this . carousel = React . createRef ( ) ;
97
104
const defaultPageWidth = props . loop ?
98
- Constants . screenWidth : props . pageWidth + props . itemSpacings || Constants . screenWidth ;
105
+ Constants . screenWidth : props . pageWidth + this . getItemSpacings ( props ) || Constants . screenWidth ;
99
106
100
107
this . state = {
101
108
containerWidth : undefined ,
@@ -115,21 +122,39 @@ export default class Carousel extends BaseComponent {
115
122
}
116
123
117
124
onOrientationChanged = ( ) => {
118
- if ( ! this . props . pageWidth || this . props . loop ) {
125
+ const { pageWidth, loop} = this . getThemeProps ( ) ;
126
+ if ( ! pageWidth || loop ) {
119
127
this . orientationChange = true ;
120
128
// HACK: setting to containerWidth for Android's call when view disappear
121
129
this . setState ( { pageWidth : this . state . containerWidth || Constants . screenWidth } ) ;
122
130
}
123
131
} ;
124
132
125
133
generateStyles ( ) {
126
- this . styles = createStyles ( this . props ) ;
134
+ this . styles = createStyles ( this . getThemeProps ( ) ) ;
135
+ }
136
+
137
+ getItemSpacings ( props ) {
138
+ const { itemSpacings = 16 } = props ;
139
+ return itemSpacings ;
140
+ }
141
+
142
+ getContainerMarginHorizontal = ( ) => {
143
+ const { containerMarginHorizontal = 0 } = this . getThemeProps ( ) ;
144
+ return containerMarginHorizontal ;
145
+ }
146
+
147
+ // TODO: RN 61.5 - try to remove this from the children and move to the ScrollView's contentContainerStyle
148
+ // style={{overflow: 'visible'}} does not work in ScrollView on Android, maybe it will be fixed in the future
149
+ getContainerPaddingVertical = ( ) => {
150
+ const { containerPaddingVertical = 0 } = this . getThemeProps ( ) ;
151
+ return containerPaddingVertical ;
127
152
}
128
153
129
154
updateOffset = ( animated = false ) => {
130
155
const centerOffset = Constants . isIOS && this . shouldUsePageWidth ( ) ?
131
156
( Constants . screenWidth - this . state . pageWidth ) / 2 : 0 ;
132
- const x = presenter . calcOffset ( this . props , this . state ) - centerOffset ;
157
+ const x = presenter . calcOffset ( this . getThemeProps ( ) , this . state ) - centerOffset ;
133
158
134
159
if ( this . carousel ) {
135
160
this . carousel . current . scrollTo ( { x, animated} ) ;
@@ -157,45 +182,47 @@ export default class Carousel extends BaseComponent {
157
182
}
158
183
159
184
getSnapToOffsets = ( ) => {
160
- const { itemSpacings} = this . props ;
161
185
const { containerWidth, pageWidth} = this . state ;
162
186
163
187
if ( this . shouldEnablePagination ( ) ) {
164
188
return undefined ;
165
189
}
166
190
167
191
if ( containerWidth ) {
168
- const spacings = pageWidth === containerWidth ? 0 : itemSpacings ;
192
+ const spacings = pageWidth === containerWidth ? 0 : this . getItemSpacings ( this . getThemeProps ( ) ) ;
169
193
const initialBreak = pageWidth - ( containerWidth - pageWidth - spacings ) / 2 ;
170
- const snapToOffsets = _ . times ( presenter . getChildrenLength ( this . props ) , index => initialBreak + index * pageWidth ) ;
194
+ const snapToOffsets = _ . times ( presenter . getChildrenLength ( this . props ) ,
195
+ index => initialBreak + index * pageWidth + this . getContainerMarginHorizontal ( ) ) ;
171
196
return snapToOffsets ;
172
197
}
173
198
} ;
174
199
175
200
shouldUsePageWidth ( ) {
176
- const { loop, pageWidth} = this . props ;
201
+ const { loop, pageWidth} = this . getThemeProps ( ) ;
177
202
return ! loop && pageWidth ;
178
203
}
179
204
180
205
shouldEnablePagination ( ) {
181
- const { pagingEnabled} = this . props ;
206
+ const { pagingEnabled} = this . getThemeProps ( ) ;
182
207
return pagingEnabled && ! this . shouldUsePageWidth ( ) ;
183
208
}
184
209
185
210
onContainerLayout = ( { nativeEvent : { layout : { width : containerWidth } } } ) => {
186
211
const update = { containerWidth} ;
212
+ const { pageWidth} = this . getThemeProps ( ) ;
187
213
188
- if ( ! this . props . pageWidth ) {
214
+ if ( ! pageWidth ) {
189
215
update . pageWidth = containerWidth ;
190
216
update . initialOffset = {
191
- x : presenter . calcOffset ( this . props , { currentPage : this . state . currentPage , pageWidth : containerWidth } )
217
+ x : presenter . calcOffset ( this . getThemeProps ( ) , { currentPage : this . state . currentPage , pageWidth : containerWidth } )
192
218
} ;
193
219
}
194
220
this . setState ( update ) ;
195
221
} ;
196
222
197
223
shouldAllowAccessibilityLayout ( ) {
198
- return this . props . allowAccessibleLayout && Constants . accessibility . isScreenReaderEnabled ;
224
+ const { allowAccessibleLayout} = this . getThemeProps ( ) ;
225
+ return allowAccessibleLayout && Constants . accessibility . isScreenReaderEnabled ;
199
226
}
200
227
201
228
onContentSizeChange = ( ) => {
@@ -222,13 +249,13 @@ export default class Carousel extends BaseComponent {
222
249
return ;
223
250
}
224
251
225
- const { loop} = this . props ;
252
+ const { loop} = this . getThemeProps ( ) ;
226
253
const { pageWidth} = this . state ;
227
254
const offsetX = event . nativeEvent . contentOffset . x ;
228
255
229
256
if ( offsetX >= 0 ) {
230
257
if ( ! this . orientationChange ) { // Avoid new calculation on orientation change
231
- const newPage = presenter . calcPageIndex ( offsetX , this . props , pageWidth ) ;
258
+ const newPage = presenter . calcPageIndex ( offsetX , this . getThemeProps ( ) , pageWidth ) ;
232
259
this . setState ( { currentPage : newPage } ) ;
233
260
}
234
261
this . orientationChange = false ;
@@ -243,12 +270,20 @@ export default class Carousel extends BaseComponent {
243
270
244
271
renderChild = ( child , key ) => {
245
272
if ( child ) {
246
- const paddingLeft = this . shouldUsePageWidth ( ) ? this . props . itemSpacings : undefined ;
273
+ const paddingLeft = this . shouldUsePageWidth ( ) ? this . getItemSpacings ( this . getThemeProps ( ) ) : undefined ;
247
274
const index = Number ( key ) ;
248
275
const length = presenter . getChildrenLength ( this . props ) ;
276
+ const containerMarginHorizontal = this . getContainerMarginHorizontal ( ) ;
277
+ const marginLeft = index === 0 ? containerMarginHorizontal : 0 ;
278
+ const marginRight = index === length - 1 ? containerMarginHorizontal : 0 ;
279
+ const paddingVertical = this . getContainerPaddingVertical ( ) ;
249
280
250
281
return (
251
- < View style = { { width : this . state . pageWidth , paddingLeft} } key = { key } collapsable = { false } >
282
+ < View
283
+ style = { { width : this . state . pageWidth , paddingLeft, marginLeft, marginRight, paddingVertical} }
284
+ key = { key }
285
+ collapsable = { false }
286
+ >
252
287
{ this . shouldAllowAccessibilityLayout ( ) && ! Number . isNaN ( index ) &&
253
288
< View style = { this . styles . hiddenText } >
254
289
< Text > { `page ${ index + 1 } out of ${ length } ` } </ Text >
@@ -261,7 +296,7 @@ export default class Carousel extends BaseComponent {
261
296
} ;
262
297
263
298
renderChildren ( ) {
264
- const { children, loop} = this . props ;
299
+ const { children, loop} = this . getThemeProps ( ) ;
265
300
const length = presenter . getChildrenLength ( this . props ) ;
266
301
267
302
const childrenArray = React . Children . map ( children , ( child , index ) => {
@@ -277,16 +312,10 @@ export default class Carousel extends BaseComponent {
277
312
}
278
313
279
314
renderPageControl ( ) {
280
- const {
281
- pageControlPosition,
282
- pageControlProps,
283
- size = 6 ,
284
- spacing = 8 ,
285
- color = Colors . dark20 ,
286
- inactiveColor = Colors . dark60
287
- } = this . getThemeProps ( ) ;
288
-
315
+ const { pageControlPosition, pageControlProps = { } } = this . getThemeProps ( ) ;
316
+
289
317
if ( pageControlPosition ) {
318
+ const { size = 6 , spacing = 8 , color = Colors . dark20 , inactiveColor = Colors . dark60 , ...others } = pageControlProps ;
290
319
const pagesCount = presenter . getChildrenLength ( this . props ) ;
291
320
const containerStyle =
292
321
pageControlPosition === PAGE_CONTROL_POSITIONS . UNDER
@@ -300,7 +329,7 @@ export default class Carousel extends BaseComponent {
300
329
containerStyle = { containerStyle }
301
330
inactiveColor = { inactiveColor }
302
331
color = { color }
303
- { ...pageControlProps }
332
+ { ...others }
304
333
numOfPages = { pagesCount }
305
334
currentPage = { this . getCalcIndex ( this . state . currentPage ) }
306
335
/>
@@ -309,7 +338,7 @@ export default class Carousel extends BaseComponent {
309
338
}
310
339
311
340
renderCounter ( ) {
312
- const { pageWidth, showCounter, counterTextStyle} = this . props ;
341
+ const { pageWidth, showCounter, counterTextStyle} = this . getThemeProps ( ) ;
313
342
const { currentPage} = this . state ;
314
343
const pagesCount = presenter . getChildrenLength ( this . props ) ;
315
344
@@ -325,7 +354,7 @@ export default class Carousel extends BaseComponent {
325
354
}
326
355
327
356
renderAccessibleLayout ( ) {
328
- const { containerStyle, children} = this . props ;
357
+ const { containerStyle, children} = this . getThemeProps ( ) ;
329
358
330
359
return (
331
360
< View style = { containerStyle } onLayout = { this . onContainerLayout } >
@@ -346,13 +375,14 @@ export default class Carousel extends BaseComponent {
346
375
}
347
376
348
377
renderCarousel ( ) {
349
- const { containerStyle, itemSpacings , ...others } = this . props ;
378
+ const { containerStyle, ...others } = this . getThemeProps ( ) ;
350
379
const { initialOffset} = this . state ;
351
- const scrollContainerStyle = this . shouldUsePageWidth ( ) ? { paddingRight : itemSpacings } : undefined ;
380
+ const scrollContainerStyle = this . shouldUsePageWidth ( ) ? { paddingRight : this . getItemSpacings ( this . getThemeProps ( ) ) } : undefined ;
352
381
const snapToOffsets = this . getSnapToOffsets ( ) ;
382
+ const marginBottom = Math . max ( 0 , this . getContainerPaddingVertical ( ) - 16 ) ;
353
383
354
384
return (
355
- < View style = { containerStyle } onLayout = { this . onContainerLayout } >
385
+ < View style = { [ { marginBottom } , containerStyle ] } onLayout = { this . onContainerLayout } >
356
386
< ScrollView
357
387
{ ...others }
358
388
ref = { this . carousel }
@@ -381,7 +411,7 @@ export default class Carousel extends BaseComponent {
381
411
}
382
412
}
383
413
384
- function createStyles ( ) {
414
+ function createStyles ( { containerPaddingVertical = 0 } ) {
385
415
return StyleSheet . create ( {
386
416
counter : {
387
417
paddingHorizontal : 8 ,
@@ -398,7 +428,7 @@ function createStyles() {
398
428
alignSelf : 'center'
399
429
} ,
400
430
pageControlContainerStyleUnder : {
401
- marginVertical : 16
431
+ marginVertical : 16 - containerPaddingVertical
402
432
} ,
403
433
hiddenText : {
404
434
position : 'absolute' ,
0 commit comments