前言:好久没有写博客了,回想起刚开始写博客的时候对自己的要求,“每周至少一篇!!!“(还有当初说减肥跟写博客同步进行,结果越减越肥。),嗯嗯,说多了都是泪,最近在一直在学习h5,然后看到现在rn项目中有小伙伴在用一个第三方的侧滑删除控件,于是想去看看那些大神是咋实现的,最后发现,也就这样哈~没想象中的那么难,写这篇博客的目的也就是当作一个学习笔记,大牛勿喷!!2017对我来说是不平凡的一年,期间换了几次工作,但最后还是找到了自己的归宿,所以对2017还是比较满意的,感恩!!2018迎来了又一个本命年,回头想想自己,其实也不小了,但心里却总是对自己说:“我还是一个小鲜肉!“,唉唉!感叹时光的流逝,身边的亲人一个一个离去,有些时候一个人发呆的时候总问自己“你到底想做什么?你能做什么?“我却被自己问的哑口无言,骚年!现实点吧~ 也请对自己和身边的人好一点,坚持自己的初衷,永远不要做思想的巨人行动的矮子,嗯嗯!说了那么多废话,想必大家也觉得我无聊,管你们无不无聊!我开心就行,哈哈哈哈~~~

最后实现的效果呢也很简单,大概是这样的:

先说一下我们的大体思路,很简单!底部绝对定位放一个默认的(含有“删除“按钮)的view,然后上面盖住一个默认的需要渲染的view,给整个item一个滑动监听,然后慢慢的漏出底部view,嗯嗯!! 原理真的很简单,下面我们一步一步的撸我们的代码哈~

首先新建一个很干净的项目叫SwipeDemo然后跑起来:

照着我们的思路简单实现一下,代码很简单,我直接贴出来了:

/*** Sample React Native App* https://github.com/facebook/react-native* @flow*/import React, {Component} from 'react';
import {Platform,StyleSheet,Text,View,TouchableOpacity
} from 'react-native';export default class App extends Component {render() {return (<View style={styles.container}><View style={styles.swipeContainer}>{/*绝对在底部的view*/}<View style={styles.swipeActions}><TouchableOpacitystyle={styles.delTextContainer}onPress={()=>{alert('ss');}}><Textstyle={styles.deleteTextStyle}>删除</Text></TouchableOpacity></View>{/*内容content*/}<View style={styles.content}><Text>我是item的内容</Text></View></View></View>);}
}const styles = StyleSheet.create({container: {flex: 1,alignItems: 'center',backgroundColor: '#F5FCFF',},swipeContainer: {width: '100%',marginTop: 100,height:100,},swipeActions:{backgroundColor: 'grey',width: '100%',overflow:'hidden',...StyleSheet.absoluteFillObject,flexDirection:'row',justifyContent:'flex-end'},delTextContainer:{width:100,backgroundColor:'red',alignItems:'center',justifyContent:'center'},deleteTextStyle:{color:'#fff',},content:{width: '100%',flex:1,backgroundColor:'yellow',justifyContent:'center',alignItems:'center',}
});

运行代码:

