如何安装tracker(封装Picker组件)
import {
View,
Text,
TouchableWithoutFeedback,
TouchableOpacity,
FlatList,
} from 'react-native'
import React,{
PureComponent,
Component,
} from 'react'
import _ from 'lodash'
import styleSheet, {getThemeColor} from '../utils/styleSheet'
import {Callback} from "modern/types/lang";
import Modal from './Modal'
import {getScreenHeight, getScreenWidth} from "modern/consts/ui-common";
const styles = styleSheet.create({
container:{
flex:1,
backgroundColor: 0x00000074,
alignItems: 'center',
justifyContent: 'flex-end',
},
contentView:{
flexDirection:'row',
justifyContent: 'space-around',
backgroundColor: 'white'
},
stage:{
top:0,
bottom:0,
left:0,
right:0,
position:'absolute',
zIndex:10,
flexDirection:'row',
justifyContent: 'space-around',
},
maskView:{
left:0,
right:0,
position:'absolute',
top:0,
bottom:0,
zIndex:0,
justifyContent:'space-between'
},
emptyView:{
height:50,
flexDirection:'row',
justifyContent:'space-between',
paddingHorizontal:20,
backgroundColor: 'white',
},
maskStyle:{
width:'100%',
// backgroundColor:'rgba(232,232,232,0.9)',
borderColor:"rgba(232,232,232,0.9)",
backgroundColor:'white'
},
midMaskStyle:{
backgroundColor:'#f9f9f9'
},
headerBtnView:{
height:50,justifyContent: 'center'
},
cancelText:{
fontSize:16,color:'gray'
}
})
function DefaultView (){
return (
<View style={{flex:1,justifyContent:'center',alignItems: 'center'}}>
<Text>暂无数据</Text>
</View>
)
}
interface ISHeadProps {
customHead:any,
confirm:Callback,
hide:Callback,
headOptions:any
}
const Head:React.FC<ISHeadProps> = React.memo(({customHead,confirm,hide,headOptions})=>{
if(customHead && _.isFunction(customHead)){
return customHead(confirm,hide)
}
const {
cancelTextStyle={},
cancelBtnView={},
confirmBtnView={},
confirmTextStyle={},
leftText='取消',
rightText='确定',
headerContainView={},
} = headOptions
return <View style={[styles.emptyView,headerContainView]}>
<TouchableOpacity style={[styles.headerBtnView,cancelBtnView]} onPress={hide}>
<Text style={[styles.cancelText,cancelTextStyle]}>{leftText}</Text>
</TouchableOpacity>
<TouchableOpacity onPress={confirm} style={[styles.headerBtnView,confirmBtnView]}>
<Text style={[{color:getThemeColor(),fontSize:16},confirmTextStyle]}>{rightText}</Text>
</TouchableOpacity>
</View>
})
interface ISEmpty {
hide:Callback
}
const Empty:React.FC<ISEmpty> = React.memo(({hide})=>{
return <TouchableWithoutFeedback onPress={hide}>
<View style={{flex:1,width:getScreenWidth()}} />
</TouchableWithoutFeedback>
})
interface ISMaskView {
maxLength:number,
itemHeihght:number,
maskOptions:any,
}
const MaskView:React.FC<ISMaskView> = React.memo(({maxLength,itemHeihght,maskOptions={}})=>{
const {
upMaskView,
bottomMaskView,
midMaskView
} = maskOptions
const mid = Math.floor(maxLength/2)
return <View style={[styles.maskView]}>
<View style={[styles.maskStyle,{height:itemHeihght*mid,borderBottomWidth:0.5,},upMaskView]}/>
<View style={[styles.midMaskStyle,{height:itemHeihght},midMaskView]} />
<View style={[styles.maskStyle,{height:itemHeihght*mid,borderTopWidth:0.5,},bottomMaskView]}/>
</View>
})
interface ISourceType {
id:string,
name:string,
sub?:ISourceType[]
[propname:string]:any,
}
interface ISitemOptons {
itemHeihght?:number,
maxLength?:5 | 7 | 9,
ActiveTextStyle?:any,
normalTextStyle?:any,
}
interface ISProps {
sourceData:ISourceType[],
cancel?:Callback,
confirm:Callback,
selectData:ISourceType[],
pickerType:'scroll' | 'click' | 'all',
customHead:any,
headOptions:any,
maskOptions:any,
itemOptons:ISitemOptons,
isLinkage:boolean,
renderListEmptyComponent:Callback,
emptyOptions:any,
wrapOptions:any,
EmptyView:any
}
interface ISState {
visible:boolean,
floor:number,
}
function WithHeadAndMethod(WrapComponent:any){
return class PickerAlertView extends PureComponent<ISProps,ISState>{
public selectedData:ISourceType[] =[]
public static defaultProps = {
itemOptons:{},
selectData:[],
headOptions:{},
pickerType:'all',
maskOptions:{},
isLinkage:false,
emptyOptions:{},
wrapOptions:{
stageView:{}
}
}
constructor(props:ISProps) {
super(props);
this.state = {
visible:false,
floor:this.getMaxFloor(),
}
}
public getMaxFloor = ()=>{
const { sourceData,isLinkage } = this.props
if(_.isEmpty(sourceData)) return 0
if(isLinkage) return sourceData.length
let floor:number = 1
function treeData(arr:any){
const sub:any = arr.find((item:any)=>item?.sub?.length > 0)
if(sub){
floor = floor 1
let arr2:any = []
arr.forEach((item:any)=>{
if(item?.sub?.length>0){
arr2 = arr2.concat(item.sub)
}
})
treeData(arr2)
}
}
treeData(sourceData)
return floor
}
public show = ()=>{
this.setState({visible:true})
}
public confirm = ()=>{
const { confirm=_.noop } = this.props
this.hide()
confirm(this.selectedData)
}
public hide = ()=>{
const { cancel=_.noop } = this.props
cancel()
this.setState({visible:false})
}
public getSelected = ()=>this.selectedData
private setSelected = (item:ISourceType,floor:number)=>{
this.selectedData[floor] = item
}
public componentDidUpdate(preProps,prevState,snapshot){
if(!_.isEqual(this.props.sourceData,preProps.sourceData)){
this.setState({
floor:this.getMaxFloor()
})
}
}
public render(){
const {
visible,
floor,
} = this.state
const {
selectData,
sourceData,
pickerType,
customHead,
headOptions,
maskOptions,
itemOptons,
isLinkage,
renderListEmptyComponent,
emptyOptions,
wrapOptions,
EmptyView = DefaultView
} = this.props
const { stageView } = wrapOptions
if(!visible) return null
const {
maxLength=9,
itemHeihght=50,
ActiveTextStyle={},
normalTextStyle={}
} = itemOptons
return (
<Modal
visible={visible}
animationType="slide"
transparent={true}
>
<View
style={styles.container}
>
<Empty hide={this.hide}/>
<View style={{ width:getScreenWidth()}}>
<Head
headOptions={headOptions}
hide={this.hide}
confirm={this.confirm}
customHead={customHead}
/>
<View style={[{height:itemHeihght*maxLength},styles.contentView]}>
<View style={[styles.stage,stageView]}>
{
_.isEmpty(sourceData) ?<EmptyView/>:
<WrapComponent
sourceList={sourceData}
setSelect={this.setSelected}
floor={floor}
currentFloor={0}
maxLength={maxLength}
defaultSelected = {selectData}
itemHeihght={itemHeihght}
ActiveTextStyle={ActiveTextStyle}
normalTextStyle={normalTextStyle}
pickerType={pickerType}
originData={sourceData}
isLinkage={isLinkage}
renderListEmptyComponent={renderListEmptyComponent}
emptyOptions={emptyOptions}
/>
}
</View>
<MaskView
maxLength={maxLength}
itemHeihght={itemHeihght}
maskOptions={maskOptions}
/>
</View>
</View>
</View>
</Modal>
)
}
}
}
interface ISItemProps {
sourceList:ISourceType[],
setSelect:Callback,
floor:number,
currentFloor:number,
maxLength: 5 | 7 | 9,
defaultSelected:ISourceType[],
itemHeihght:number,
ActiveTextStyle:any,
normalTextStyle:any,
pickerType:string,
isLinkage:boolean,
originData:any,
renderListEmptyComponent:Callback,
emptyOptions:any
}
interface ISItemState {
nextData:ISourceType[],
currentChoose:ISourceType,
initialScrollIndex:number,
renderList:any[],
surerefresh:any
}
class PickerAlertViewItem extends PureComponent<ISItemProps,ISItemState> {
public scrollView:any
public flatEl:any
public currentItem:any
public itemEL:any
public config:any = {
waitForInteraction: false,
itemVisiblePercentThreshold:100,
}
public constructor(props:ISItemProps) {
super(props);
this.state = {
nextData:this.defaultRenderList(),
currentChoose:this.getDefaultChoose(),
initialScrollIndex:this.getInitialScrollIndex(),
renderList:this.flatListData(),
surerefresh:null,
}
}
public getInitialScrollIndex = ()=>{
const {defaultSelected,currentFloor,sourceList } = this.props
if(_.isEmpty(defaultSelected)) return 0
const initIndex = sourceList.findIndex(item=>String(item.id) === String(defaultSelected[currentFloor]?.id))
return initIndex<0?0:initIndex
}
public defaultRenderList = ()=>{
const { currentFloor, floor, defaultSelected, sourceList,isLinkage,originData} = this.props
if(isLinkage){
return originData[currentFloor 1]
}
const getNoFefault = ()=>this.props.sourceList?.[0]?.sub || []
const getDefaultList = ()=>{
if(currentFloor 1 === floor ) return []
return sourceList.find(value=>value.id === defaultSelected[currentFloor].id)?.sub || getNoFefault()
}
return _.isEmpty(defaultSelected)?getNoFefault():getDefaultList()
}
public getDefaultChoose = ()=>{
const { defaultSelected, currentFloor, sourceList } = this.props
return _.isEmpty(defaultSelected)?sourceList?.[0]:(sourceList.find(item=>item.id === defaultSelected?.[currentFloor]?.id) || sourceList?.[0])
}
public mid = ()=>{
const { maxLength } = this.props
return Math.floor(maxLength/2)
}
public flatListData = (nextData:any[])=>{
const { sourceList,currentFloor,originData ,isLinkage} = this.props
const mid = this.mid()
const arr = Array(mid).fill({id:'',name:'',sub:[]})
let currentData = nextData?nextData:sourceList
if(isLinkage){
currentData = originData[currentFloor]
}
if(currentData.length === 0 || !currentData) return []
return [...arr,...currentData,...arr]
}
public getItemLayout = (data:any,index:any) =>{
const { itemHeihght } = this.props
return {length: itemHeihght, offset: itemHeihght * index, index}
}
public renderItem = ({item,index,separators}:any)=>{
const { itemHeihght ,ActiveTextStyle,normalTextStyle,pickerType} = this.props
const {currentChoose} = this.state
const itemPress = (pickerType === 'scroll' || item.id === currentChoose?.id)?_.noop:this.clickItem
return <TouchableWithoutFeedback onPress={()=>itemPress(item,index)}>
<Text
numberOfLines={1}
style={[
{
height:itemHeihght,
textAlign:'center',
lineHeight:itemHeihght,
opacity:0.8,
paddingHorizontal: 10,
},
item.id === currentChoose?.id?ActiveTextStyle:normalTextStyle
]}
>{item.name}</Text>
</TouchableWithoutFeedback>
}
public clickItem =(item:ISourceType,index:any)=>{
const mid = this.mid()
if(index<mid) return
if(!item) return
this.scrollToIndex(index)
this.chooseItem(index,item)
}
public scrollToIndex = (index:any)=>{
const { renderList } = this.state
if(renderList.length === 0 || !renderList) return
if(this.flatEl){
this.flatEl.scrollToIndex({
index,
viewPosition:0.5,
animated:true
})
}
}
public chooseItem = (index:number,item:ISourceType)=>{
const { setSelect,currentFloor,isLinkage } = this.props
setSelect(item,currentFloor)
if(isLinkage) return
this.setState({
currentChoose:item || {},
nextData:item?.sub || []
},()=>{
if(this.itemEL) this.itemEL.reduction()
})
}
public reduction=()=>{
const currentChoose = this.props.sourceList?.[0] || {}
const nextData = currentChoose?.sub || []
const mid = this.mid()
this.setState({
currentChoose,
nextData,
renderList:this.flatListData(),
surerefresh:Date.now() Math.random(),
})
}
public componentDidMount(){
this.initSelected()
}
public componentDidUpdate(preProp:ISItemProps,preState:ISItemState){
const mid = this.mid()
if(this.state.surerefresh !== preState.surerefresh){
_.delay(()=>this.clickItem(this.state.currentChoose,mid),100)
}
}
public initSelected = ()=>{
const {setSelect,currentFloor } = this.props
const { currentChoose } = this.state
setSelect(currentChoose,currentFloor)
if(this.flatEl) this.flatEl.recordInteraction()
}
public renderListEmptyComponent = (data:any)=>{
const {renderListEmptyComponent,itemHeihght,emptyOptions,maxLength} = this.props
if(renderListEmptyComponent) return renderListEmptyComponent()
return <View style={{height:itemHeihght*maxLength,justifyContent:'center',alignItems: 'center'}}>
<Text
numberOfLines={1}
style={[
{
height:itemHeihght,
textAlign:'center',
lineHeight:itemHeihght,
opacity:0.8,
paddingHorizontal: 10,
}
]}
>{emptyOptions.descText || '暂无数据'}</Text>
</View>
}
public render(){
const {
floor,
currentFloor,
setSelect,
defaultSelected,
maxLength,
itemHeihght=50,
ActiveTextStyle,
normalTextStyle,
pickerType,
isLinkage,
originData,
emptyOptions,
} = this.props
const {
nextData,
initialScrollIndex,
renderList,
} = this.state
const nextFloor = currentFloor 1
return (
<>
<FlatList
style={{flex:1}}
ref={ref=>this.flatEl = ref}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
keyExtractor={(item: object, index: number) => String(index)}
renderItem={this.renderItem}
viewabilityConfig={this.config}
data={renderList}
getItemLayout={this.getItemLayout}
initialScrollIndex={initialScrollIndex}
onMomentumScrollEnd={this._moveEnd}
scrollEnabled={pickerType === 'click'?false:true}
ListEmptyComponent={this.renderListEmptyComponent}
/>
{
floor > nextFloor ?
<PickerAlertViewItem
ref={ref=>this.itemEL = ref}
sourceList={nextData}
floor={floor}
setSelect={setSelect}
currentFloor={nextFloor}
defaultSelected={defaultSelected}
maxLength={maxLength}
itemHeihght={itemHeihght}
ActiveTextStyle={ActiveTextStyle}
normalTextStyle={normalTextStyle}
pickerType={pickerType}
isLinkage={isLinkage}
originData={originData}
emptyOptions={emptyOptions}
/>:
null
}
</>
)
}
private _moveEnd=(e)=>{
const {itemHeihght} = this.props
const { renderList } = this.state
const contentOffset = e.nativeEvent.contentOffset.y;
const mid = this.mid()
const index = Math.round(contentOffset/itemHeihght) mid
this.clickItem(renderList[index],index)
}
}
export default WithHeadAndMethod(PickerAlertViewItem)
,今天小编就来说说关于如何安装tracker?下面更多详细答案一起来看看吧!
如何安装tracker
import {
View,
Text,
TouchableWithoutFeedback,
TouchableOpacity,
FlatList,
} from 'react-native'
import React,{
PureComponent,
Component,
} from 'react'
import _ from 'lodash'
import styleSheet, {getThemeColor} from '../utils/styleSheet'
import {Callback} from "modern/types/lang";
import Modal from './Modal'
import {getScreenHeight, getScreenWidth} from "modern/consts/ui-common";
const styles = styleSheet.create({
container:{
flex:1,
backgroundColor: 0x00000074,
alignItems: 'center',
justifyContent: 'flex-end',
},
contentView:{
flexDirection:'row',
justifyContent: 'space-around',
backgroundColor: 'white'
},
stage:{
top:0,
bottom:0,
left:0,
right:0,
position:'absolute',
zIndex:10,
flexDirection:'row',
justifyContent: 'space-around',
},
maskView:{
left:0,
right:0,
position:'absolute',
top:0,
bottom:0,
zIndex:0,
justifyContent:'space-between'
},
emptyView:{
height:50,
flexDirection:'row',
justifyContent:'space-between',
paddingHorizontal:20,
backgroundColor: 'white',
},
maskStyle:{
width:'100%',
// backgroundColor:'rgba(232,232,232,0.9)',
borderColor:"rgba(232,232,232,0.9)",
backgroundColor:'white'
},
midMaskStyle:{
backgroundColor:'#f9f9f9'
},
headerBtnView:{
height:50,justifyContent: 'center'
},
cancelText:{
fontSize:16,color:'gray'
}
})
function DefaultView (){
return (
<View style={{flex:1,justifyContent:'center',alignItems: 'center'}}>
<Text>暂无数据</Text>
</View>
)
}
interface ISHeadProps {
customHead:any,
confirm:Callback,
hide:Callback,
headOptions:any
}
const Head:React.FC<ISHeadProps> = React.memo(({customHead,confirm,hide,headOptions})=>{
if(customHead && _.isFunction(customHead)){
return customHead(confirm,hide)
}
const {
cancelTextStyle={},
cancelBtnView={},
confirmBtnView={},
confirmTextStyle={},
leftText='取消',
rightText='确定',
headerContainView={},
} = headOptions
return <View style={[styles.emptyView,headerContainView]}>
<TouchableOpacity style={[styles.headerBtnView,cancelBtnView]} onPress={hide}>
<Text style={[styles.cancelText,cancelTextStyle]}>{leftText}</Text>
</TouchableOpacity>
<TouchableOpacity onPress={confirm} style={[styles.headerBtnView,confirmBtnView]}>
<Text style={[{color:getThemeColor(),fontSize:16},confirmTextStyle]}>{rightText}</Text>
</TouchableOpacity>
</View>
})
interface ISEmpty {
hide:Callback
}
const Empty:React.FC<ISEmpty> = React.memo(({hide})=>{
return <TouchableWithoutFeedback onPress={hide}>
<View style={{flex:1,width:getScreenWidth()}} />
</TouchableWithoutFeedback>
})
interface ISMaskView {
maxLength:number,
itemHeihght:number,
maskOptions:any,
}
const MaskView:React.FC<ISMaskView> = React.memo(({maxLength,itemHeihght,maskOptions={}})=>{
const {
upMaskView,
bottomMaskView,
midMaskView
} = maskOptions
const mid = Math.floor(maxLength/2)
return <View style={[styles.maskView]}>
<View style={[styles.maskStyle,{height:itemHeihght*mid,borderBottomWidth:0.5,},upMaskView]}/>
<View style={[styles.midMaskStyle,{height:itemHeihght},midMaskView]} />
<View style={[styles.maskStyle,{height:itemHeihght*mid,borderTopWidth:0.5,},bottomMaskView]}/>
</View>
})
interface ISourceType {
id:string,
name:string,
sub?:ISourceType[]
[propname:string]:any,
}
interface ISitemOptons {
itemHeihght?:number,
maxLength?:5 | 7 | 9,
ActiveTextStyle?:any,
normalTextStyle?:any,
}
interface ISProps {
sourceData:ISourceType[],
cancel?:Callback,
confirm:Callback,
selectData:ISourceType[],
pickerType:'scroll' | 'click' | 'all',
customHead:any,
headOptions:any,
maskOptions:any,
itemOptons:ISitemOptons,
isLinkage:boolean,
renderListEmptyComponent:Callback,
emptyOptions:any,
wrapOptions:any,
EmptyView:any
}
interface ISState {
visible:boolean,
floor:number,
}
function WithHeadAndMethod(WrapComponent:any){
return class PickerAlertView extends PureComponent<ISProps,ISState>{
public selectedData:ISourceType[] =[]
public static defaultProps = {
itemOptons:{},
selectData:[],
headOptions:{},
pickerType:'all',
maskOptions:{},
isLinkage:false,
emptyOptions:{},
wrapOptions:{
stageView:{}
}
}
constructor(props:ISProps) {
super(props);
this.state = {
visible:false,
floor:this.getMaxFloor(),
}
}
public getMaxFloor = ()=>{
const { sourceData,isLinkage } = this.props
if(_.isEmpty(sourceData)) return 0
if(isLinkage) return sourceData.length
let floor:number = 1
function treeData(arr:any){
const sub:any = arr.find((item:any)=>item?.sub?.length > 0)
if(sub){
floor = floor 1
let arr2:any = []
arr.forEach((item:any)=>{
if(item?.sub?.length>0){
arr2 = arr2.concat(item.sub)
}
})
treeData(arr2)
}
}
treeData(sourceData)
return floor
}
public show = ()=>{
this.setState({visible:true})
}
public confirm = ()=>{
const { confirm=_.noop } = this.props
this.hide()
confirm(this.selectedData)
}
public hide = ()=>{
const { cancel=_.noop } = this.props
cancel()
this.setState({visible:false})
}
public getSelected = ()=>this.selectedData
private setSelected = (item:ISourceType,floor:number)=>{
this.selectedData[floor] = item
}
public componentDidUpdate(preProps,prevState,snapshot){
if(!_.isEqual(this.props.sourceData,preProps.sourceData)){
this.setState({
floor:this.getMaxFloor()
})
}
}
public render(){
const {
visible,
floor,
} = this.state
const {
selectData,
sourceData,
pickerType,
customHead,
headOptions,
maskOptions,
itemOptons,
isLinkage,
renderListEmptyComponent,
emptyOptions,
wrapOptions,
EmptyView = DefaultView
} = this.props
const { stageView } = wrapOptions
if(!visible) return null
const {
maxLength=9,
itemHeihght=50,
ActiveTextStyle={},
normalTextStyle={}
} = itemOptons
return (
<Modal
visible={visible}
animationType="slide"
transparent={true}
>
<View
style={styles.container}
>
<Empty hide={this.hide}/>
<View style={{ width:getScreenWidth()}}>
<Head
headOptions={headOptions}
hide={this.hide}
confirm={this.confirm}
customHead={customHead}
/>
<View style={[{height:itemHeihght*maxLength},styles.contentView]}>
<View style={[styles.stage,stageView]}>
{
_.isEmpty(sourceData) ?<EmptyView/>:
<WrapComponent
sourceList={sourceData}
setSelect={this.setSelected}
floor={floor}
currentFloor={0}
maxLength={maxLength}
defaultSelected = {selectData}
itemHeihght={itemHeihght}
ActiveTextStyle={ActiveTextStyle}
normalTextStyle={normalTextStyle}
pickerType={pickerType}
originData={sourceData}
isLinkage={isLinkage}
renderListEmptyComponent={renderListEmptyComponent}
emptyOptions={emptyOptions}
/>
}
</View>
<MaskView
maxLength={maxLength}
itemHeihght={itemHeihght}
maskOptions={maskOptions}
/>
</View>
</View>
</View>
</Modal>
)
}
}
}
interface ISItemProps {
sourceList:ISourceType[],
setSelect:Callback,
floor:number,
currentFloor:number,
maxLength: 5 | 7 | 9,
defaultSelected:ISourceType[],
itemHeihght:number,
ActiveTextStyle:any,
normalTextStyle:any,
pickerType:string,
isLinkage:boolean,
originData:any,
renderListEmptyComponent:Callback,
emptyOptions:any
}
interface ISItemState {
nextData:ISourceType[],
currentChoose:ISourceType,
initialScrollIndex:number,
renderList:any[],
surerefresh:any
}
class PickerAlertViewItem extends PureComponent<ISItemProps,ISItemState> {
public scrollView:any
public flatEl:any
public currentItem:any
public itemEL:any
public config:any = {
waitForInteraction: false,
itemVisiblePercentThreshold:100,
}
public constructor(props:ISItemProps) {
super(props);
this.state = {
nextData:this.defaultRenderList(),
currentChoose:this.getDefaultChoose(),
initialScrollIndex:this.getInitialScrollIndex(),
renderList:this.flatListData(),
surerefresh:null,
}
}
public getInitialScrollIndex = ()=>{
const {defaultSelected,currentFloor,sourceList } = this.props
if(_.isEmpty(defaultSelected)) return 0
const initIndex = sourceList.findIndex(item=>String(item.id) === String(defaultSelected[currentFloor]?.id))
return initIndex<0?0:initIndex
}
public defaultRenderList = ()=>{
const { currentFloor, floor, defaultSelected, sourceList,isLinkage,originData} = this.props
if(isLinkage){
return originData[currentFloor 1]
}
const getNoFefault = ()=>this.props.sourceList?.[0]?.sub || []
const getDefaultList = ()=>{
if(currentFloor 1 === floor ) return []
return sourceList.find(value=>value.id === defaultSelected[currentFloor].id)?.sub || getNoFefault()
}
return _.isEmpty(defaultSelected)?getNoFefault():getDefaultList()
}
public getDefaultChoose = ()=>{
const { defaultSelected, currentFloor, sourceList } = this.props
return _.isEmpty(defaultSelected)?sourceList?.[0]:(sourceList.find(item=>item.id === defaultSelected?.[currentFloor]?.id) || sourceList?.[0])
}
public mid = ()=>{
const { maxLength } = this.props
return Math.floor(maxLength/2)
}
public flatListData = (nextData:any[])=>{
const { sourceList,currentFloor,originData ,isLinkage} = this.props
const mid = this.mid()
const arr = Array(mid).fill({id:'',name:'',sub:[]})
let currentData = nextData?nextData:sourceList
if(isLinkage){
currentData = originData[currentFloor]
}
if(currentData.length === 0 || !currentData) return []
return [...arr,...currentData,...arr]
}
public getItemLayout = (data:any,index:any) =>{
const { itemHeihght } = this.props
return {length: itemHeihght, offset: itemHeihght * index, index}
}
public renderItem = ({item,index,separators}:any)=>{
const { itemHeihght ,ActiveTextStyle,normalTextStyle,pickerType} = this.props
const {currentChoose} = this.state
const itemPress = (pickerType === 'scroll' || item.id === currentChoose?.id)?_.noop:this.clickItem
return <TouchableWithoutFeedback onPress={()=>itemPress(item,index)}>
<Text
numberOfLines={1}
style={[
{
height:itemHeihght,
textAlign:'center',
lineHeight:itemHeihght,
opacity:0.8,
paddingHorizontal: 10,
},
item.id === currentChoose?.id?ActiveTextStyle:normalTextStyle
]}
>{item.name}</Text>
</TouchableWithoutFeedback>
}
public clickItem =(item:ISourceType,index:any)=>{
const mid = this.mid()
if(index<mid) return
if(!item) return
this.scrollToIndex(index)
this.chooseItem(index,item)
}
public scrollToIndex = (index:any)=>{
const { renderList } = this.state
if(renderList.length === 0 || !renderList) return
if(this.flatEl){
this.flatEl.scrollToIndex({
index,
viewPosition:0.5,
animated:true
})
}
}
public chooseItem = (index:number,item:ISourceType)=>{
const { setSelect,currentFloor,isLinkage } = this.props
setSelect(item,currentFloor)
if(isLinkage) return
this.setState({
currentChoose:item || {},
nextData:item?.sub || []
},()=>{
if(this.itemEL) this.itemEL.reduction()
})
}
public reduction=()=>{
const currentChoose = this.props.sourceList?.[0] || {}
const nextData = currentChoose?.sub || []
const mid = this.mid()
this.setState({
currentChoose,
nextData,
renderList:this.flatListData(),
surerefresh:Date.now() Math.random(),
})
}
public componentDidMount(){
this.initSelected()
}
public componentDidUpdate(preProp:ISItemProps,preState:ISItemState){
const mid = this.mid()
if(this.state.surerefresh !== preState.surerefresh){
_.delay(()=>this.clickItem(this.state.currentChoose,mid),100)
}
}
public initSelected = ()=>{
const {setSelect,currentFloor } = this.props
const { currentChoose } = this.state
setSelect(currentChoose,currentFloor)
if(this.flatEl) this.flatEl.recordInteraction()
}
public renderListEmptyComponent = (data:any)=>{
const {renderListEmptyComponent,itemHeihght,emptyOptions,maxLength} = this.props
if(renderListEmptyComponent) return renderListEmptyComponent()
return <View style={{height:itemHeihght*maxLength,justifyContent:'center',alignItems: 'center'}}>
<Text
numberOfLines={1}
style={[
{
height:itemHeihght,
textAlign:'center',
lineHeight:itemHeihght,
opacity:0.8,
paddingHorizontal: 10,
}
]}
>{emptyOptions.descText || '暂无数据'}</Text>
</View>
}
public render(){
const {
floor,
currentFloor,
setSelect,
defaultSelected,
maxLength,
itemHeihght=50,
ActiveTextStyle,
normalTextStyle,
pickerType,
isLinkage,
originData,
emptyOptions,
} = this.props
const {
nextData,
initialScrollIndex,
renderList,
} = this.state
const nextFloor = currentFloor 1
return (
<>
<FlatList
style={{flex:1}}
ref={ref=>this.flatEl = ref}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
keyExtractor={(item: object, index: number) => String(index)}
renderItem={this.renderItem}
viewabilityConfig={this.config}
data={renderList}
getItemLayout={this.getItemLayout}
initialScrollIndex={initialScrollIndex}
onMomentumScrollEnd={this._moveEnd}
scrollEnabled={pickerType === 'click'?false:true}
ListEmptyComponent={this.renderListEmptyComponent}
/>
{
floor > nextFloor ?
<PickerAlertViewItem
ref={ref=>this.itemEL = ref}
sourceList={nextData}
floor={floor}
setSelect={setSelect}
currentFloor={nextFloor}
defaultSelected={defaultSelected}
maxLength={maxLength}
itemHeihght={itemHeihght}
ActiveTextStyle={ActiveTextStyle}
normalTextStyle={normalTextStyle}
pickerType={pickerType}
isLinkage={isLinkage}
originData={originData}
emptyOptions={emptyOptions}
/>:
null
}
</>
)
}
private _moveEnd=(e)=>{
const {itemHeihght} = this.props
const { renderList } = this.state
const contentOffset = e.nativeEvent.contentOffset.y;
const mid = this.mid()
const index = Math.round(contentOffset/itemHeihght) mid
this.clickItem(renderList[index],index)
}
}
export default WithHeadAndMethod(PickerAlertViewItem)
接上一版 多级联动组件;增加了非联动组件;完善了配置;优化了使用过程中的小问题;
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com