Skip to content

Commit 0dbe448

Browse files
committed
Carousel - refactor and add support for orientation change; fix for Carousel-related components (ActionBar's demo screen, MainScreen)
1 parent c52d0e4 commit 0dbe448

File tree

4 files changed

+62
-47
lines changed

4 files changed

+62
-47
lines changed

demo/src/screens/MainScreen.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,6 @@ const styles = StyleSheet.create({
336336
justifyContent: 'center',
337337
},
338338
page: {
339-
width: Constants.screenWidth,
340339
flex: 1,
341340
paddingLeft: 24,
342341
},

demo/src/screens/componentScreens/ActionBarScreen.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import _ from 'lodash';
22
import React, {Component} from 'react';
33
import {Alert, StyleSheet} from 'react-native';
4-
import {Constants, Colors, Typography, View, ActionBar, PageControl, Carousel} from 'react-native-ui-lib'; //eslint-disable-line
4+
import {Colors, Typography, View, ActionBar, PageControl, Carousel} from 'react-native-ui-lib'; //eslint-disable-line
55
import cameraSelected from '../../assets/icons/cameraSelected.png';
66
import video from '../../assets/icons/video.png';
77
import tags from '../../assets/icons/tags.png';
@@ -90,12 +90,10 @@ export default class ActionBarScreen extends Component {
9090

9191
const styles = StyleSheet.create({
9292
page: {
93-
width: Constants.screenWidth,
94-
flex: 1,
93+
flex: 1
9594
},
9695
pageControl: {
97-
zIndex: 1,
98-
width: Constants.screenWidth,
96+
zIndex: 1
9997
},
10098
absoluteContainer: {
10199
position: 'absolute',

src/components/carousel/CarouselPresenter.js

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,15 @@
11
import _ from 'lodash';
22
import {Constants} from '../../helpers';
33

4-
export function getDirectionOffset(offset, props) {
5-
let fixedOffset = offset;
6-
7-
if (Constants.isRTL && Constants.isAndroid) {
8-
const {loop, pageWidth} = props;
9-
const totalWidth = ((getChildrenLength(props) - 1) + (loop ? 2 : 0)) * pageWidth;
10-
fixedOffset = Math.abs(totalWidth - offset);
11-
}
12-
13-
return fixedOffset;
14-
}
154

165
export function getChildrenLength(props) {
176
const length = _.get(props, 'children.length') || 0;
187
return length;
198
}
209

2110
export function calcOffset(props, state) {
22-
const {currentPage} = state;
23-
const {pageWidth, loop} = props;
11+
const {currentPage, pageWidth} = state;
12+
const {loop} = props;
2413

2514
const actualCurrentPage = loop ? currentPage + 1 : currentPage;
2615

@@ -30,9 +19,21 @@ export function calcOffset(props, state) {
3019
return offset;
3120
}
3221

33-
export function calcPageIndex(offset, props) {
22+
export function getDirectionOffset(offset, props, pageWidth) {
23+
let fixedOffset = offset;
24+
25+
if (Constants.isRTL && Constants.isAndroid) {
26+
const {loop} = props;
27+
const totalWidth = ((getChildrenLength(props) - 1) + (loop ? 2 : 0)) * pageWidth;
28+
fixedOffset = Math.abs(totalWidth - offset);
29+
}
30+
31+
return fixedOffset;
32+
}
33+
34+
export function calcPageIndex(offset, props, pageWidth) {
3435
const pagesCount = getChildrenLength(props);
35-
const {pageWidth, loop} = props;
36+
const {loop} = props;
3637
const pageIndexIncludingClonedPages = Math.round(offset / pageWidth);
3738

3839
let actualPageIndex;
@@ -45,16 +46,15 @@ export function calcPageIndex(offset, props) {
4546
return actualPageIndex;
4647
}
4748

48-
export function isOutOfBounds(offset, props) {
49-
const {pageWidth} = props;
49+
export function isOutOfBounds(offset, props, pageWidth) {
5050
const length = getChildrenLength(props);
5151
const minLimit = 1;
5252
const maxLimit = ((length + 1) * pageWidth) - 1;
5353

5454
return !_.inRange(offset, minLimit, maxLimit);
5555
}
5656

57-
// todo: need to support more cases of page width in loop mode
57+
// TODO: need to support more cases of page width in loop mode
5858
export function calcCarouselWidth(props) {
5959
const {pageWidth, loop} = props;
6060
let length = getChildrenLength(props);

src/components/carousel/index.js

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import _ from 'lodash';
2-
import React from 'react';
32
import PropTypes from 'prop-types';
3+
import React from 'react';
44
import {ScrollView, StyleSheet} from 'react-native';
55
import {Constants} from '../../helpers';
66
import {BaseComponent} from '../../commons';
7+
import View from '../view';
78
import * as presenter from './CarouselPresenter';
89

910

@@ -42,26 +43,41 @@ export default class Carousel extends BaseComponent {
4243
};
4344

4445
static defaultProps = {
45-
initialPage: 0,
46-
pageWidth: Constants.screenWidth
46+
initialPage: 0
4747
};
4848

4949
constructor(props) {
5050
super(props);
5151

52+
const defaultPageWidth = props.pageWidth || Constants.screenWidth;
53+
5254
this.state = {
5355
currentPage: props.initialPage,
5456
currentStandingPage: props.initialPage,
55-
initialOffset: {x: presenter.calcOffset(props, {currentPage: props.initialPage})}
57+
pageWidth: defaultPageWidth,
58+
initialOffset: {x: presenter.calcOffset(props, {currentPage: props.initialPage, pageWidth: defaultPageWidth})}
5659
};
5760
}
5861

59-
generateStyles() {
60-
this.styles = createStyles(this.props);
62+
componentDidMount() {
63+
Constants.addDimensionsEventListener(this.onOrientationChanged);
6164
}
6265

63-
get pageWidth() {
64-
return Math.floor(this.props.pageWidth);
66+
componentWillUnmount() {
67+
Constants.removeDimensionsEventListener(this.onOrientationChanged);
68+
}
69+
70+
onOrientationChanged = () => {
71+
if (!this.props.pageWidth) {
72+
this.setState({
73+
pageWidth: Constants.screenWidth,
74+
initialOffset: {x: presenter.calcOffset(this.props, {currentPage: this.state.currentPage, pageWidth: Constants.screenWidth})}
75+
});
76+
}
77+
}
78+
79+
generateStyles() {
80+
this.styles = createStyles(this.props);
6581
}
6682

6783
updateOffset = (animated = false) => {
@@ -104,40 +120,42 @@ export default class Carousel extends BaseComponent {
104120
}
105121

106122
const {loop} = this.props;
107-
const offsetX = presenter.getDirectionOffset(event.nativeEvent.contentOffset.x, this.props);
123+
const {pageWidth} = this.state;
124+
const offsetX = presenter.getDirectionOffset(event.nativeEvent.contentOffset.x, this.props, pageWidth);
108125

109126
if (offsetX >= 0) {
110-
const newPage = presenter.calcPageIndex(offsetX, this.props);
111-
127+
const newPage = presenter.calcPageIndex(offsetX, this.props, pageWidth);
112128
this.setState({currentPage: newPage});
113129
}
114130

115-
if (loop && presenter.isOutOfBounds(offsetX, this.props)) {
131+
if (loop && presenter.isOutOfBounds(offsetX, this.props, pageWidth)) {
116132
this.updateOffset();
117133
}
118134

119135
_.invoke(this.props, 'onScroll', event);
120136
}
121137

122-
cloneChild(child) {
123-
if (!child.key) {
124-
return child;
125-
}
126-
127-
return React.cloneElement(child, {
128-
key: `${child.key}-clone`,
129-
});
138+
renderChild = (child, key) => {
139+
return (
140+
<View style={{width: this.state.pageWidth}} key={key}>
141+
{child}
142+
</View>
143+
);
130144
}
131145

132146
renderChildren() {
133147
const {children, loop} = this.props;
134148
const length = presenter.getChildrenLength(this.props);
135-
const childrenArray = React.Children.toArray(children);
149+
150+
const childrenArray = React.Children.map(children, (child, index) => {
151+
return this.renderChild(child, `${index}`);
152+
});
136153

137154
if (loop) {
138-
childrenArray.unshift(this.cloneChild(children[length - 1]));
139-
childrenArray.push(this.cloneChild(children[0]));
155+
childrenArray.unshift(this.renderChild(children[length - 1], `${length - 1}-clone`));
156+
childrenArray.push(this.renderChild(children[0], `${0}-clone`));
140157
}
158+
141159
return childrenArray;
142160
}
143161

0 commit comments

Comments
 (0)