@uiw/react-native
Version:
UIW for React Native
118 lines (111 loc) • 3.31 kB
JavaScript
import React, { useImperativeHandle, forwardRef, useRef, useCallback } from 'react';
import { Animated, StyleSheet, View, Text, I18nManager } from 'react-native';
import { RectButton } from 'react-native-gesture-handler';
import Swipeable from 'react-native-gesture-handler/Swipeable';
const SwipeAction = (props, ref) => {
const {
children,
right = [],
left = [],
swipeWidth = '20%',
...others
} = props;
const swipeableRef = useRef(null);
const renderRight = useCallback(() => {
return renderRightAction;
}, [right, swipeWidth]);
const renderLeft = useCallback(() => {
return renderLeftAction;
}, [left, swipeWidth]); // 右侧滑出
const renderRightAction = progress => {
return right && right.map(({
x = 1,
text,
color,
onPress,
render
}, idx) => {
const trans = progress.interpolate({
inputRange: [0, 1],
outputRange: [x, 0]
});
return <View key={idx} style={[styles.viewActions, {
width: swipeWidth
}]}>
<Animated.View style={{
flex: 1,
transform: [{
translateX: trans
}]
}}>
<RectButton style={[styles.rightAction, {
backgroundColor: color
}]} onPress={() => {
onPress && onPress();
}}>
{render ? render(text, right[idx], idx) : <Text style={styles.actionText}>{text}</Text>}
</RectButton>
</Animated.View>
</View>;
});
}; // 左侧滑出
const renderLeftAction = (progress, dragX) => {
return left && left.map(({
text,
color,
onPress,
render
}, idx) => {
const trans = dragX.interpolate({
inputRange: [0, 50, 100, 101],
outputRange: [-20, 0, 0, 1],
extrapolate: 'clamp'
});
return <View style={[styles.viewActions, {
width: swipeWidth
}]} key={idx}>
<Animated.View style={[{
flex: 1,
transform: [{
translateX: trans
}]
}]}>
<RectButton style={[styles.rightAction, {
backgroundColor: color
}]} onPress={() => {
onPress && onPress();
}}>
{render ? render(text, left[idx], idx) : <Text style={styles.actionText}>{text}</Text>}
</RectButton>
</Animated.View>
</View>;
});
}; // 暴露给父组件调用 Swipeable上的方法
useImperativeHandle(ref, () => ({
swipeable: swipeableRef.current
}));
return <Swipeable ref={swipeableRef} friction={2} enableTrackpadTwoFingerGesture rightThreshold={50} leftThreshold={50} overshootRight={false} renderRightActions={renderRight()} renderLeftActions={renderLeft()} {...others}>
{children && children}
</Swipeable>;
};
const styles = StyleSheet.create({
leftAction: {
alignItems: 'center',
flex: 1,
justifyContent: 'center'
},
actionText: {
color: 'white',
backgroundColor: 'transparent',
textAlign: 'center'
},
rightAction: {
alignItems: 'center',
flex: 1,
justifyContent: 'center'
},
viewActions: {
flexDirection: I18nManager.isRTL ? 'row-reverse' : 'row'
}
});
export default forwardRef(SwipeAction);