Skip to content

Commit f064ba2

Browse files
authored
Carousel autoplay (#699)
* added autoplay feature for carousel, with defautl interval of 4 seconds * 1)Added a checkbox for autoplay in the Carousel demo screen. 2)filled the types in Carousel.d.ts * fixed bug when making a loop to the begining: the autoplay moved left all the way back instead of right. fixed by moving right to the cloned first page, then returning silently to the real first page * resets the autoplay timer when the user scrolls manually, in order to avoid auto scroll immediately after manual one
1 parent 7deb323 commit f064ba2

File tree

3 files changed

+82
-7
lines changed

3 files changed

+82
-7
lines changed

demo/src/screens/componentScreens/CarouselScreen.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ class CarouselScreen extends Component {
3030
state = {
3131
limitShownPages: false,
3232
numberOfPagesShown: 7,
33-
currentPage: INITIAL_PAGE
33+
currentPage: INITIAL_PAGE,
34+
autoplay: false
3435
};
3536

3637
onChangePage = currentPage => {
@@ -42,14 +43,15 @@ class CarouselScreen extends Component {
4243
};
4344

4445
render() {
45-
const {limitShownPages, numberOfPagesShown} = this.state;
46+
const {limitShownPages, numberOfPagesShown, autoplay} = this.state;
4647

4748
return (
4849
<ScrollView showsVerticalScrollIndicator={false}>
4950
<Text text30 margin-20>Carousel</Text>
5051

5152
<View marginH-20 marginB-20>
5253
{renderBooleanOption.call(this, 'Limit number of pages shown in page control', 'limitShownPages')}
54+
{renderBooleanOption.call(this, 'autoplay', 'autoplay')}
5355
{renderSliderOption.call(this, 'Number of pages shown', 'numberOfPagesShown', {
5456
min: 5,
5557
max: 10,
@@ -62,7 +64,8 @@ class CarouselScreen extends Component {
6264
key={numberOfPagesShown}
6365
migrate
6466
ref={r => (this.carousel = r)}
65-
// loop
67+
//loop
68+
autoplay={autoplay}
6669
onChangePage={this.onChangePage}
6770
pageWidth={WIDTH}
6871
// itemSpacings={Spacings.s3}
@@ -85,7 +88,7 @@ class CarouselScreen extends Component {
8588
</View>
8689

8790
<View padding-20>
88-
<Carousel containerStyle={{height: 160}} initialPage={INITIAL_PAGE} loop allowAccessibleLayout>
91+
<Carousel containerStyle={{height: 160}} initialPage={INITIAL_PAGE} loop allowAccessibleLayout autoplay={autoplay}>
8992
{_.map(IMAGES, (image, index) => {
9093
return (
9194
<View key={index} flex padding-10 bottom>

src/components/carousel/index.js

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,22 @@ export default class Carousel extends BaseComponent {
8787
/**
8888
* Whether to layout Carousel for accessibility
8989
*/
90-
allowAccessibleLayout: PropTypes.bool
90+
allowAccessibleLayout: PropTypes.bool,
91+
/**
92+
* Whether to switch automatically between the pages
93+
*/
94+
autoplay: PropTypes.bool,
95+
/**
96+
* the amount of ms to wait before switching to the next page, in case autoplay is on
97+
*/
98+
autoplayInterval: PropTypes.number
9199
};
92100

93101
static defaultProps = {
94102
initialPage: 0,
95-
pagingEnabled: true
103+
pagingEnabled: true,
104+
autoplay: false,
105+
autoplayInterval: 4000
96106
};
97107

98108
static pageControlPositions = PAGE_CONTROL_POSITIONS;
@@ -115,10 +125,24 @@ export default class Carousel extends BaseComponent {
115125

116126
componentDidMount() {
117127
Constants.addDimensionsEventListener(this.onOrientationChanged);
128+
129+
if (this.props.autoplay) {
130+
this.startAutoPlay();
131+
}
118132
}
119133

120134
componentWillUnmount() {
121135
Constants.removeDimensionsEventListener(this.onOrientationChanged);
136+
clearInterval(this.autoplayTimer);
137+
}
138+
139+
componentDidUpdate(prevProps, prevState) {
140+
const {autoplay} = this.props;
141+
if (autoplay && !prevProps.autoplay) {
142+
this.startAutoPlay();
143+
} else if (!autoplay && prevProps.autoplay) {
144+
this.stopAutoPlay();
145+
}
122146
}
123147

124148
onOrientationChanged = () => {
@@ -168,6 +192,23 @@ export default class Carousel extends BaseComponent {
168192
}
169193
};
170194

195+
196+
197+
startAutoPlay() {
198+
this.autoplayTimer = setInterval(() => {
199+
this.goToNextPage();
200+
}, this.props.autoplayInterval);
201+
}
202+
203+
stopAutoPlay() {
204+
clearInterval(this.autoplayTimer);
205+
}
206+
207+
resetAutoPlay() {
208+
this.stopAutoPlay();
209+
this.startAutoPlay();
210+
}
211+
171212
goToPage(pageIndex, animated = true) {
172213
this.setState({currentPage: this.getCalcIndex(pageIndex)}, () => this.updateOffset(animated));
173214
}
@@ -243,13 +284,34 @@ export default class Carousel extends BaseComponent {
243284
}
244285
};
245286

287+
goToNextPage() {
288+
const {currentPage} = this.state;
289+
const pagesCount = presenter.getChildrenLength(this.getThemeProps());
290+
const {loop} = this.getThemeProps();
291+
292+
let nextPageIndex;
293+
if (loop) {
294+
nextPageIndex = currentPage + 1;
295+
} else {
296+
nextPageIndex = Math.min(pagesCount - 1, currentPage + 1);
297+
}
298+
299+
this.goToPage(nextPageIndex, true);
300+
301+
// in case of a loop, after we advanced right to the cloned first page,
302+
// we return silently to the real first page
303+
if (loop && currentPage === pagesCount) {
304+
this.goToPage(0, false);
305+
}
306+
}
307+
246308
onScroll = event => {
247309
if (!this.skippedInitialScroll) {
248310
this.skippedInitialScroll = true;
249311
return;
250312
}
251313

252-
const {loop} = this.getThemeProps();
314+
const {loop, autoplay} = this.getThemeProps();
253315
const {pageWidth} = this.state;
254316
const offsetX = event.nativeEvent.contentOffset.x;
255317

@@ -265,6 +327,10 @@ export default class Carousel extends BaseComponent {
265327
this.updateOffset();
266328
}
267329

330+
if (autoplay) { // reset the timer to avoid auto scroll immediately after manual one
331+
this.resetAutoPlay();
332+
}
333+
268334
_.invoke(this.props, 'onScroll', event);
269335
};
270336

typings/components/Carousel.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ export interface CarouselProps {
1515
initialPage?: number;
1616
pageWidth?: number;
1717
itemSpacings?: number;
18+
containerMarginHorizontal?: number;
19+
containerPaddingVertical?: number;
1820
loop?: boolean;
1921
onChangePage?: (page: number, prevPage: number) => void;
2022
onScroll?: (event?: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -23,6 +25,10 @@ export interface CarouselProps {
2325
pageControlPosition?: CarouselPageControlPosition;
2426
showCounter?: boolean;
2527
counterTextStyle?: StyleProp<TextStyle>;
28+
pagingEnabled?: boolean;
29+
allowAccessibleLayout?: boolean;
30+
autoplay?: boolean;
31+
autoplayInterval?: number;
2632
}
2733

2834
export class Carousel extends BaseComponent<CarouselProps> {}

0 commit comments

Comments
 (0)