RN 简单的触摸监听已经无法满足这个需求,所以 引入 手势监听(handler)

上代码:

handler定义:

let _this = this;let handlers = {onStartShouldSetResponder: () => true,onMoveShouldSetResponder: () => true,onResponderTerminationRequest: () => false,onResponderStart: () => {console.log('start')console.log(_this.props._isScrollIng)clearTimeout(_this.longTimer);_this.longTimer = setTimeout(() => {if (!_this.props._isScrollIng) {this.setState({clickStatus: true,})_this.props._onLongPress()_this.props._getLocationNow(_this.props.id, 0, 0)}}, 300);// 300 ms 之后触发长按},onResponderMove: (evt) => {console.log('move')console.log(_this.props._isScrollIng)console.log(evt.nativeEvent.locationX)console.log(evt.nativeEvent.locationY)console.log(_this.props.id)if (!_this.props._isScrollIng && this.state.clickStatus) { // 条件:屏幕不滚动,触发长按 _this.props._getLocationNow(_this.props.id, evt.nativeEvent.locationX, evt.nativeEvent.locationY)//根据当前触发的handle对象,以及点击坐标与其相对位置,判断当前所处view}},onResponderRelease: () => {console.log(_this.props._isScrollIng)console.log('release')clearTimeout(_this.longTimer);this.setState({clickStatus: false,})_this.props._toggleIsActive();//让scrollView重新可以滚动,并且把屏幕滚动状态设置为false(针对短点表情触发的屏幕滚动结束)_this.props._onRefreshPreView();//让最后一个预览表情,离开预览状态},};

handler 使用:

<View{...handlers}style={[{width: iconWidth,height: iconWidth,}, styles.iconWrap]}> </View>

表情Sticker组件的使用(自定义的,都有注释):

 if (this.state.stickerArr.pagInfo) {this.state.iconObj.forEach((v, k) => {Icons.push((<Stickerkey={k}id = {k} //每个表情有自己的id标记index_touch = {this.state.nowTouchIndex} //当前手势所处view的idanimateIconUrl = {v}iconUrl = {this.state.gifObj[k]}_toggleIsActive={this._toggleIsActive.bind(this) } //手势释放,触发的方法定义在上层界面_onLongPress = {this._onLongPress.bind(this) } //触发长按的方法,定义在上层界面_getLocationNow = {this._onGetLocationNow.bind(this) } //获取当前手势坐标方法,定义在上层界面_onRefreshPreView = {this._onRefreshPreview.bind(this) } //重置最后一个预览状态的表情方法,,定义在上层界面_isScrollIng = {this.state.scrollIng} //当前界面是否在滚动状态/>));})}

通过触发handler的id,及手势移动与其的相对偏移量,算出当前手势所在view:

上位置判断算法:

_onGetLocationNow(id, offsetX, offsetY) {let screenWidth = Dimensions.get('window').width;let iconWidth = (screenWidth - 5 * TAP) / 4;let row = 0;let col = 0;let index = undefined;let offsetXAbs = Math.abs(offsetX);let offsetYAbs = Math.abs(offsetY);if (offsetX <= iconWidth + TAP / 2 && offsetX >= 0 && offsetY <= iconWidth && offsetY >= 0) {index = id;} else {col = Math.ceil((offsetXAbs) / (iconWidth + TAP / 2)) - 1;row = Math.ceil((offsetYAbs) / (iconWidth)) - 1;console.log('row_1:' + row);if (offsetX < 0) {col = 0 - (col + 1);}if (offsetY < 0) {row = 0 - (row + 1);}}console.log('col_1:' + col);console.log('row_2:' + row);let rangetimes = Math.ceil((id + 1) / 4); // 超出范围判定if (col >= 0 && (col + id) >= rangetimes * 4 - 1) {col = rangetimes * 4 - 1 - id;} else {if (col < 0 && (id + col) <= (rangetimes - 1) * 4) {col = 0 - (id - (rangetimes - 1) * 4);}}console.log('col_2:' + col);console.log('row_3:' + row);index = id + row * 4 + col;if (index < 0 || index >= this.state.iconObj.length) {index = undefined;}console.log('index:' + index);console.log('col:' + col);this.setState({nowTouchIndex: index,})}

触发长按要屏蔽上层scrollView的滚动以及滚动要屏蔽view的触发长按:

这里代码杂:说个里面有的一个坑,就是scrollView 滚动结束 并不会调用onAnimatedScrollEnd(文档上说调用),想监听这个事件用:onMomentumScrollEnd

差不多了,全套代码肯定是没有的,毕竟是项目,大概理解下,想深入交流就加一下群:429307812

------- 我是小尾巴

React-native 实现表情商城 表情长按拖动预览(还原安卓微信效果)相关推荐

  1. react native一键分享功能实现amp;原理和注意点(支持微信、qq、新浪微博等)

    前言 目前使用一键分享比较主流的两个SDK:ShareSDK.友盟: 又因为友盟功能比较多且比较全,比如说友盟统计.友盟推送等,所以本文重点介绍的是友盟分享功能在rn上的应用以及要注意的点. reac ...

  2. React:后端返回pdf数据流,前端打开页面预览,使用fetch,PDFObject

    预览页面: import React, { useEffect } from 'react'; import { connect } from 'react-redux'; import PropTy ...

  3. 小程序生成长图(预览,不限高度)+小程序码+小程序码中间logo换成自定义logo

    上条博客已经介绍了如何云调用生成小程序码,链接地址: https://blog.csdn.net/mingjuna2010/article/details/92796711 这条博客我们来介绍小程序中 ...

  4. React Native UI NIKE商城

    发现了一个写的不错的UI,分享给大家. 界面效果 主要代码 /* eslint-disable prettier/prettier */ import React from 'react'; impo ...

  5. WebRTC Native M96 SDK接口封装--startPreview开启视频预览

    今天聊的事儿,跟peer connection一点关系没有,只是开启本地预览. 在没有进行任何网络连接的时候,用户也可以先把本地的摄像头打开,孤芳自赏一下. 如何枚举视频设备,已经介绍过了:https ...

  6. javascript实现 京东淘宝等商城的商品图片大图预览功能

    微科技 2017-01-15 15:07 在京东和淘宝等购买东西的时候,我们会经常预览左侧商品展示图片,把鼠标放到原图,右侧就会有个大图显示出细节.本文将带领大家写一个这样简单的功能! 一.实现原理 ...

  7. 全网最全 Flutter 与 React Native 深入对比分析

    作为 GSY 开源系列的作者,在去年也整理过 <移动端跨平台开发的深度解析> 的对比文章,时隔一年之后,本篇将重新由 环境搭建.实现原理.编程开发.插件开发.编译运行.性能稳定.发展未来 ...

  8. 比较 React Native 与 Vue 和 Capacitor

    随着可用移动应用程序开发框架数量的增加,2018 年引入的 Vue Native 使开发人员能够使用 Vue.js 代码创建 React Native 移动应用程序. 然而,Vue Native 团队 ...

  9. React Native 初体验

    2015年9月底开始正式接触React native,公司的ios团队用它写了一个安卓项目之后,到上周,公司彻底停止了RN的使用. 至于我们为什么停止使用RN,原因大致有两个: 一.RN对安卓的支持还 ...

最新文章

  1. sTC8G1K08+通过串口显示内部电压_基于51单片机的数字电流电压表
  2. 实战:kafka实现日志收集系统
  3. [ZJOI2005]午餐 贪心+dp
  4. 如何使用hiprint插件制作条码标签
  5. Android点击通知栏信息后返回正在运行的程序,而不是一个新Activity
  6. 自动驾驶 9-3: 走向非线性 - 扩展卡尔曼滤波器 Going Nonlinear - The Extended Kalman Filter
  7. 使用计算机程序的设计语言是,计算机程序设计语言有哪些?
  8. 计算机专业大学生买什么u盘合适,12款热销U盘横评:哪款U盘最值得买?
  9. mma7660(gsensor)的hwmon驱动
  10. 从“老公”的称呼来历,看男人地位的变迁
  11. 学习CPP看过的博客
  12. Ubuntu开机一直卡在[OK] Started GNOME Display Manager处,解决方案!
  13. Hadoop Web 控制台安全认证
  14. 项目启动后sqlSessionFactory获取不到创建数据库连接失败
  15. vue3-HTTP请求
  16. 韶音骨传导耳机好用吗?韶音和南卡骨传导耳机对比实测
  17. MTK平台开机初始化时 camera驱动流程|MTK camera调试常见几十种问题处理方法
  18. mysql主从服务器宕机,Mysql主从数据库配置及宕机处理
  19. zookeeper集群启动时配置异常 myid file is missing
  20. Cortex-M0体系结构

热门文章

  1. Manifest merger failed问题:tools:replace=android:theme和tools:replace=android:icon
  2. Android应用开发中,第三方集成新浪微博(sinaWeiboSDK)的过程记录
  3. Meta元宇宙内容VP:VR游戏与元宇宙关系紧密,社交并非全部
  4. 电子学会 青少年编程等级考试(C语言)六级(数据结构)试题
  5. python 基金净值_Python 关于处理基金净值数据的问题
  6. EXCEL_VBA_抱歉,无法找到…….xlam。是否可能被移动、重命名或删除?
  7. shell脚本打开另一终端 并执行命令
  8. Jupyter Notebook 如何安装 + 使用?【审核5次重磅发布】
  9. postgre基本用法(一)
  10. 摄氏度符号英文计算机语言,英文文章里摄氏度符号打法