React-Native ListView拖拽交换Item.doc_第1页
React-Native ListView拖拽交换Item.doc_第2页
React-Native ListView拖拽交换Item.doc_第3页
React-Native ListView拖拽交换Item.doc_第4页
React-Native ListView拖拽交换Item.doc_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

React-Native ListView拖拽交换Item先上效果图:、对,就是这样在实现这个效果前,我的思路是这样的,布局-item可点击突出显示-可移动item-可交换item-抬起手指恢复正确的位置。下面一一解释。布局忘了说了,由于这个界面的item的元素较少,并且为了方便起见,我并没有采用ListView控件去实现这个list,而是使用数组map返回一个个itemView。javascript view plain copy 在CODE上查看代码片派生到我的代码片render() return( s.map(item, i)= return ( this.itemsi = ref key=i style=styles.item, top: (i+1)*49 item ); ) ); 前面NavigationBar部分不用看,自己封装的组件,通过map函数,可以依次遍历每个数组元素(s = Android,iOS,前端,拓展资源,休息视频;)。因为我们需要后面能直接控制每个DOM(后面会直接操控它的样式),所以需要添加ref属性,不熟悉或者不明白ref这个prop的,可以参考这里。还需要注意的地方是,因为我们的item是可以拖拽移动的,能直接操控它们位置属性的就是绝对和相对布局,提供了top,left,right,bottom这些个props。贴一下item的stylesheet。javascript view plain copy 在CODE上查看代码片派生到我的代码片item: flexDirection: row, height: px2dp(49), width: theme.screenWidth, alignItems: center, backgroundColor: #fff, paddingLeft: px2dp(20), borderBottomColor: theme.segment.color, borderBottomWidth: theme.segment.width, position: absolute, , 不用在意其他的props,最关键的最起作用的就是position属性,一旦设置,该View的位置就不会受控于flexbox的布局了,直接浮动受控于top,left这几个参数。对于.this._panResponder.panHandlers 这个属性,就会谈到React-native中的手势,也就是我们下一个内容。item可点击突出显示如果不了解react-native中的手势,建议简单去了解下,直通车在这里还有这个。一旦需要自己实现手势,我们需要实现这几个方法。javascript view plain copy 在CODE上查看代码片派生到我的代码片onStartShouldSetPanResponder: (evt, gestureState) = true, 开启手势响应 onMoveShouldSetPanResponder: (evt, gestureState) = true, 开启移动手势响应 onPanResponderGrant: (evt, gestureState) = 手指触碰屏幕那一刻触发 , onPanResponderMove: (evt, gestureState) = 手指在屏幕上移动触发 , onPanResponderTerminationRequest: (evt, gestureState) = true, 当有其他不同手势出现,响应是否中止当前的手势 onPanResponderRelease: (evt, gestureState) = 手指离开屏幕触发 , onPanResponderTerminate: (evt, gestureState) = 当前手势中止触发 , 简单介绍了下几个函数的意义,所以很明显,要实现item点击突出显示,我们需要在onPanRespondedGrant这里做事情。贴代码来解释,javascript view plain copy 在CODE上查看代码片派生到我的代码片onPanResponderGrant: (evt, gestureState) = const pageY, locationY = evt.nativeEvent; 1 this.index = this._getIdByPosition(pageY); 2 this.preY = pageY - locationY; 3 /get the taped item and highlight it let item = this.itemsthis.index; 4 item.setNativeProps( 5 style: shadowColor: #000, 6 shadowOpacity: 0.3, 6 shadowRadius: 5, 6 shadowOffset: height: 0, width: 2, 6 elevation: 5 7 ); , 1. evt参数有个nativeEvent对象,其中包含了一系列的参数,包括点击的位置,有几个手指点击屏幕等等。pageY是相对于根节点的位置,locationY是相对于元素自己。2. 通过这个pageY我们需要计算出这个点上是对应的哪一个item,由于我的布局简单,写个函数来计算了下,javascript view plain copy 在CODE上查看代码片派生到我的代码片_getIdByPosition(pageY) var id = -1; const height = px2dp(49); if(pageY = height & pageY = height*2 & pageY = height*3 & pageY = height*4 & pageY = height*5 & pageY let top = this.preY + gestureState.dy; let item = this.itemsthis.index; item.setNativeProps( style: top: top ); , 可交换item这个是最核心的部分了,思路是这样的,当我们点击某个item并且开始移动它的时候,我们还需要计算下,当前这个手指移动到的位置有没有进入别的Item范围,如果有,OK,我们将进入到的那个item位置放到我们手上拿着的这个item的位置。因为有了之前的函数通过位置计算id,我们可以很快的求出是否这个位置返回的id和我们手上这个item的id一样。javascript view plain copy 在CODE上查看代码片派生到我的代码片onPanResponderMove: (evt, gestureState) = let top = this.preY + gestureState.dy; let item = this.itemsthis.index; item.setNativeProps( style: top: top ); let collideIndex = this._getIdByPosition(evt.nativeEvent.pageY); 获取当前的位置上item的id if(collideIndex != this.index & collideIndex != -1) 判断是否和手上的item的id一样 let collideItem = this.itemscollideIndex; collideItem.setNativeProps( style: top: this._getTopValueYById(this.index) 将collideItem的位置移动到手上的item的位置 ); /swap two values this.itemsthis.index, this.itemscollideIndex = this.itemscollideIndex, this.itemsthis.index; this.index = collideIndex; , 在swap two value这里,我们还需要做一件很重要的事,当位置此时发生交换时,对应的item的id值我们需要进行一下交换,不然下一次再碰撞检测时,collideItem移动到的位置始终都是我们手上拿的item的初始位置。PS:这里我用的ES6的语法交换两个数的数值。抬起手指恢复正确的位置抬起手指时,我们需要做两件事: 1.将手上拿起的item的属性恢复原样,2. 将其摆到正确的位置上。第一个设置属性很简单,当初怎么改的,就怎么改回去,用setNativeProps。第二个也简单,因为我们在移动和交换过程中,始终保持id对应正确的item,所以我们只要有了id就可以计算出正确的位置。javascript view plain copy 在CODE上查看代码片派生到我的代码片onPanResponderRelease: (evt, gestureState) = const shadowStyle = shadowColor: #000, shadowOpacity: 0, shadowRadius: 0, shadowOffset: height: 0, width: 0, elevation: 0 ; let item = this.itemsthis.index; /go back the correct position item.setNativeProps( style: .shadowStyle, top: this._getTopValueYById(this.index) ); , 忘了在之前贴一下根据id计算位置的函数了,javascript view plain copy 在CODE上查看代码片派生到我的代码片_getTopValueYById(id) const height = px2dp(49); return (id + 1) * height; 因为我的NavigationBar也是行高49,所以id为0的第一item位置就应该1*49。这样就容易理解这个代码了吧。Anything Else?Finish it?咱们的数据结构呢?这个只是界面作出了改动了,我们的数据还需要做出相应的变化,这里简单起见,我在构造函数中,添加了this.order= ,当开始map时,我们就将各个item的名字push进去,所以这个数组的顺序就代表着这个list的顺序。javascript view plain copy 在CODE上查看代码片派生到我的代码片s.map(item, i)= this.order.push(item); /add code at here return ( this.itemsi = ref key=i style=styles.item, top: (i+1)*49 item ); ) 当开始交换位置时,这个order也需要交换。javascript view plain copy 在CODE上查看代码片派生到我的代码片/swap two values this.itemsthis.index, this.itemscollideIndex = this.itemscollideIndex, this.itemsthis.index; this.orderthis.index, this.ordercollideIndex = this.ordercollideIndex, this.orderthis.index; add code at here this.index = collideIndex; OK,至此,大功告成,完成。完整代码最后贴出来。关于新项目目前正在做这个新项目,因为上一个“掘金”项目,毕竟api不公开,偷偷获取数据流别人不怪罪已经很感谢了,而且有的数据获取不到,所以做不了一个完整的react-native项目,最近在用gank.io的公开api在做一个全新的项目,从界面设计到代码架构(Redux架构)都是一次全新的体验,毕竟上一个项目是第一个,还是摸索,这一次将会更加熟练,会重新规范代码结构和命名。所以欢迎大家可以关注我的新项目,PS:这个项目仍然处在开发阶段,当完成时,会再一次博客记录这次开发旅程完整代码有些代码是自己封装的,不用理会/* * Created by wangdi on 27/11/16. */use strict;import React, Component, PropTypes from react;import StyleSheet, View, Text, PanResponder from react-native;import Icon from react-native-vector-icons/Ionicons;import BackPageComponent from ./BackPageComponent;import NavigationBar from ././components/NavigationBar;import px2dp from ././utils/px2dp;import theme from ././constants/theme;export default class OrderContentPage extends BackPageComponent constructor(props) super(props); s = Android,iOS,前端,拓展资源,休息视频; this.items = ; this.order = ; render() return( s.map(item, i)= this.order.push(item); return ( this.itemsi = ref key=i style=styles.item, top: (i+1)*49 item ); ) ); componentWillMount() this._panResponder = PanResponder.create( onStartShouldSetPanResponder: (evt, gestureState) = true, onMoveShouldSetPanResponder: (evt, gestureState) = true, onPanResponderGrant: (evt, gestureState) = const pageY, locationY = evt.nativeEvent; this.index = this._getIdByPosition(pageY); this.preY = pageY - locationY; /get the taped item and highlight it let item = this.itemsthis.index; item.setNativeProps( style: shadowColor: #000, shadowOpacity: 0.3, shadowRadius: 5, shadowOffset: height: 0, width: 2, elevation: 5 ); , onPanResponderMove: (evt, gestureState) = let top = this.preY + gestureState.dy; let item = this.itemsthis.index; item.setNativeProps( style: top: top ); let collideIndex = this._getIdByPosition(evt.nativeEvent.pageY); if(collideIndex != this.index & collideIndex != -1) let collideItem = this.itemscollideIndex; collideItem.setNveProps( style: top: this._getTopValueYById(this.index) ); /swap two values this.itemsthis.index, this.itemscollideIndex = this.itemscollideIndex, this.itemsthis.index; this.orderthis.index, this.ordercollideIndex = this.ordercollideIndex, this.orderthis.index; this.index = collideIndex; , onPanResponderTerminationRequest: (evt, gestureState) = true, onPanResponderRelease: (evt, gestureState) = const shadowStyle = shadowColor: #000, shadowOpacity: 0, shadowRadius: 0, shadowOffset: height: 0, width: 0, elevation: 0 ; let item = this.itemsthis.index; /go back the correct position item.setNativeProps( style: .shadowStyle, top: this._getTopValueYById(this.index) ); console

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论