Last active
June 28, 2017 19:49
-
-
Save RaneWallin/d8addddcaa460f23d91206d4d3625d50 to your computer and use it in GitHub Desktop.
A React Native component that allows the user to control the scrolling content by tapping up and down icons.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by rane on 6/28/17. | |
* TapControlledScrollView | |
* This component allows the user to scroll through content using | |
* up and down icons. The default scroll behavior is disabled. | |
* | |
* scrollDistance property determines how far the view scrolls. Default is 30 | |
* | |
* Usage: | |
* <TapControlledScrollView | |
* scrollDistance="30" | |
* > | |
* ... | |
* </TapControlledScrollView> | |
*/ | |
import React, { Component } from 'react'; | |
import { | |
ScrollView, | |
View, | |
TouchableOpacity, | |
} from 'react-native'; | |
import NativeMethodsMixin from 'NativeMethodsMixin'; | |
import Icon from 'react-native-vector-icons/EvilIcons'; | |
class TapControlledScrollView extends Component { | |
// this.state.scrollPosition is the current y position of the scroll view contents | |
state = ({ | |
scrollPosition: 0, | |
topVisible: false, | |
bottomVisible: false | |
}); | |
doScroll = (direction, distance) => { | |
let way = (direction && direction === 'up') ? -1 : 1; | |
return { x: 0, y: this.state.scrollPosition + distance * way, animated: true } | |
} | |
doIconPress = (direction, distance) => { | |
this.refs['_ScrollView'].scrollTo(this.doScroll(direction, distance)); | |
} | |
watchScroll = (event) => { | |
const nEvent = event.nativeEvent; | |
this.setState({ | |
scrollPosition: nEvent.contentOffset.y | |
}); | |
if ((nEvent.contentOffset.y + | |
nEvent.layoutMeasurement.height) >= | |
nEvent.contentSize.height) { | |
this.setState({ bottomVisible: false }); | |
} else { | |
this.setState({ bottomVisible: true }); | |
} | |
} | |
renderIcon(which) { | |
switch(which) { | |
case 'top': | |
if (this.state.scrollPosition > 0) { | |
return ( | |
<Icon | |
style={ [styles.iconStyle] } | |
name="chevron-up" | |
/> | |
) | |
} | |
break; | |
case 'bottom': | |
if(this.state.bottomVisible) { | |
return ( | |
<Icon | |
style={ styles.iconStyle } | |
name="chevron-down" | |
/> | |
); | |
} | |
break; | |
} | |
} | |
setIcons(contentHeight) { | |
NativeMethodsMixin.measure.call(this.refs['_ScrollView'], | |
(x, y, width, height) => { | |
if(contentHeight > height) { | |
this.setState({ bottomVisible: true }) | |
} else { | |
this.setState({ bottomVisible: false }); | |
} | |
} | |
) | |
} | |
render() { | |
if(!this.props.scrollDistance)this.props.scrollDistance=30; | |
return( | |
<View style={{ flex: 1, flexDirection: 'row' }}> | |
<ScrollView | |
style={{ flex: 1 }} | |
showsHorizontalScrollIndicator={ false } | |
showsVerticalScrollIndicator={ false } | |
onContentSizeChange={ (width, height) => this.setIcons(height) } | |
//onLayout={ (event) => this.setIcons(event) } | |
onScroll={ (event) => this.watchScroll(event) } | |
scrollEnabled={ false } | |
ref="_ScrollView" | |
> | |
{ this.props.children } | |
</ScrollView> | |
<View | |
style={{ | |
flexDirection: 'column', | |
justifyContent: 'space-between' | |
}} | |
> | |
<TouchableOpacity | |
style={{ alignSelf: 'flex-start'}} | |
onPress={ this.doIconPress.bind(this, 'up', this.props.scrollDistance) } | |
> | |
{ this.renderIcon('top') } | |
</TouchableOpacity> | |
<TouchableOpacity | |
style={{ alignSelf: 'flex-end' }} | |
onPress={ this.doIconPress.bind(this, 'down', this.props.scrollDistance) } | |
> | |
{ this.renderIcon('bottom') } | |
</TouchableOpacity> | |
</View> | |
</View> | |
); | |
} | |
} | |
const styles = { | |
iconStyle: { | |
fontSize: 50, | |
textAlign: 'center' | |
} | |
} | |
export default TapControlledScrollView; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment