diff --git a/.gitignore b/.gitignore index dc34d7c..e925287 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ npm-debug.log node_modules .DS_Store .swp +.idea \ No newline at end of file diff --git a/demo/test.gif b/demo/test.gif new file mode 100644 index 0000000..6257532 Binary files /dev/null and b/demo/test.gif differ diff --git a/index.js b/index.js index 9b0fd3c..535fb3d 100644 --- a/index.js +++ b/index.js @@ -1,209 +1,233 @@ -'use strict'; - -import React, {Component} from 'react'; -import ReactNative, { - StyleSheet, - Text, - View, - ScrollView, - Dimensions, - Platform, - ViewPropTypes +import React from 'react'; +import styled from 'styled-components'; +import { + View, + Text, + ScrollView, + Dimensions, + Platform, } from 'react-native'; import PropTypes from 'prop-types'; +const Container = styled.View` + height: ${props => props.wrapperHeight}; + flex: 1; + overflow: hidden; + align-self: center; + width: ${props => props.wrapperWidth}; + background-color: ${props => props.wrapperBackground}; +`; +export const HighLightView = styled.View` + position: absolute; + top: ${props => (props.wrapperHeight - props.itemHeight) / 2}; + height: ${props => props.itemHeight}; + width: ${props => props.highlightWidth}; + border-top-color: ${props => props.highlightColor}; + border-bottom-color: ${props => props.highlightColor}; + border-top-width: ${props => props.highlightBorderWidth}px; + border-bottom-width: ${props => props.highlightBorderWidth}px; +`; +export const SelectedItem = styled.View` + height: 30px; + justify-content: center; + align-items: center; + height: ${props => props.itemHeight}; +`; const deviceWidth = Dimensions.get('window').width; -const deviceHeight = Dimensions.get('window').height; - -export default class ScrollPicker extends Component { - - static propTypes = { - style:ViewPropTypes.style, - dataSource:PropTypes.array.isRequired, - selectedIndex:PropTypes.number, - onValueChange:PropTypes.func, - renderItem:PropTypes.func, - highlightColor:PropTypes.string, - - itemHeight:PropTypes.number, - wrapperHeight:PropTypes.number, - }; - - constructor(props){ - super(props); - - this.itemHeight = this.props.itemHeight || 30; - this.wrapperHeight = this.props.wrapperHeight || (this.props.style ? this.props.style.height : 0) ||this.itemHeight * 5; - - this.state = { - selectedIndex: this.props.selectedIndex || 0 - }; +export default class ScrollPicker extends React.Component { + constructor() { + super(); + this.onMomentumScrollBegin = this.onMomentumScrollBegin.bind(this); + this.onMomentumScrollEnd = this.onMomentumScrollEnd.bind(this); + this.onScrollBeginDrag = this.onScrollBeginDrag.bind(this); + this.onScrollEndDrag = this.onScrollEndDrag.bind(this); + this.state = { + selectedIndex: 1, } + } - componentDidMount(){ - if(this.props.selectedIndex){ - setTimeout(() => { - this.scrollToIndex(this.props.selectedIndex); - }, 0); - } + componentDidMount() { + if (typeof this.props.selectedIndex !== 'undefined') { + this.scrollToIndex(this.props.selectedIndex); } - componentWillUnmount(){ - this.timer && clearTimeout(this.timer); - } - - render(){ - let {header, footer} = this._renderPlaceHolder(); - let highlightWidth = (this.props.style ? this.props.style.width : 0) || deviceWidth; - let highlightColor = this.props.highlightColor || '#333'; - let wrapperStyle = { - height:this.wrapperHeight, - flex:1, - backgroundColor:'#fafafa', - overflow:'hidden', - }; + } - let highlightStyle = { - position:'absolute', - top:(this.wrapperHeight - this.itemHeight) / 2, - height:this.itemHeight, - width:highlightWidth, - borderTopColor:highlightColor, - borderBottomColor:highlightColor, - borderTopWidth:StyleSheet.hairlineWidth, - borderBottomWidth:StyleSheet.hairlineWidth, - }; - - return ( - - - { this.sview = sview; }} - bounces={false} - showsVerticalScrollIndicator={false} - onMomentumScrollBegin={this._onMomentumScrollBegin.bind(this)} - onMomentumScrollEnd={this._onMomentumScrollEnd.bind(this)} - onScrollBeginDrag={this._onScrollBeginDrag.bind(this)} - onScrollEndDrag={this._onScrollEndDrag.bind(this)} - > - {header} - {this.props.dataSource.map(this._renderItem.bind(this))} - {footer} - - - ) + componentWillUnmount() { + if (this.timer) { + clearTimeout(this.timer); } - - _renderPlaceHolder(){ - let h = (this.wrapperHeight - this.itemHeight) / 2; - let header = ; - let footer = ; - return {header, footer}; + } + + render() { + const {header, footer} = this.renderPlaceHolder(); + return ( + + + { + this.sview = sview; + }} + bounces={false} + showsVerticalScrollIndicator={false} + onTouchStart={this.props.onTouchStart} + onMomentumScrollBegin={this.onMomentumScrollBegin} + onMomentumScrollEnd={this.onMomentumScrollEnd} + onScrollBeginDrag={this.onScrollBeginDrag} + onScrollEndDrag={this.onScrollEndDrag} + > + {header} + {this.props.dataSource.map(this.renderItem.bind(this))} + {footer} + + + ); + } + + renderPlaceHolder() { + const height = (this.props.wrapperHeight - this.props.itemHeight) / 2; + const header = ; + const footer = ; + return {header, footer}; + } + + renderItem(data, index) { + const isSelected = index === this.state.selectedIndex; + const item = {data}; + + return ( + + {item} + + ); + } + + scrollFix(e) { + let verticalY = 0; + const h = this.props.itemHeight; + if (e.nativeEvent.contentOffset) { + verticalY = e.nativeEvent.contentOffset.y; } - - _renderItem(data, index){ - let isSelected = index === this.state.selectedIndex; - let item = {data}; - - if(this.props.renderItem){ - item = this.props.renderItem(data, index, isSelected); - } - - return ( - - {item} - - ); + const selectedIndex = Math.round(verticalY / h); + const verticalElem = selectedIndex * h; + if (verticalElem !== verticalY) { + // using scrollTo in ios, onMomentumScrollEnd will be invoked + if (Platform.OS === 'ios') { + this.isScrollTo = true; + } + if (this.sview) { + this.sview.scrollTo({y: verticalElem}); + } } - _scrollFix(e){ - let y = 0; - let h = this.itemHeight; - if(e.nativeEvent.contentOffset){ - y = e.nativeEvent.contentOffset.y; - } - let selectedIndex = Math.round(y / h); - let _y = selectedIndex * h; - if(_y !== y){ - // using scrollTo in ios, onMomentumScrollEnd will be invoked - if(Platform.OS === 'ios'){ - this.isScrollTo = true; - } - this.sview.scrollTo({y:_y}); - } - if(this.state.selectedIndex === selectedIndex){ - return; - } - // onValueChange - if(this.props.onValueChange){ - let selectedValue = this.props.dataSource[selectedIndex]; - this.setState({ - selectedIndex:selectedIndex, - }); - this.props.onValueChange(selectedValue, selectedIndex); - } + if (this.state.selectedIndex === selectedIndex) { + return; } - _onScrollBeginDrag(){ - this.dragStarted = true; - if(Platform.OS === 'ios'){ - this.isScrollTo = false; - } - this.timer && clearTimeout(this.timer); + this.setState({ + selectedIndex, + }); + // onValueChange + if (this.props.onValueChange) { + const selectedValue = this.props.dataSource[selectedIndex]; + this.props.onValueChange(selectedValue, selectedIndex); } - _onScrollEndDrag(e){ - this.dragStarted = false; - // if not used, event will be garbaged - let _e = { - nativeEvent:{ - contentOffset:{ - y: e.nativeEvent.contentOffset.y, - }, - }, - }; - this.timer && clearTimeout(this.timer); - this.timer = setTimeout( - () => { - if(!this.momentumStarted && !this.dragStarted){ - this._scrollFix(_e, 'timeout'); - } - }, - 10 - ); + } + + onScrollBeginDrag() { + this.dragStarted = true; + if (Platform.OS === 'ios') { + this.isScrollTo = false; } - _onMomentumScrollBegin(e){ - this.momentumStarted = true; - this.timer && clearTimeout(this.timer); + if (this.timer) { + clearTimeout(this.timer); } - _onMomentumScrollEnd(e){ - this.momentumStarted = false; - if(!this.isScrollTo && !this.momentumStarted && !this.dragStarted){ - this._scrollFix(e); - } + } + + onScrollEndDrag(e) { + this.props.onScrollEndDrag(); + this.dragStarted = false; + // if not used, event will be garbaged + const element = { + nativeEvent: { + contentOffset: { + y: e.nativeEvent.contentOffset.y, + }, + }, + }; + if (this.timer) { + clearTimeout(this.timer); } - - scrollToIndex(ind){ - this.setState({ - selectedIndex:ind, - }); - let y = this.itemHeight * ind; - this.sview.scrollTo({y:y}); + this.timer = setTimeout( + () => { + if (!this.momentumStarted && !this.dragStarted) { + this.scrollFix(element, 'timeout'); + } + }, + 10, + ); + } + + onMomentumScrollBegin() { + this.momentumStarted = true; + if (this.timer) { + clearTimeout(this.timer); } + } - getSelected(){ - let selectedIndex = this.state.selectedIndex; - let selectedValue = this.props.dataSource[selectedIndex]; - return selectedValue; + onMomentumScrollEnd(e) { + this.props.onMomentumScrollEnd(); + this.momentumStarted = false; + if (!this.isScrollTo && !this.momentumStarted && !this.dragStarted) { + this.scrollFix(e); } + } + + scrollToIndex(ind) { + this.setState({ + selectedIndex: ind, + }); + const y = this.props.itemHeight * ind; + setTimeout(() => { + if (this.sview) { + this.sview.scrollTo({y}); + } + }, 0); + } } - -let styles = StyleSheet.create({ - itemWrapper: { - height:30, - justifyContent: 'center', - alignItems: 'center', - }, - itemText:{ - color:'#999', - }, - itemTextSelected:{ - color:'#333', - }, -}); +ScrollPicker.propTypes = { + style: PropTypes.object, + dataSource: PropTypes.array, + selectedIndex: PropTypes.number, + onValueChange: PropTypes.func, + renderItem: PropTypes.func, + highlightColor: PropTypes.string, + itemHeight: PropTypes.number, + wrapperBackground: PropTypes.string, + wrapperWidth: PropTypes.number, + wrapperHeight: PropTypes.number, + highlightWidth: PropTypes.number, + highlightBorderWidth: PropTypes.number, + itemTextStyle: PropTypes.object, + activeItemTextStyle: PropTypes.object, + onMomentumScrollEnd: PropTypes.func, + onScrollEndDrag: PropTypes.func, +}; +ScrollPicker.defaultProps = { + dataSource: [1, 2, 3], + itemHeight: 60, + wrapperBackground: '#FFFFFF', + wrapperHeight: 180, + wrapperWidth: 150, + highlightWidth: deviceWidth, + highlightBorderWidth: 2, + highlightColor: '#333', + onMomentumScrollEnd: () => { + }, + onScrollEndDrag: () => { + }, + itemTextStyle: {fontSize: 20, lineHeight: 26, textAlign: 'center', color: '#B4B4B4'}, + activeItemTextStyle: {fontSize: 20, lineHeight: 26, textAlign: 'center', color: '#222121'} +}; \ No newline at end of file diff --git a/package.json b/package.json index 3d74dc2..e3c4bd9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "react-native-picker-scrollview", - "version": "0.1.0", + "name": "react-native-wheel-scroll-picker", + "version": "0.2.4", "description": "a pure js picker, each option item customizable", "main": "index.js", "scripts": { @@ -8,17 +8,17 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/veizz/react-native-picker-scrollview.git" + "url": "https://github.com/yasemincidem/react-native-picker-scrollview" }, "keywords": [ "picker", "react-native", "react-native-picker" ], - "author": "veizz", + "author": "yasemin", "license": "MIT", "bugs": { - "url": "https://github.com/veizz/react-native-picker-scrollview/issues" + "url": "https://github.com/yasemincidem/react-native-picker-scrollview/issues" }, - "homepage": "https://github.com/veizz/react-native-picker-scrollview#readme" + "homepage": "https://github.com/yasemincidem/react-native-picker-scrollview#readme" } diff --git a/readme.md b/readme.md index 5b8e36c..45003d8 100644 --- a/readme.md +++ b/readme.md @@ -1,52 +1,48 @@ -## react-native-picker-scrollview +## react-native-wheel-scroll-picker a pure js picker, each option item customizable -![example](./res/demo.gif) +![example](./demo/test.gif) ### usage ```shell -npm install react-native-picker-scrollview --save +npm install react-native-wheel-scroll-picker --save ``` ```jsx import React, {Component} from 'react'; -import ScrollPicker from 'react-native-picker-scrollview'; +import ScrollPicker from 'react-native-wheel-scroll-picker'; export default class SimpleExample extends Component { render() { return( - {this.sp = sp}} - - dataSource={[ - 'a', - 'b', - 'c', - 'd', - ]} - selectedIndex={0} - itemHeight={50} - wrapperHeight={250} - highlightColor={'#d8d8d8'} - renderItem={(data, index, isSelected) => { - // - }} - onValueChange={(data, selectedIndex) => { - // - }} - /> + { + // + }} + onValueChange={(data, selectedIndex) => { + // + }} + wrapperHeight={180} + wrapperWidth={150} + wrapperBackground={'#FFFFFF'} + itemHeight={60} + highlightColor={'#d8d8d8'} + highlightBorderWidth={2} + activeItemColor={'#222121'} + itemColor={'#B4B4B4'} + /> ) } - - - // - someOtherFunc(){ - this.sp.scrollToIndex(2); // select 'c' - let selectedValue = this.sp.getSelected(); // returns 'c' - } } ``` diff --git a/res/demo.gif b/res/demo.gif deleted file mode 100644 index 8c43606..0000000 Binary files a/res/demo.gif and /dev/null differ