import React, { ReactElement } from 'react' import { View, Text, TouchableOpacity, StyleSheet, ScrollView, RegisteredStyle, ViewStyle, TextStyle, Dimensions } from 'react-native' import variables from '../../common/styles/variables' import tabStyle from './styles' const styles = StyleSheet.create(tabStyle) interface Props { style?: ViewStyle dataContainerStyle?: ViewStyle dataItemContainerStyle?: ViewStyle dataItemStyle?: ViewStyle activeColor?: string value?: any data?: any[] renderItem?: Function onChange?: Function scrollable?: boolean } interface State {} export class Tab extends React.Component { private _container: any private _scroller: any private _itemLayouts: any[] = [] private _scrollerContentOffsetX: number = 0 static defaultProps = { activeColor: variables.mtdGrayBase, value: null, data: [], onChange: null, scrollable: false, } scrollTo(index: number = 0) { if (!this.props.scrollable) { return } this._container.measure((x, y, width) => { const distance = this.calucateDistance(index, this._scrollerContentOffsetX, width) if (distance == null) { return } this._scroller.scrollTo({ x: distance, y: 0, animated: true }) }) } calucateDistance(index, baseX, containerWidth) { let distance = null // 对缓存的 _itemLayouts 进行排序 const layouts = this._itemLayouts.sort((a: any, b: any) => { return a.index - b.index }) if (!layouts[index] || !layouts[index].layout) { return distance } const targetX = layouts[index].layout.x const targetWidth = layouts[index].layout.width let deltaX = null if (baseX <= 0) { deltaX = - baseX + targetX + targetWidth - containerWidth if (deltaX >= 0) { distance = baseX + deltaX } } if (baseX > 0) { deltaX = - baseX + targetX + targetWidth if (deltaX <= 0) { distance = targetX } else { if (deltaX < targetWidth) { distance = targetX } else { deltaX = deltaX - containerWidth if (deltaX > 0) { distance = baseX + deltaX } } } } return distance } renderItems () { const { dataItemContainerStyle, dataItemStyle, value, data = [], onChange, renderItem, } = this.props return data.map((item, index) => { const active = value === item.value return ( { if (item.disabled) { return } onChange && onChange(item, index) }} onLayout={this.handleLayoutItem.bind(this, index, item)}> { renderItem ? renderItem(item, index, active) : { this.renderItemContent(item, index, active) } } ) }) } renderItemContent = (item, index, active) => { return [ { {item.label} } , ] } handleLayoutItem = (index, item, e) => { const existed = this._itemLayouts.some((layoutItem: any) => { return layoutItem.index === index }) !existed && e && e.nativeEvent && this._itemLayouts.push({ index, layout: e.nativeEvent.layout }) } handleScroll = (e) => { e && e.nativeEvent && e.nativeEvent.contentOffset && (this._scrollerContentOffsetX = e.nativeEvent.contentOffset.x) } render () { const { scrollable, style, dataContainerStyle } = this.props const itemViews = this.renderItems() return ( { this._container = c }} style={[styles.container, style]}> { scrollable ? { this._scroller = c }} horizontal showsHorizontalScrollIndicator={false} scrollEventThrottle={0} onScroll={this.handleScroll}> {itemViews} : {itemViews} } ) } }