import * as React from 'react'; import { NativeScrollEvent, NativeSyntheticEvent, ScrollView, StyleSheet, Text, View, } from 'react-native'; import { picker } from '../../_styles/themes/default.components'; import { innerScaleSize } from '../../_styles/themes/responsive'; interface IMDPickerColumnProps { itemHeight?: number; onPickerSelected: ( selectIndex: number, selectContext: any, columnIndex: number ) => void; column: any[]; width: number; offsetY: number; columnIndex: number; selectIndex: number; invalidItemIndexs: number[]; } interface IMDPickerColumnState { selectIndex: number; } export default class PickerColumn extends React.Component< IMDPickerColumnProps, IMDPickerColumnState > { public static defaultProps = { itemHeight: innerScaleSize(40 * 2), onPickerSelected: null, invalidItemIndexs: [], }; constructor (props: IMDPickerColumnProps) { super(props); this.state = { selectIndex: 0, }; } private selectIndex = 0; private oldIndex = 0; private isDragAnima: boolean = false; private scroller: ScrollView | null = null; private isNewProps: boolean = false; public componentWillReceiveProps (nextProps: IMDPickerColumnProps) { if ( JSON.stringify(nextProps.column) !== JSON.stringify(this.props.column) || nextProps.selectIndex !== this.selectIndex ) { this.selectIndex = this.checkValidIndex(nextProps.selectIndex, nextProps); this.isNewProps = true; this.setState({ selectIndex: nextProps.selectIndex, }); } } public componentWillMount () { this.selectIndex = this.checkValidIndex(this.props.selectIndex, this.props); this.isNewProps = true; this.setState({ selectIndex: this.props.selectIndex, }); } public componentDidMount () { this.scrollTopIndex(this.selectIndex); } public componentDidUpdate () { this.scrollTopIndex(this.selectIndex); } public render () { return ( { this.scroller = scrollView; }} style={[styles.column, { width: this.props.width }]} removeClippedSubviews={true} automaticallyAdjustContentInsets={false} showsVerticalScrollIndicator={false} contentInset={{ top: this.props.offsetY, left: 0, bottom: this.props.offsetY, right: 0, }} contentOffset={{ x: 0, y: -this.props.offsetY }} onScrollBeginDrag={() => { this.onScrollBeginDrag(); }} onScrollEndDrag={(e: NativeSyntheticEvent) => { this.onScrollEndDrag(e); }} onMomentumScrollEnd={(e: NativeSyntheticEvent) => { this.onMomentumScrollEnd(e); }} onMomentumScrollBegin={(e: NativeSyntheticEvent) => { this.onMomentumScrollBegin(e); }} > {this.renderList(this.props.column)} ); } private renderList (column: any[]) { return column.map((item, index) => { return this.renderItem(item, index); }); } private renderItem (item: any, index: number) { return ( {item.text || item.label} ); } private onScrollBeginDrag () { // console.log('ttttpicker','onScrollBeginDrag',this.props.columnIndex,this.isDragAnima) } private onScrollEndDrag (e: NativeSyntheticEvent) { const pIndex = this.caculateScrollIndex(e); setTimeout(() => { if (!this.isDragAnima) { this.updateSelectIndex(pIndex); this.props.onPickerSelected( this.selectIndex, this.getActiveValue(), this.props.columnIndex ); } }, 200); } private onMomentumScrollBegin (e: NativeSyntheticEvent) { this.isDragAnima = true; } private onMomentumScrollEnd (e: NativeSyntheticEvent) { const pIndex = this.caculateScrollIndex(e); setTimeout(() => { if (this.isDragAnima) { this.isDragAnima = false; this.updateSelectIndex(pIndex); this.props.onPickerSelected( this.selectIndex, this.getActiveValue(), this.props.columnIndex ); } }, 200); } private scrollToPisiton (x: number, y: number) { if (!this.isNewProps && Math.abs(this.selectIndex - this.oldIndex) < 2) { this.scroller!.scrollResponderScrollTo({ x, y, animated: true }); } else { if (this.isNewProps) { this.isNewProps = false; } this.scroller!.scrollResponderScrollTo({ x, y, animated: false }); } } private scrollTopIndex (index: number) { this.scrollToPisiton(0, index * this.props.itemHeight! - this.props.offsetY); } private caculateScrollIndex (e: NativeSyntheticEvent) { let pIndex = Math.round( (e.nativeEvent.contentOffset.y + this.props.offsetY) / this.props.itemHeight! ); if (pIndex < 0) { pIndex = 0; } else if (pIndex >= this.props.column.length) { pIndex = this.props.column.length - 1; } return pIndex; } private updateSelectIndex (index: number) { this.oldIndex = this.selectIndex; this.selectIndex = this.checkValidIndex(index, this.props); this.setState({ selectIndex: this.selectIndex, }); } private checkValidIndex (index: number, props: IMDPickerColumnProps) { while (props.invalidItemIndexs.indexOf(index) >= 0) { ++index; } if (index >= props.column.length) { index = 0; } return index; } private getActiveValue () { const item: any = this.props.column[this.selectIndex]; return item; } } const styles = StyleSheet.create({ column: { display: 'flex', flexDirection: 'column', overflow: 'hidden', }, item: { width: '100%', alignItems: 'center', justifyContent: 'center', }, text: { textAlign: 'center', fontSize: picker.fontSize, marginLeft: 10, marginRight: 10, }, });