2019-8-3 更新成了TS版本的
我將項目升級成TS版本了管宵,可以看這里
https://github.com/Tzng/React-Component/tree/master/react-native/ActionsBarTs
具體的用法是這樣的:
<ActionBarItem
bannerAction={flag => this.changeBar(flag, 'aaa')}
isActive={activeBar === 'aaa'}
data={deplist}
themeColor={theme.themeColor}
handleSubmit={(data, type) => this.onSelectSubmit(data, 'aaa', type)}
/>
注意下層級牙瓢,如果是多個的話框全,這個要放在上面哦
首先看看效果
基本思路
看動圖我們可以發(fā)現(xiàn)筐付,組件是由三部分組成的皂吮,一個是標題部分样眠,也就是用來點擊的地方贬养,一個是彈出來的那一塊昼捍,還以及一個遮罩層识虚。
標題部分
這部分是很簡單,就是一個文本和一個Icon
<ZlTouchable
onPress={this.openOrClosePanel}
style={{
flex: 1,
height: 40,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: themeColor
}}
>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text
style={[
styles.title_style,
{
color: '#fff'
}
]}
>
{/* 結果的展示 */}
{selectItems.length === 0 ? data.title : this.split(itemNames) + '(' + selectItems.length + ')'}
</Text>
</View>
</ZlTouchable>
在使用TouchableOpacity
的時候妒茬,需要考慮到一個情況就是舷礼,用戶可能會快速的點擊,從而出現(xiàn)一些異辰即常現(xiàn)象妻献,所以要對點擊事件進行點擊間隔限制操作蛛株,所以這里是用的一個自己寫的ZlTouchable
組件來完成的
代碼:
import React from 'react';
import { TouchableOpacity } from 'react-native';
class ZlTouchable extends React.Component<any> {
constructor(props) {
super(props);
this.lastClickTime = 0;
}
onPress() {
const { onPress } = this.props;
const clickTime = Date.now();
if (!this.lastClickTime || Math.abs(this.lastClickTime - clickTime) > 300) { // 350的時間可以延長,根據需要改變
this.lastClickTime = clickTime;
if (onPress) {
onPress();
} else {
return '';
}
}
return '';
}
render() {
const { activeOpacity, style, disabled, children } = this.props;
return (
<TouchableOpacity
onPress={() => this.onPress()}
activeOpacity={activeOpacity || 0.85}
style={style}
disabled={disabled}
>
{children}
</TouchableOpacity>);
}
}
export default ZlTouchable;
這樣的話育拨,我們就可以解決用戶快速點擊的問題了谨履。
彈出菜單
這里的彈出菜單,我是這么想的熬丧,拿到數(shù)據后呢笋粟,先把菜單生成出來,放在標題部分的上面析蝴,高度話害捕,用父組件傳遞進來。這樣的話闷畸,就得這么寫了
/**
* 說明:生成下拉菜單
* @author tangbin
* @date 2019/3/29
* @time 11:04
*/
renderActivityPanel = () => {
// 得到數(shù)據
const { data: { items } } = this.props;
// 得到最大高度
const { maxHeight, themeColor } = this.props;
const { rotationAnim } = this.state;
return (
<View
style={{
position: 'absolute',
left: 0,
right: 0,
top: 38, // 決定了彈窗距離頂部的距離
bottom: 0
}}
>
<Animated.View
style={{
position: 'absolute',
left: 0,
right: 0,
top: -(maxHeight + 50),
width,
zIndex: 20,
transform: [
{ translateY: rotationAnim.interpolate({
inputRange: [0, 1],
outputRange: [0, maxHeight + 50]
}) },
]
}}
>
<View style={{ height: maxHeight }}>
<ScrollView
style={{
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'white',
}}
>
{items.map(item => (
<ZlTouchable
key={item.id}
style={{ flex: 1, height: 39 }}
onPress={() => this.itemOnPress(item)}
>
{this.renderChcek(item, themeColor)}
</ZlTouchable>
))}
</ScrollView>
</View>
<View
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between'
}}
>
<ZlTouchable style={styles.cancel_button} onPress={this.openOrClosePanel}>
<View style={styles.button_text_view}>
<Text style={styles.cancel_button_text}>取消</Text>
</View>
</ZlTouchable>
<ZlTouchable style={styles.warning_button} onPress={this.handleSubmit}>
<View style={styles.button_text_view}>
<Text style={styles.warning_button_text}>確定</Text>
</View>
</ZlTouchable>
</View>
<View style={GlobalStyles.line} />
</Animated.View>
</View>
);
};
把我們的選項用ScrollView
包裹起來尝盼,這樣就能滾動了,然后佑菩,用動畫組件把整改菜單給包裹進去盾沫,并且在動畫組件設置相應的樣式,比如top
要設置成負數(shù)殿漠,zIndex
也要設置對應的等級赴精,然后我們就可設置相應的動畫了
動畫
首先,我們要設置點擊菜單的動畫
openPanel = () => {
const { rotationAnim, fadeAnim } = this.state;
this.isShowCouver = true;
rotationAnim.setValue(0);
Animated.parallel([
// 使用寬松函數(shù)讓數(shù)值隨時間動起來绞幌。
Animated.spring( // 隨時間變化而執(zhí)行動畫
rotationAnim, // 動畫中的變量值
{
toValue: 1, // 透明度最終變?yōu)?蕾哟,即完全不透明
duration: 300, // 讓動畫持續(xù)一段時間
useNativeDriver: true // <-- 加上這一行
}
),
// 使用寬松函數(shù)讓數(shù)值隨時間動起來。
Animated.spring( // 隨時間變化而執(zhí)行動畫
fadeAnim, // 動畫中的變量值
{
toValue: 0.5, // 透明度最終變?yōu)?莲蜘,即完全不透明
duration: 300, // 讓動畫持續(xù)一段時間
useNativeDriver: true // <-- 加上這一行
}
)
]).start();
};
然后呢渐苏,設置關閉的動畫
// 關閉動畫
closePanel = () => {
const { rotationAnim } = this.state;
this.isShowCouver = false;
rotationAnim.setValue(1);
// 這里只執(zhí)行彈窗的動畫,是因為遮罩層組件在切換的時候菇夸,已經被卸載了
Animated.spring(
rotationAnim,
{
toValue: 0,
duration: 300,
useNativeDriver: true // <-- 加上這一行
}
).start();
};
關閉動畫要把打開的動畫少一點琼富,因為遮罩層在關閉的時候,已經沒有了庄新,所以是不需要的鞠眉。
完整代碼看地址:
https://github.com/Tzng/React-Component/tree/master/react-native/ActionBar