irpas技术客

react native仿QQ左划_qq_38710423

未知 2497

使用PanResponder 和 Animated.timing 完成的一个仿QQ左划出现删除编辑的组件。 1、关键代码 <Animated.View style={{ flexDirection: "row", transform: [{ translateX }], }}{...PanResponder.create({ // 要求成为响应者: onStartShouldSetPanResponder: (evt, gestureState) => { return false; }, onMoveShouldSetPanResponder: (evt, gestureState) => { if (Math.abs(gestureState.dx) > 8 && Math.abs(gestureState.dy) < 8) { scrollCallBack && scrollCallBack(false); return true; } }, // onMoveShouldSetPanResponderCapture: (evt, gestureState) => true, onPanResponderGrant: (evt, gestureState) => { // 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情! this.handlerSeekGrant(evt, gestureState); }, onPanResponderMove: (evt, gestureState) => { // 最近一次的移动距离为gestureState.move{X,Y} this.handlerSeekMove(evt, gestureState); // 从成为响应者开始时的累计手势移动距离为gestureState.d{x,y} }, onPanResponderTerminationRequest: (evt, gestureState) => { if (Platform.OS === "ios") { let maxX = this.props.buttonViewWidth; let changeX = this.pageXEnd - this.pageXStart; let translateX = Math.abs(changeX) > maxX / 4 ? -maxX : 0; Animated.timing(this.state.translateX, { toValue: translateX, duration: 300, useNativeDriver: false, isInteraction: false, }).start(); if (this.rightBack) this.rightBack = false; return true; } else { return true; } }, onPanResponderTerminate: (evt, gestureState) => { if (Platform.OS === "android") { let maxX = this.props.buttonViewWidth; let changeX = this.pageXEnd - this.pageXStart; let translateX = Math.abs(changeX) > maxX / 4 ? -maxX : 0; Animated.timing(this.state.translateX, { toValue: translateX, duration: 300, useNativeDriver: false, isInteraction: false, }).start(); if (this.rightBack) this.rightBack = false; return true; } else { return true; } }, onPanResponderRelease: (evt, gestureState) => { // 用户放开了所有的触摸点,且此时视图已经成为了响应者。 // 一般来说这意味着一个手势操作已经成功完成。 this.handlerSeekRelease(evt, gestureState); scrollCallBack && scrollCallBack(true); }, }).panHandlers}> 2、handlerSeekGrant方法 handlerSeekGrant(evt, gestureState) { this.pageXStart = evt.nativeEvent.pageX; } 3、handlerSeekMove方法 //手势拖动 handlerSeekMove(evt, gestureState) { let x = evt.nativeEvent.pageX; let maxX = this.props.buttonViewWidth; this.pageXEnd = x; let changeX = this.pageXEnd - this.pageXStart; let translateX = 0; if (changeX < 0) {//左 if (this.state.translateX.__getValue() === -maxX) { translateX = -maxX; } else { translateX = Math.abs(changeX) > maxX ? -maxX : changeX; } } else { if (this.state.translateX.__getValue() < 0) { translateX = Math.abs(-(maxX - changeX)) > maxX ? 0 : -(maxX - changeX); } else { } } this.setState({ translateX: new Animated.Value(translateX), }, () => this._eventEmitter()); } ?4、handlerSeekRelease方法 //手势结束 handlerSeekRelease(evt, gestureState) { let x = evt.nativeEvent.pageX; let maxX = this.props.buttonViewWidth; this.pageXEnd = x; let changeX = this.pageXEnd - this.pageXStart; let translateX = 0; if (changeX < 0 || changeX === 0) {//左 translateX = Math.abs(changeX) > maxX / 4 ? -maxX : 0; //如果已经在最做边则往左边拉的时候不做操作 if (this.state.translateX.__getValue() === -this.props.buttonViewWidth) translateX = -maxX; } else if (changeX > 0) {//右 translateX = Math.abs(changeX) > maxX / 4 ? 0 : -maxX; } Animated.timing(this.state.translateX, { toValue: translateX, duration: 300, useNativeDriver: false, isInteraction: false, }).start(); if (this.rightBack) this.rightBack = false; } 5、全部代码 import React, { Component } from "react"; import { StyleSheet, View, PanResponder, Animated, DeviceEventEmitter, Platform, } from "react-native"; import propTypes from "prop-types"; class LeftStrokeComponent extends Component { static propTypes = { mainChildren: propTypes.element, buttonChildren: propTypes.element, buttonViewWidth: propTypes.number, id: propTypes.any, scrollCallBack: propTypes.func, }; constructor(props) { super(props); this.state = { translateX: new Animated.Value(0), }; this.pageXStart = null; this.pageXEnd = null; this.rightBack = true;//用于判断只要其中一个滚动 其他的就收回 } render() { const { translateX } = this.state; const { mainChildren, buttonChildren, scrollCallBack } = this.props; return ( <View style={styles.container}> <Animated.View style={{ flexDirection: "row", transform: [{ translateX }], }}{...PanResponder.create({ // 要求成为响应者: onStartShouldSetPanResponder: (evt, gestureState) => { return false; }, onMoveShouldSetPanResponder: (evt, gestureState) => { if (Math.abs(gestureState.dx) > 8 && Math.abs(gestureState.dy) < 8) { scrollCallBack && scrollCallBack(false); return true; } }, // onMoveShouldSetPanResponderCapture: (evt, gestureState) => true, onPanResponderGrant: (evt, gestureState) => { // 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情! this.handlerSeekGrant(evt, gestureState); }, onPanResponderMove: (evt, gestureState) => { // 最近一次的移动距离为gestureState.move{X,Y} this.handlerSeekMove(evt, gestureState); // 从成为响应者开始时的累计手势移动距离为gestureState.d{x,y} }, onPanResponderTerminationRequest: (evt, gestureState) => { if (Platform.OS === "ios") { let maxX = this.props.buttonViewWidth; let changeX = this.pageXEnd - this.pageXStart; let translateX = Math.abs(changeX) > maxX / 4 ? -maxX : 0; Animated.timing(this.state.translateX, { toValue: translateX, duration: 300, useNativeDriver: false, isInteraction: false, }).start(); if (this.rightBack) this.rightBack = false; return true; } else { return true; } }, onPanResponderTerminate: (evt, gestureState) => { if (Platform.OS === "android") { let maxX = this.props.buttonViewWidth; let changeX = this.pageXEnd - this.pageXStart; let translateX = Math.abs(changeX) > maxX / 4 ? -maxX : 0; Animated.timing(this.state.translateX, { toValue: translateX, duration: 300, useNativeDriver: false, isInteraction: false, }).start(); if (this.rightBack) this.rightBack = false; return true; } else { return true; } }, onPanResponderRelease: (evt, gestureState) => { // 用户放开了所有的触摸点,且此时视图已经成为了响应者。 // 一般来说这意味着一个手势操作已经成功完成。 this.handlerSeekRelease(evt, gestureState); scrollCallBack && scrollCallBack(true); }, }).panHandlers}> {mainChildren} {buttonChildren} </Animated.View> </View> ); } //手势开始 handlerSeekGrant(evt, gestureState) { this.pageXStart = evt.nativeEvent.pageX; } //手势拖动 handlerSeekMove(evt, gestureState) { let x = evt.nativeEvent.pageX; let maxX = this.props.buttonViewWidth; this.pageXEnd = x; let changeX = this.pageXEnd - this.pageXStart; let translateX = 0; if (changeX < 0) {//左 if (this.state.translateX.__getValue() === -maxX) { translateX = -maxX; } else { translateX = Math.abs(changeX) > maxX ? -maxX : changeX; } } else { if (this.state.translateX.__getValue() < 0) { translateX = Math.abs(-(maxX - changeX)) > maxX ? 0 : -(maxX - changeX); } else { } } this.setState({ translateX: new Animated.Value(translateX), }, () => this._eventEmitter()); } //手势结束 handlerSeekRelease(evt, gestureState) { let x = evt.nativeEvent.pageX; let maxX = this.props.buttonViewWidth; this.pageXEnd = x; let changeX = this.pageXEnd - this.pageXStart; let translateX = 0; if (changeX < 0 || changeX === 0) {//左 translateX = Math.abs(changeX) > maxX / 4 ? -maxX : 0; //如果已经在最做边则往左边拉的时候不做操作 if (this.state.translateX.__getValue() === -this.props.buttonViewWidth) translateX = -maxX; } else if (changeX > 0) {//右 translateX = Math.abs(changeX) > maxX / 4 ? 0 : -maxX; } Animated.timing(this.state.translateX, { toValue: translateX, duration: 300, useNativeDriver: false, isInteraction: false, }).start(); if (this.rightBack) this.rightBack = false; } _eventEmitter = () => { const { id } = this.props; this.eventEmitter = DeviceEventEmitter.emit("LEFTSTROKE", { id }); }; _onLeftStoke = (params) => { if (!this.rightBack) { this.rightBack = true; const { id } = params; if (id === this.props.id) return; if (this.state.translateX >= 0) return; Animated.timing(this.state.translateX, { toValue: 0, duration: 300, useNativeDriver: false, isInteraction: false, }).start(); } }; componentWillUnmount() { this.eventEmitter && this.eventReceive.remove(); this.eventReceive && this.eventReceive.remove(); } componentDidMount() { this.eventReceive = DeviceEventEmitter.addListener("LEFTSTROKE", this._onLeftStoke); } } export default LeftStrokeComponent; const styles = StyleSheet.create({ container: { alignItems: "center", flexDirection: "row", backgroundColor: "white", }, }); 6、使用方法 <View style={styles.container}> <FlatList data={data} renderItem={this._renderItem} onEndReachedThreshold={0.3} scrollEnabled={scrollEnabled} /> </View> _renderItem = ({ item, index }) => { return ( <LeftStrokeComponent mainChildren={this._renderMainChildren()} buttonChildren={this._renderButtonChildren()} buttonViewWidth={160} id={index} scrollCallBack={(scrollEnabled) => this.setState({ scrollEnabled })} /> ); };


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #React #native仿QQ左划