/* eslint-disable react/no-string-refs */
import _delay from 'lodash/delay';
import React, { Component } from 'react';
import {
StyleSheet,
View,
ScrollView,
Platform,
PanResponder,
TouchableOpacity,
StyleProp,
ViewStyle,
} from 'react-native';
import { Utils, TYText } from 'tuya-panel-kit';
const { convertX: cx, convertY: cy } = Utils.RatioUtils;
const Item = datas => {
const {
item,
idx,
selectIndex,
themeColor,
itemWidth,
marginRight,
switchChange,
numberOfLines,
itemStyles,
} = datas;
const style = [itemsStyle.container, itemStyles];
const isSelected = selectIndex === idx;
const { key, title } = item;
return (
switchChange(idx)}
>
{title}
);
};
Item.defaultProps = { onPress: null };
const itemsStyle = StyleSheet.create({
container: {
alignItems: 'center',
alignSelf: 'center',
justifyContent: 'center',
},
title: {
backgroundColor: 'transparent',
color: 'rgba(0,0,0,.5)',
fontSize: cx(16),
textAlign: 'center',
},
});
interface ShufflingListProps {
data: any;
themeColor?: string;
contentWidth: number;
marginRight: number;
itemWidth: number;
numberOfLines?: number;
itemStyle?: StyleProp;
onIndexChange?: (selectIdx: number) => void;
}
interface ShufflingListState {
selectIndex: number;
canTouch: boolean;
canSet: boolean;
move: boolean;
}
export default class ShufflingList extends Component {
static defaultProps = {
data: [],
themeColor: '#00CC99',
contentWidth: cx(290),
itemWidth: cx(90),
marginRight: cx(10),
numberOfLines: 1,
itemStyle: {},
};
constructor(props: ShufflingListProps) {
super(props);
this.state = {
selectIndex: 0,
canTouch: true,
canSet: true,
move: false,
};
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetPanResponder: () => false,
onPanResponderGrant: (e, gestureState) => this._handleResponderGrant(e, gestureState),
onPanResponderRelease: (e, gestureState) => this._handleResponderRelease(e, gestureState),
});
this.beforeX = 0;
this.after = 0;
}
componentDidMount() {
setTimeout(() => {
this._scrollToItem(this.state.selectIndex);
}, 1);
}
_panResponder: any;
beforeX: number;
after: number;
refs: any;
_handleResponderGrant = (e: any, gestureState: any) => {
const { moveX } = gestureState;
this.beforeX = moveX;
};
_handleResponderRelease = (e: any, gestureState: any) => {
const { moveX } = gestureState;
const { canTouch } = this.state;
if (!canTouch) return;
this.after = moveX;
this._startScroll();
};
_startScroll = () => {
const { selectIndex } = this.state;
const { data } = this.props;
const num = data.length;
if (this.after - this.beforeX > 0) {
if (selectIndex === 0) return;
this.setState(
{
selectIndex: selectIndex - 1,
},
() => this._scrollToItem(selectIndex - 1)
);
} else if (this.beforeX - this.after > 0) {
if (selectIndex === num - 1) return;
this.setState(
{
selectIndex: selectIndex + 1,
},
() => this._scrollToItem(selectIndex + 1)
);
}
};
switchChange = (i: number) => {
this.setState(
{
selectIndex: i,
canTouch: false,
},
() => this.setState({ canTouch: true })
);
this._scrollToItem(i);
};
_scrollToItem = (i: number) => {
const { data, itemWidth } = this.props;
if (data.length < 2) return;
this.refs.list.scrollTo({
animated: true,
x: i === 0 ? 0 : itemWidth * i,
y: 0,
});
Platform.OS === 'android' &&
_delay(
() =>
this.refs.list.scrollTo({
animated: true,
x: i === 0 ? 0 : itemWidth * i,
y: 0,
}),
1
);
this.props.onIndexChange(i);
};
_renderRow = (item: any, index: number) => {
const { themeColor, itemWidth, marginRight, itemStyle, numberOfLines } = this.props;
return (
- {
this.setState({ selectIndex: i });
this._scrollToItem(i);
}}
marginRight={marginRight}
itemWidth={itemWidth}
itemStyles={itemStyle}
numberOfLines={numberOfLines}
/>
);
};
_onMomentumScrollEnd = (e: any) => {
const { canSet, move } = this.state;
const { data, itemWidth } = this.props;
const offsetX = e.nativeEvent.contentOffset.x; // 滑动距离
if (offsetX <= itemWidth / 2) {
move &&
this.setState({ selectIndex: 0 }, () => {
this._scrollToItem(0);
});
} else {
const idx = Math.ceil((offsetX - itemWidth / 2) / itemWidth);
const index = idx >= data.length - 1 ? data.length - 1 : idx;
move &&
this.setState({ selectIndex: index }, () => {
this._scrollToItem(index);
});
}
this.setState({ move: false, canSet: !canSet });
};
renderList = () => {
const { data, itemWidth } = this.props;
return (
{
this.setState({ move: true });
}}
onMomentumScrollEnd={this._onMomentumScrollEnd}
>
{data.map((item: any, idx: number) => this._renderRow(item, idx))}
);
};
render() {
return {this.renderList()};
}
}