实现:通过监听panResponder水平滑动,获取滑动距离和滑动方向,修改绝对定位view的偏移量,监听手势结束通过Animated使动画继续滑动到指定位置,通过overflow将子控件多余部分隐藏避免满屏幕滑动。
代码:
使用:
return (
<RightDragView optionWidth={Dimens.dp160} itemView={this.dragItemView()}
optionView={this.dragOptionView()}/>
);
传入item:
dragItemView() {
return (
<View style={{
flexDirection: 'row',
height: Dimens.dp66,
width:PhoneInfo.phone_width-Dimens.dp24,
padding: Dimens.dp3,
alignItems: 'center',
backgroundColor: '#F9F9F9',
borderRadius: Dimens.dp8,
}}>
</View>
);
}
传入option:
dragOptionView() {
return (
<View style={{flexDirection: 'row', width: Dimens.dp160}}>
<View style={{
backgroundColor: '#4c4c4c',
height: Dimens.dp66,
width: Dimens.dp60,
justifyContent: 'center',
}}>
<Text style={styles.textWhite}>设为在用</Text>
</View>
<View style={{
height: Dimens.dp66,
width: Dimens.dp50,
backgroundColor: '#F29B48',
justifyContent: 'center',
}}>
<TouchableOpacity style={{
height: Dimens.dp66,
width: Dimens.dp50,
backgroundColor: '#F29B48',
justifyContent: 'center',
}} onPress={() => this.toEditPage()}>
<Text style={styles.textWhite} onPress={()=>this.toEditPage()}>编辑</Text>
</TouchableOpacity>
</View>
<View style={{
backgroundColor: '#F75855',
height: Dimens.dp66,
width: Dimens.dp50,
justifyContent: 'center',
}}>
<Text style={styles.textWhite}>绑定</Text>
</View>
</View>
);
}
控件:
/**
* itemOption水平滑动控件
*/
export default class RightDragView extends Component {
constructor(props) {
super(props);
this.optionWidth=props.optionWidth
//绝对定位偏移量
this.left = new Animated.Value(0);
this.grantValue = 0;
this.direction = 0;
this.aStyle = false;
}
componentWillMount() {
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => {
return true;
},
onPanResponderGrant: (event, gestureState) => {
this.direction = 0;
this.grantValue = gestureState.x0;
},
onPanResponderMove: Animated.event(
[null, {}], {
listener: (event, gestureState) => {
if ((!this.aStyle && (gestureState.moveX - this.grantValue) >= 0) || (this.aStyle && (gestureState.moveX - this.grantValue) <= 0)) {
//最左边不能向左滑动,最右边不能向右滑动
return;
}
if(gestureState.moveX - this.grantValue>this.optionWidth||gestureState.moveX - this.grantValue<-this.optionWidth){
//最大滑动区间
return;
}
if (this.aStyle) {
//向右滑动
this.left.setValue((gestureState.moveX - this.grantValue) - this.optionWidth);
} else {
//向左滑动
this.left.setValue(gestureState.moveX - this.grantValue);
}
//保存滑动方向正值向右负数向左
this.direction = gestureState.moveX - this.grantValue;
},
},
),
onPanResponderRelease: () => {
if (this.direction === 0) {
return;
}
/**
* 手势滑动结束判断item自动完成滑动
* */
if (this.aStyle) {
this.viewAnimatedHidden();
} else {
this.viewAnimatedStart();
}
},
});
}
viewAnimatedStart() {
this.aStyle = true;
Animated.timing(this.left, {
toValue: -this.optionWidth,
duration: 200,
useNativeDriver:false
}).start();
}
viewAnimatedHidden() {
this.aStyle = false;
Animated.timing(this.left, {
toValue: 0,
duration: 200,
useNativeDriver:false
}).start();
}
render() {
return (
<View style={{
flexDirection: 'row',
overflow: 'hidden',
marginTop: Dimens.dp16,
marginRight: Dimens.dp12,
}}>
<Animated.View style={{
flexDirection: 'row',
width: PhoneInfo.phone_width - Dimens.dp24+this.optionWidth,
position: 'relative',
marginLeft: Dimens.dp12,
left: this.left,
}}
{...this.panResponder.panHandlers}>
{
/**
* 显示item内容
*/
this.props.itemView
}
{
/**
* 显示滑动option
*/
this.props.optionView
}
</Animated.View>
</View>
);
}
}