react-native拖拽体验优化

this.panResponder = PanResponder.create({
  /***************** 要求成为响应者 *****************/
  // 单机手势是否可以成为响应者
  onStartShouldSetPanResponder: (evt, gestureState) => true,
  // 移动手势是否可以成为响应者
  onMoveShouldSetPanResponder: (evt, gestureState) => true,
  // 拦截子组件的单击手势传递,是否拦截
  onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
  // 拦截子组件的移动手势传递,是否拦截
  onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
  /***************** 响应者事件回调处理 *****************/
  // 单击手势监听回调
  onPanResponderGrant: (e, gestureState) => {
    console.log('onPanResponderGrant==>' + '单击手势申请成功,开始处理手势');
    this._onPanResponderGrant(e);
  },
  // 移动手势监听回调
  onPanResponderMove: throttle((e, gestureState) => {
    console.log('onPanResponderMove==>' + '移动手势申请成功,开始处理手势' + `${gestureState}`);
    this._onPanResponderMove(e, gestureState);
  }, 200),
  // 手势动作结束回调
  onPanResponderEnd: (evt, gestureState) => {
    console.log('onPanResponderEnd==>' + '手势操作完成了,用户离开');
    this._onPanResponderEnd(evt);
  },
  // 手势释放, 响应者释放回调
  onPanResponderRelease: (e, gestureState) => {
    // 用户放开了所有的触摸点,且此时视图已经成为了响应者。
    // 一般来说这意味着一个手势操作已经成功完成。
    this._onPanResponderRelease(e, gestureState);
    console.log('onPanResponderRelease==>' + '放开了触摸,手势结束');
  },
  // 手势申请失败,未成为响应者的回调
  onResponderReject: (e, gestureState) => {
    // 申请失败,其他组件未释放响应者
    console.log('onResponderReject==>' + '响应者申请失败');
    this._onPanResponderRelease(e, gestureState);
  },
  // 当前手势被强制取消的回调
  onPanResponderTerminate: e => {
    // 另一个组件已经成为了新的响应者,所以当前手势将被取消
    console.log('onPanResponderTerminate==>' + '由于某些原因(系统等),所以当前手势将被取消');
    return true;
  },
  onShouldBlockNativeResponder: (evt, gestureState) => {
    return true;
  }
});
  

需求是多个可以拖拽的对象所以需要知道每次是拖拽哪个,而调用方法需要用 {...this.panResponder.panHandlers}解构之后得到的json通过props传递给组件,使得组件变成响应者,打印{...this.panResponder.panHandlers}

[图片上传失败...(image-3e7074-1580929245556)]

多个拖拽就不能知道是哪个变成了响应者

  1. 不用解构,给View绑定事件,传递index

Animated.View绑定事件,如

<Animated.View
  onResponderMove={(nativeEvent, gestureState) => this.onResponderMove(index, nativeEvent, gestureState}
>

将index作为参数传递过去就知道是哪项作为了响应者,但是,参数中gestureState是undefined

[图片上传失败...(image-5cb757-1580929245556)]

官网中说:它提供了一个对触摸响应系统响应器的可预测的包装。对于每一个处理函数,它在原生事件之外提供了一个新的gestureState对象。

所以不用PanResponder.create得不到gestureState对象

2.通过重写解构出来的{...this.panResponder}后的onResponderGrant将index放到state中

List.map(li => (
    <Animated.View
      style={styles.scheduleMoveImgView}
      {...this.panResponder.panHandlers}
      onResponderGrant={e => {
        this.touchY = e.nativeEvent.locationY - 12;
        this.initHeight = ((li.end - li.start) / 1800) * initOneHeight;
        this.dragItem = li;
        this.setState({
          isMove: true,
          movingHeight: this.initHeight,
          dragIndex: index
        });
      }}
    >
    </Animated.View>
))

项目中使用了第二种方法,因为拖拽时需要得到gestureState对象

[站外图片上传中...(image-ff863f-1580929245556)]

<ScrollView
  style={{ flex: 1 }}
  scrollEnabled={!isMove}
  ref={view => {
    this.areaScrollView = view;
  }}
>
    <View style={styles.scheduleList}>
        {
            scheduleList.map((li, index) => ())
        }
    </View>
    <View style={styles.lineWrap}>
        {
            scheduleList.map((li, index) => ())
        }
    </View>
    <View style={styles.scheduleSelectList}>
        {
            scheduleSelectList.map((li, index) => ())
        }
    </View>
</ScrollView>

ScrollView的children有3个View,scheduleList是0-24小时的间距,lineWrap是今天线,绝对定位,scheduleSelectList是选中的时间段,绝对定位。

android中的坑

[图片上传失败...(image-8bd84e-1580929245556)]


[图片上传失败...(image-d90c41-1580929245556)]

在android里面只有1/4的区域能够点击,ios没事,截图中绿色和黄色的交界处才能点击。原来只有图标能点击(圆圈灰色X,2424),在手机中点击体验不好,改成黄色区域能够点击(5050),因为黄色删除按钮和拖动按钮都是绝对定位,通过拖动,动态设置box(蓝色区域)的height。

box{
    position: 'absolute',
    top,
    height
}

蓝色区域外的区域点击在android中无效

解决方案

<View> // 青色区域,top - 25, 高度 + 50
    <View></View> // 内部边框区域 margin 25
</View>

[图片上传失败...(image-6670c6-1580929245556)]

这个时候,按钮就在区域内了,可以点击按钮全部位置了

接下来就遇到第二个问题

2个box之间间隔一个区域,这个时候就不能选择这个区域了,2个box区域重叠,上面一个box的高度向下25,下面一个box的top向上25,中间的一个区域不能点击

设置区域position: 'absolute', zIndex: 100会导致按钮的3/4能点击,左下角1/4不能点击问题

[图片上传失败...(image-11774f-1580929245556)]

解决方案

<View> // 一块区域
    <View></View> // 不定位
    <View></View> // 定位(宽度80%)
</View>

解决之后

[图片上传失败...(image-7bd580-1580929245556)]

红色区域在andriod能点击选中

但是在ios中红色区域是在青色的内部(心中感到ios和anroid都有不同的渲染机制,都有坑),只有设置外层的View的zIndex: 100大于青色区域才行,ios中内部View的zIndex是在外层zIndex 的基础上的。所以方案失败。(如果设置外面的View的zIndex: 100,就不能设置width: 80%, 因为每个区域都有一个下边框,80%的话下边框的长度也变成了80%了,可以通过设置内部的View的width为Dimensions.get('window').width*0.8 这时候的下边框就是一样了,最终没采用这种方案)

最终方案

通过设置 scheduleList.map((li, index) => ()) 生成不同时间段的高为0.5的下边框(绝对定位), 内部View展示为80%,效果就是上图一样了

rn的体验等级,能用,凑合,流畅,丝滑

最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351