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 ~ !