Skip to content

Commit

Permalink
feat(pages): support optionally render page (leecade#1009)
Browse files Browse the repository at this point in the history
* feat(pages): support optionally render page

re leecade#1004

* fix(ScrollView): android ScrollView will not scrollTo certain offset when props change
  • Loading branch information
ArrayZoneYour authored Jul 9, 2019
1 parent 655eb20 commit f8d66f3
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 61 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"react-native",
"ios"
],
"version": "1.6.0-nightly.1",
"version": "1.6.0-nightly.2",
"description": "Swiper component for React Native.",
"main": "index.js",
"scripts": {
Expand Down
118 changes: 58 additions & 60 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ import {
ActivityIndicator
} from 'react-native'

import ViewPagerAndroid from '@react-native-community/viewpager'

/**
* Default styles
* @type {StyleSheetPropType}
Expand Down Expand Up @@ -129,8 +127,16 @@ export default class extends Component {
autoplayDirection: PropTypes.bool,
index: PropTypes.number,
renderPagination: PropTypes.func,
dotStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.array]),
activeDotStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.array]),
dotStyle: PropTypes.oneOfType([
PropTypes.object,
PropTypes.number,
PropTypes.array
]),
activeDotStyle: PropTypes.oneOfType([
PropTypes.object,
PropTypes.number,
PropTypes.array
]),
dotColor: PropTypes.string,
activeDotColor: PropTypes.string,
/**
Expand Down Expand Up @@ -215,6 +221,11 @@ export default class extends Component {
if (this.props.autoplay && !prevProps.autoplay) {
this.autoplay()
}
if (this.props.children !== prevProps.children) {
this.setState(
this.initState({ ...this.props, index: this.state.index }, true)
)
}
}

initState(props, updateIndex = false) {
Expand All @@ -223,11 +234,15 @@ export default class extends Component {

const initState = {
autoplayEnd: false,
children: null,
loopJump: false,
offset: {}
}

initState.total = props.children ? props.children.length || 1 : 0
// Support Optional render page
initState.children = props.children.filter(child => child)

initState.total = initState.children ? initState.children.length || 1 : 0

if (state.total === initState.total && !updateIndex) {
// retain the index
Expand Down Expand Up @@ -300,11 +315,9 @@ export default class extends Component {
// related to https://github.com/leecade/react-native-swiper/issues/570
// contentOffset is not working in react 0.48.x so we need to use scrollTo
// to emulate offset.
if (Platform.OS === 'ios') {
if (this.initialRender && this.state.total > 1) {
this.scrollView.scrollTo({ ...offset, animated: false })
this.initialRender = false
}
if (this.initialRender && this.state.total > 1) {
this.scrollView.scrollTo({ ...offset, animated: false })
this.initialRender = false
}

this.setState(state)
Expand All @@ -327,7 +340,7 @@ export default class extends Component {
*/
autoplay = () => {
if (
!Array.isArray(this.props.children) ||
!Array.isArray(this.state.children) ||
!this.props.autoplay ||
this.internals.isScrolling ||
this.state.autoplayEnd
Expand Down Expand Up @@ -396,8 +409,8 @@ export default class extends Component {
*/
onScrollEndDrag = e => {
const { contentOffset } = e.nativeEvent
const { horizontal, children } = this.props
const { index } = this.state
const { horizontal } = this.props
const { children, index } = this.state
const { offset } = this.internals
const previousOffset = horizontal ? offset.x : offset.y
const newOffset = horizontal ? contentOffset.x : contentOffset.y
Expand All @@ -416,6 +429,19 @@ export default class extends Component {
* @param {string} dir 'x' || 'y'
*/
updateIndex = (offset, dir, cb) => {
// Android ScrollView will not scrollTo certain offset when props change
const callback = () => {
cb()
if (Platform.OS === 'android') {
this.state.index === 0 &&
this.scrollView.scrollTo({ x: state.width, y: 0, animated: false })
this.state.index === this.state.total - 1 &&
this.scrollView.scrollTo({
x: state.width * this.state.total,
animated: false
})
}
}
const state = this.state
let index = state.index
if (!this.internals.offset)
Expand Down Expand Up @@ -462,14 +488,14 @@ export default class extends Component {
newState.offset = { x: 0, y: 0 }
newState.offset[dir] = offset[dir] + 1
this.setState(newState, () => {
this.setState({ offset: offset }, cb)
this.setState({ offset: offset }, callback)
})
} else {
newState.offset = offset
this.setState(newState, cb)
this.setState(newState, callback)
}
} else {
this.setState(newState, cb)
this.setState(newState, callback)
}
}

Expand All @@ -488,12 +514,7 @@ export default class extends Component {
if (state.dir === 'x') x = diff * state.width
if (state.dir === 'y') y = diff * state.height

if (Platform.OS !== 'ios') {
this.scrollView &&
this.scrollView[animated ? 'setPage' : 'setPageWithoutAnimation'](diff)
} else {
this.scrollView && this.scrollView.scrollTo({ x, y, animated })
}
this.scrollView && this.scrollView.scrollTo({ x, y, animated })

// update scroll state
this.internals.isScrolling = true
Expand Down Expand Up @@ -535,12 +556,7 @@ export default class extends Component {
if (state.dir === 'x') x = diff * state.width
if (state.dir === 'y') y = diff * state.height

if (Platform.OS !== 'ios') {
this.scrollView &&
this.scrollView[animated ? 'setPage' : 'setPageWithoutAnimation'](diff)
} else {
this.scrollView && this.scrollView.scrollTo({ x, y, animated })
}
this.scrollView && this.scrollView.scrollTo({ x, y, animated })

// update scroll state
this.internals.isScrolling = true
Expand Down Expand Up @@ -655,11 +671,11 @@ export default class extends Component {
}

renderTitle = () => {
const child = this.props.children[this.state.index]
const child = this.state.children[this.state.index]
const title = child && child.props && child.props.title
return title ? (
<View style={styles.title}>
{this.props.children[this.state.index].props.title}
{this.state.children[this.state.index].props.title}
</View>
) : null
}
Expand Down Expand Up @@ -689,13 +705,11 @@ export default class extends Component {
}

return (
<TouchableOpacity
<TouchableOpacity
onPress={() => button !== null && this.scrollBy(-1)}
disabled={this.props.disablePrevButton}
>
<View>
{button}
</View>
<View>{button}</View>
</TouchableOpacity>
)
}
Expand Down Expand Up @@ -735,35 +749,20 @@ export default class extends Component {
}

renderScrollView = pages => {
if (Platform.OS === 'ios') {
return (
<ScrollView
ref={this.refScrollView}
{...this.props}
{...this.scrollViewPropOverrides()}
contentContainerStyle={[styles.wrapperIOS, this.props.style]}
contentOffset={this.state.offset}
onScrollBeginDrag={this.onScrollBegin}
onMomentumScrollEnd={this.onScrollEnd}
onScrollEndDrag={this.onScrollEndDrag}
style={this.props.scrollViewStyle}
>
{pages}
</ScrollView>
)
}
return (
<ViewPagerAndroid
<ScrollView
ref={this.refScrollView}
{...this.props}
initialPage={this.props.loop ? this.state.index + 1 : this.state.index}
onPageScrollStateChanged={this.onPageScrollStateChanged}
onPageSelected={this.onScrollEnd}
key={pages.length}
style={[styles.wrapperAndroid, this.props.style]}
{...this.scrollViewPropOverrides()}
contentContainerStyle={[styles.wrapperIOS, this.props.style]}
contentOffset={this.state.offset}
onScrollBeginDrag={this.onScrollBegin}
onMomentumScrollEnd={this.onScrollEnd}
onScrollEndDrag={this.onScrollEndDrag}
style={this.props.scrollViewStyle}
>
{pages}
</ViewPagerAndroid>
</ScrollView>
)
}

Expand All @@ -772,9 +771,8 @@ export default class extends Component {
* @return {object} react-dom
*/
render() {
const { index, total, width, height } = this.state
const { index, total, width, height, children } = this.state
const {
children,
containerStyle,
loop,
loadMinimal,
Expand Down

0 comments on commit f8d66f3

Please sign in to comment.