然后我们给内容content一个向左的偏移量:

 render() {return (<View style={styles.container}><View style={styles.swipeContainer}>{/*绝对在底部的view*/}<View style={styles.swipeActions}><TouchableOpacity
                            style={styles.delTextContainer}onPress={()=>{alert('ss');}}><Text
                                style={styles.deleteTextStyle}>删除</Text></TouchableOpacity></View>{/*内容content*/}<View style={[styles.content,{transform:[{translateX:-10}]}]}><Text>我是item的内容</Text></View></View></View>);

我们向左偏移了10:

可以看到我们绝对在底部的view漏出了一点点~

我们再向左偏移左偏移了100:


可以看到我们绝对在底部的view完全漏出来了~

所以看到这里小伙伴是不是有点明白了呢??我们只需要给一个手势在move的时候动态的设置左偏移量,然后手指松开的时候做一些逻辑判断,最后给一个动画,就可以简单的实现我们的侧滑删除功能了。

在写组件之前建议大家了解一下rn的手势,也就是PanResponder组件,大家可以参考下官网及这篇文章:

React Native 触摸事件处理详解
PanResponder

好啦~ 我们先创建一个view叫SwipeRow.js:

/*** @author YASIN* @version [React-Native Ocj V01, 2018/3/13]* @date 17/2/23* @description SwipeRow*/
import React, {Component,
} from 'react';
import PropTypes from 'prop-types';
import {Animated,PanResponder,Platform,StyleSheet,TouchableOpacity,ViewPropTypes,View,Text
} from 'react-native';export default class SwipeRow extends Component {render() {return (<View style={[styles.swipeContainer, this.props.style]}><View style={styles.swipeActions}>{this.props.children[0]}</View>{this.props.children[1]}</View>);}
}
const styles = StyleSheet.create({swipeContainer: {width: '100%',},swipeActions: {backgroundColor: 'grey',width: '100%',overflow: 'hidden',...StyleSheet.absoluteFillObject,flexDirection: 'row',justifyContent: 'flex-end'},
});

然后App.js代码改为:

/*** Sample React Native App* https://github.com/facebook/react-native* @flow*/import React, {Component} from 'react';
import {Platform,StyleSheet,Text,View,TouchableOpacity
} from 'react-native';
import SwipeRow from './SwipeRow';export default class App extends Component {render() {return (<View style={styles.container}><SwipeRow style={{marginTop: 100}}>{/*绝对在底部的view*/}<TouchableOpacitystyle={styles.delTextContainer}onPress={() => {alert('ss');}}><Textstyle={styles.deleteTextStyle}>删除</Text></TouchableOpacity>{/*内容content*/}<View style={[styles.content, {transform: [{translateX: -100}]}]}><Text>我是item的内容</Text></View></SwipeRow></View>);}
}const styles = StyleSheet.create({container: {flex: 1,alignItems: 'center',backgroundColor: '#F5FCFF',width: '100%',},delTextContainer: {width: 100,backgroundColor: 'red',alignItems: 'center',justifyContent: 'center'},deleteTextStyle: {color: '#fff',},content: {width: '100%',height: 100,backgroundColor: 'yellow',justifyContent: 'center',alignItems: 'center',}
});

运行代码:

可以发现我们得到的是一样的效果,我们只是简单的封装到了一个叫SwipeRow的组件中了~

接着我们封装一个手势的处理类:

/*** @author YASIN* @version [React-Native Ocj V01, 2018/3/13]* @date 17/2/23* @description SwipeRow*/
import React, {Component,
} from 'react';
import PropTypes from 'prop-types';
import {Animated,PanResponder,Platform,StyleSheet,TouchableOpacity,ViewPropTypes,View,Text
} from 'react-native';export default class SwipeRow extends Component {// 构造constructor(props) {super(props);// 初始状态this._panResponder = PanResponder.create({onMoveShouldSetPanResponderCapture: this._handleMoveShouldSetPanResponderCapture,onPanResponderGrant: this._handlePanResponderGrant,onPanResponderMove: this._handlePanResponderMove,onPanResponderRelease: this._handlePanResponderEnd,onPanResponderTerminate: this._handlePanResponderEnd,onShouldBlockNativeResponder: (event, gestureState) => false,//表示是否用 Native 平台的事件处理,默认是禁用的,全部使用 JS 中的事件处理,注意此函数目前只能在 Android 平台上使用});}render() {return (<View style={[styles.swipeContainer, this.props.style]}><View style={styles.swipeActions}>{this.props.children[0]}</View>{this.renderRowContent()}</View>);}renderRowContent() {return (<Animated.View{...this._panResponder.panHandlers}>{this.props.children[1]}</Animated.View>);}/*** 是否需要成为move事件响应者,返回true直接走onPanResponderMove* @param event* @param gestureState* @returns {boolean}* @private*/_handleMoveShouldSetPanResponderCapture(event: Object, gestureState: Object,): boolean {//当垂直滑动的距离<10 水平滑动的距离>10的时候才让捕获事件console.log('_handleMoveShouldSetPanResponderCapture');return gestureState.dy < 10 && Math.abs(gestureState.dx) > 10;}/*** 表示申请成功,组件成为了事件处理响应者* @param event* @param gestureState* @private*/_handlePanResponderGrant(event: Object, gestureState: Object): void {console.log('_handlePanResponderGrant');}/*** 处理滑动事件* @param event* @param gestureState* @private*/_handlePanResponderMove(event: Object, gestureState: Object): void {console.log('_handlePanResponderMove');}/*** 结束事件的时候回调* @param event* @param gestureState* @private*/_handlePanResponderEnd(event: Object, gestureState: Object): void {console.log('_handlePanResponderEnd');}
}
const styles = StyleSheet.create({swipeContainer: {width: '100%',},swipeActions: {backgroundColor: 'grey',width: '100%',overflow: 'hidden',...StyleSheet.absoluteFillObject,flexDirection: 'row',justifyContent: 'flex-end'},
});

然后运行代码(手指从右向左拖动)看log:

好啦,我们在_handlePanResponderMove方法中处理下滑动事件:

 /*** 处理滑动事件* @param event* @param gestureState* @private*/_handlePanResponderMove(event: Object, gestureState: Object): void {if (this._previousLeft === null) {this._previousLeft = this.state.currentLeft._value}let nowLeft = this._previousLeft + gestureState.dx / 0.5;//右滑最大距离为0(边界值)nowLeft = Math.min(nowLeft, 0);this.state.currentLeft.setValue(nowLeft,);}

然后去除App.js中的{transform: [{translateX: -100}]:

  {/*内容content*/}<View style={[styles.content, {transform: [{translateX: -100}]}]}><Text>我是item的内容</Text></View>

SwipeRow组件中我们添加一个:

//上一次滑动最后的left偏移量this._previousLeft = 0;//left偏移动画this.state = {currentLeft: new Animated.Value(this._previousLeft),};

然后在move跟end的时候操作:

 /*** 处理滑动事件* @param event* @param gestureState* @private*/_handlePanResponderMove(event: Object, gestureState: Object): void {if (this._previousLeft === null) {this._previousLeft = this.state.currentLeft._value}let nowLeft = this._previousLeft + gestureState.dx / 0.5;//右滑最大距离为0(边界值)nowLeft = Math.min(nowLeft, 0);this.state.currentLeft.setValue(nowLeft,);}/*** 结束事件的时候回调* @param event* @param gestureState* @private*/_handlePanResponderEnd(event: Object, gestureState: Object): void {console.log('_handlePanResponderEnd');this._previousLeft = null;}

最后付给动画组件:

render() {return (<View style={[styles.swipeContainer, this.props.style]}><View style={styles.swipeActions}>{this.props.children[0]}</View>{this.renderRowContent()}</View>);}renderRowContent() {return (<Animated.View{...this._panResponder.panHandlers}style={{transform: [{translateX: this.state.currentLeft}]}}>{this.props.children[1]}</Animated.View>);}

全部代码:

/*** @author YASIN* @version [React-Native Ocj V01, 2018/3/13]* @date 17/2/23* @description SwipeRow*/
import React, {Component,
} from 'react';
import PropTypes from 'prop-types';
import {Animated,PanResponder,Platform,StyleSheet,TouchableOpacity,ViewPropTypes,View,Text
} from 'react-native';export default class SwipeRow extends Component {// 构造constructor(props) {super(props);// 初始状态this._panResponder = PanResponder.create({onMoveShouldSetPanResponderCapture: this._handleMoveShouldSetPanResponderCapture.bind(this),onPanResponderGrant: this._handlePanResponderGrant.bind(this),onPanResponderMove: this._handlePanResponderMove.bind(this),onPanResponderRelease: this._handlePanResponderEnd.bind(this),onPanResponderTerminate: this._handlePanResponderEnd.bind(this),onShouldBlockNativeResponder: (event, gestureState) => false,//表示是否用 Native 平台的事件处理,默认是禁用的,全部使用 JS 中的事件处理,注意此函数目前只能在 Android 平台上使用});//上一次滑动最后的left偏移量this._previousLeft = 0;//left偏移动画this.state = {currentLeft: new Animated.Value(this._previousLeft),};}render() {return (<View style={[styles.swipeContainer, this.props.style]}><View style={styles.swipeActions}>{this.props.children[0]}</View>{this.renderRowContent()}</View>);}renderRowContent() {return (<Animated.View{...this._panResponder.panHandlers}style={{transform: [{translateX: this.state.currentLeft}]}}>{this.props.children[1]}</Animated.View>);}/*** 是否需要成为move事件响应者,返回true直接走onPanResponderMove* @param event* @param gestureState* @returns {boolean}* @private*/_handleMoveShouldSetPanResponderCapture(event: Object, gestureState: Object,): boolean {//当垂直滑动的距离<10 水平滑动的距离>10的时候才让捕获事件console.log('_handleMoveShouldSetPanResponderCapture');return Math.abs(gestureState.dy) < 10 && Math.abs(gestureState.dx) > 10;}/*** 表示申请成功,组件成为了事件处理响应者* @param event* @param gestureState* @private*/_handlePanResponderGrant(event: Object, gestureState: Object): void {console.log('_handlePanResponderGrant');}/*** 处理滑动事件* @param event* @param gestureState* @private*/_handlePanResponderMove(event: Object, gestureState: Object): void {if (this._previousLeft === null) {this._previousLeft = this.state.currentLeft._value}let nowLeft = this._previousLeft + gestureState.dx / 0.5;//右滑最大距离为0(边界值)nowLeft = Math.min(nowLeft, 0);this.state.currentLeft.setValue(nowLeft,);}/*** 结束事件的时候回调* @param event* @param gestureState* @private*/_handlePanResponderEnd(event: Object, gestureState: Object): void {console.log('_handlePanResponderEnd');this._previousLeft = null;}
}
const styles = StyleSheet.create({swipeContainer: {width: '100%',},swipeActions: {backgroundColor: 'grey',width: '100%',overflow: 'hidden',...StyleSheet.absoluteFillObject,flexDirection: 'row',justifyContent: 'flex-end'},
});

最后运行效果:

我们只差最后一步了,就是在手指提起的时候让滑动部分反弹回去就可以了~ 先留给小伙伴自己实现吧,好吧~~感觉很简单的东西,写成文字还不是件容易的事情,吃饭去啦!!下节见咯~

React-Native带你一步一步实现侧滑删除相关推荐

  1. React Native带你一步步实现热更新(CodePush-Android)

    前言:无奈研究了一下CodePush,遇到了很多坑-- 但是原理呢不是很难理解,就是配置有点多,原理可以简单的参考一下我之前的一篇博客React-Native 热更新尝试(Android),下面说一下 ...

  2. React Native 0.50版本新功能简介

    React Native在2017年经历了众多版本的迭代,从本人接触的0.29版本开始,到前不久发布的0.52版本,React Native作为目前最受欢迎的移动跨平台方案.虽然,目前存在着很多的功能 ...

  3. React Native 宣布重构计划!

    web前端教程 用大白话,来讲编程 6月中旬 Facebook 曾宣布要对 React Native 进行大规模重构,旨在使其更轻量,更具灵活性,更适应 JavaScript 生态圈的发展. 现在 F ...

  4. 【苹果家庭推iiMessage】React Native举行开发仍是iOS,用原生的代码实现类似webview的页面

    推荐内容IMESSGAE相关 作者推荐内容 iMessage苹果推软件 *** 点击即可查看作者要求内容信息 作者推荐内容 1.家庭推内容 *** 点击即可查看作者要求内容信息 作者推荐内容 2.相册 ...

  5. 手挽手带你学React:四档(上)一步一步学会react-redux (自己写个Redux)

    手挽手带你学React入门四档,用人话教你react-redux,理解redux架构,以及运用在react中.学完这一章,你就可以开始自己的react项目了. 之前在思否看到过某个大神的redux搭建 ...

  6. React-Native带你一步一步实现侧滑删除(二)

    上一节我们已经简单的实现了侧滑删除, 我们最后还留了一个小小的功能,那就是当手指抬起的时候,我们需要选择打开或者关闭侧滑功能,我们分几种情况考虑: 大的条件分两种: 一.侧滑已经打开 1.抬起手指的时 ...

  7. 从零开始带你一步一步使用 YOLOv3 测试自己的数据

    上一篇: 从零开始带你一步一步使用YOLOv3训练自己的数据 我给大家详细介绍了如何使用 YOLOv3 模型来训练自己的数据集.训练部分完成,本文将继续给大家详细介绍如何使用我们训练好的模型来进行图片 ...

  8. 从零开始带你一步一步使用YOLOv3测试自己的数据

    红色石头的个人网站:redstonewill.com 知乎:https://www.zhihu.com/people/red_stone_wl 公众号:AI有道(redstonewill) 上一篇: ...

  9. 从零开始带你一步一步使用YOLOv3训练自己的数据

    红色石头的个人网站:redstonewill.com 知乎:https://www.zhihu.com/people/red_stone_wl 公众号:AI有道(redstonewill) YOLOv ...

最新文章

  1. C# - 基于LinkLabel可动态生成多超链接信息的自定义控件
  2. C++ Set常用用法
  3. sed命令详解--转
  4. JAX-RS Bean验证错误消息国际化
  5. Visio安装网盘,我不会破解
  6. 背景透明及引发的文字透明问题
  7. 极光:2019年个人网盘行业研究报告
  8. 全市场等权中位数_市场指数估值周报20200418
  9. Linux CentOS 大数据集群的基础配置(3) CHD分布式环境搭建
  10. WhatsApp被禁用该如何操作呢?实操WhatsApp解封全过程| 2022五月
  11. Kaggle-泰坦尼克号-机器学习/数据挖掘学习笔记
  12. 小记!华为 8.0系统切换APP内语言(中英文)无效(其他版本手机均有效)。
  13. debian修改字体
  14. 如何在office word or ppt 中插入Latex公式
  15. sas mysql乱码_SAS 数据步 常见错误汇总之1-上
  16. Ubuntu 20.04 安装Azure Kinect SDK和ROS driver以及遇到k4a的报错
  17. 测井计算机使用的总线,测井数据处理开始步入工作站时代
  18. hibrnate教程14~Hibernate JPA注解入门
  19. 小微权力监督平台功能列表:实现三资管理、大数据比对、监督举报等
  20. Photoshop软件的应用领域介绍

热门文章

  1. GPS 车辆追踪软件 GIS系统和分布式
  2. BAT常问面试题JVM
  3. telegrame机器人爬坑
  4. VAR 在 Stata 中的模拟、估计和推断
  5. 《炬丰科技-半导体工艺》 碳化硅技术优于传统硅技术
  6. java多线程编程从入门到卓越(超详细总结)
  7. 关于开学一个月的学习感悟
  8. python神经网络训练完了怎么输入得到结果_python神经网络读书笔记
  9. 刷题_33:剪花布条 and 客似云来
  10. 关于GreaterWMS我踩过的坑