reactnative实现qq聊天消息气泡拖拽消失效果

前言(可跳过) 我在开发自己的APP时遇到了一个类似于qq聊天消息气泡拖拽消息的需求,因为在网上没有找到相关的组件,所以自己动手实现了一下
需求:对聊天消息气泡拖拽到一定长度松开时该气泡会消失(可自行增加拖拽过程,以及消失的动画)
reactnative实现qq聊天消息气泡拖拽消失效果
文章图片

解决方案:
0.创建一个足够大的数组(长度大于聊天框实例数量),初始化每个元素为React.createRef()
const badgeRegistryArr = new Array(99).fill(React.createRef())
1.渲染聊天列表时,对每个聊天框实例创建一个ref,并映射到数组中(ref={MappingArr[index]})


2.使用PanResponder创建一个触摸手势实例以此来实现拖拽效果(即当onPanResponderMove发生时更改一次Animated的值,已将样式部署到所有实例)
this.state = { pan: new Animated.ValueXY(), };
——————
const { pan,currentTargetId } = this.state const [translateX, translateY] = [pan.x, pan.y]; const imageStyle = {transform: [{translateX}, {translateY}]}

——————
style={[imageStyle,{position:'relative',zIndex:999}]}
——————
// 设置初始位置 pan.setValue({x: 0, y: 0}); },``` —————— ```// 使用拖拽的偏移量来定位 onPanResponderMove: Animated.event([ null, {dx: this.state.pan.x, dy: this.state.pan.y}, ]),``` 3.第2步操作会改变所有聊天气泡的值,所以我们要甄别一下,在开始手势操作事件中我们进行一次setState(得到当前的_nativeTag),然后刷新聊天框实例列表,并将列表中每个元素的_nativeTag和当前_nativeTag进行比对,为true时,将样式部署到且只部署到该实例。这样单独拖拽的效果就实现了 ```this.state = { pan: new Animated.ValueXY(), currentTargetId:0, }; ```—————— ```onPanResponderGrant: (evt, gestureState) => { // 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情! const { pan } = this.state const { _nativeTag } = evt.currentTarget this.setState({currentTargetId:_nativeTag}) pan.setValue({x: 0, y: 0}); },

——————
const { pan,currentTargetId } = this.state const [translateX, translateY] = [pan.x, pan.y]; let _nativeTag = null _nativeTag = badgeRegistryArr[item.id-1].current ? badgeRegistryArr[item.id-1].current._nativeTag:null if(_nativeTag === currentTargetId){ return {transform: [{translateX}, {translateY}]} } }

——————
const imageStyle = this.judgeBadgeMove(item);
【reactnative实现qq聊天消息气泡拖拽消失效果】4.在state中创建一个数组(用来实现拖拽后消失的效果,暂且称为A数组)所有元素初始化为true,数组长度与0步中数组相同,在用户放开触摸点(视为手势操作完成)事件中,当横向或纵向移动长度超出指定值时,对数组A中的匹配元素(目标元素下标即为在第3步中比对操作中的命中元素下标)的值setState为false这样就实现了拖拽一定长度后消失的效果
pan: new Animated.ValueXY(), currentTargetId:0, badgeVisualArr:new Array(6).fill(true) }; ``` —————— ```onPanResponderRelease: (evt, gestureState) => { const { _nativeTag } = evt.currentTarget const { dx,dy } = gestureState badgeRegistryArr.forEach((value,index) => { if(_nativeTag === value.current._nativeTag){ let tempArr = this.state.badgeVisualArr tempArr[index] = false this.setState({badgeVisualArr:tempArr}) } }) if(Math.abs(dx) > 80 || Math.abs(dy)){ this.setState({badgeVisualValue:false}) } // 用户放开了所有的触摸点,且此时视图已经成为了响应者。 // 一般来说这意味着一个手势操作已经成功完成。 },``` —————— ```{ item.messageValue > 0 && badgeVisualArr[item.id-1] ? :null }``` ——————![](https://img2020.cnblogs.com/blog/2158262/202110/2158262-20211029202356675-1941541600.gif)

    推荐阅读