IOS ![]() |
Android ![]() |
<AreaPicker
onFinished={this.onFinished.bind(this)}
modalHeight={800}
visible={visible}
/>
复制代码
visible
: 类型 boolean
, 控制是否显示组件node
modalHeight
:类型 number
, 设置内容窗口的高度react
onFinished
:类型 func
, 选取完整地区后回调, 返回值是一个数组[{label: 'xx', value: 'xx'}]
git
onFinished(list) {
this.setState({
selected: (list.map(o => o.label)).join('')
})
}
复制代码
使用react-native-animatable
, 须要先安装。github
yarn add react-native-animatable
复制代码
遮罩层的淡入效果npm
<Animatable.View style={[styles.container, !visible && {opacity: 0, transform:[{scale: 0}]}]} ref = {ref => this.containerRef = ref}>
</Animatable.View>
复制代码
初始化组件的时候,componentWillReceiveProps
不会执行,当props
发生变化时执行,能够在这个函数里调用this.setState()
去更新组件内部属性,其中也能够经过this.props去获取到旧的属性值,完成一些对比逻辑。react-native
componentWillReceiveProps(nextProps){
const { visible } = nextProps
!!this.containerRef && this.containerRef.animate('fadeIn', ANIMATE_DURATION).then(() => {
// todo...
})
}
复制代码
选项卡的滚动线条数组
线条元素绝对定位,宽度动态获取,移动的位置经过 translateX
设置bash
<Animatable.View
animation={{
0: {
translateX: startTranslateValue
},
1: {
translateX: endTtranslateValue
}
}}
delay={0}
duration={200}
easing="ease-in-out"
// iterationCount="infinite"
useNativeDrive
style={[styles.lineStyle, {width: lineWidth}]}
>
</Animatable.View>
复制代码
其中 startTranslateValue
是始点, endTtranslateValue
是终点。 若是一开始从0
移动到100
,再接下来多是从100
移动200
函数
有一个属性 currentActiveIdx
指向当前Tab索引,当切换Tab时,currentActiveIdx
跟着变化,再发现 currentActiveIdx
发生变化的时候, 想办法调整线条宽度和移动的位置动画
componentWillReceiveProps(nextProps) {
const newVal = nextProps.currentActiveIdx
const oldVal = this.props.currentActiveIdx
if (newVal == oldVal) return
// todo 调整线条样式
}
复制代码
具体todo
了什么?
想办法获取组件宽高位置信息。
获取到上一次oldVal
的组件的宽高位置, 记录。
获取到这一次newVal
的组件的宽高位置, 记录。
始点startTranslateValue
设置为这一次的终点。
终点 endTtranslateValue
设置为这一次的x坐标值(nodeProps.x - scaleSize(30)
减去容器的左边距内填充值)。
定时器设置,确保组件完成渲染,宽高已经撑开。
setTimeout(() => {
getNodePropsByRef(this['item' + oldVal]).then(nodeProps => {
this.map[oldVal] = {
w: nodeProps.width,
x: nodeProps.x
}
getNodePropsByRef(this['item' + newVal]).then(nodeProps => {
this.map[newVal] = {
w: nodeProps.width,
x: nodeProps.x - scaleSize(30)
}
this.setState({
startTranslateValue: this.state.endTtranslateValue,
endTtranslateValue: this.map[newVal].x,
lineWidth: parseFloat(this.map[newVal].w)
})
})
})
}, 100)
复制代码
getNodePropsByRef
方法以下:
x
、 y
是相对于整个屏幕,左上角坐标
import {findNodeHandle, UIManager} from 'react-native'
export const getNodePropsByRef = ref => {
const handle = findNodeHandle(ref);
return new Promise((resolve) => {
UIManager.measure(handle, (x, y, width, height, pageX, pageY) => {
resolve({
x,
y,
width,
height,
pageX,
pageY
})
})
})
}
复制代码
数据用的是 area-data
pca['86'] // 等同于 AreaData['86']
// 全部省份:{'110000': '北京市', '120000': '天津市', '130000': '河北省', ...}
pcaa['130000'] // 等同于 AreaData['130000']
// 对应省份的全部城市:{'130100': '石家庄市', '130200': '唐山市', '130300': '秦皇岛市', ...}
pcaa['130200'] // 等同于 AreaData['130200']
// 对应市的全部县区:{'130201': '市辖区', '130202': '路南区', '130203': '路北区', ...}
复制代码
初始时配置的数据
selectedRows: [
{
label: '请选择',
value: null,
values: pca['86']
}
]
复制代码
当选中其中一个数据时,向selectedRows
添加第二组数据
selectedRows.push({
label: '请选择',
value: null,
values: pcaa[item.key]
})
复制代码
当已经有三组数据,并选中第一组的某个值时, 去掉第三组数据
selectedRows.length == 3 && selectedRows.splice(2, 1)
复制代码
一样的思路处理第二组,第三组数据的选取,最后判断选完后,调用函数返回数据
onFinished(selectedRows.map(o => ({label: o.label, value: o.value})))
复制代码
列表组件 FlatList
<FlatList
ref={getFlatListRef}
showsVerticalScrollIndicator={false}
onContentSizeChange={onFlatListContentSizeChange}
data={values}
keyExtractor={(item, index) => item.key + ''}
renderItem={ItemView}
/>
复制代码
每次更换列表数据时,须要滚动到顶部
onFlatListContentSizeChange(){
if (!!this.flatListRef) {
this.flatListRef.scrollToIndex({index: 0, animated: false})
}
}
复制代码
GITHUB - 博客
欢迎start ~ !
GITHUB - 组件
欢迎start ~ !