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)]
多个拖拽就不能知道是哪个变成了响应者
- 不用解构,给View绑定事件,传递index
Animated.View
绑定事件,如
this.onResponderMove(index, nativeEvent, gestureState}
>
将index作为参数传递过去就知道是哪项作为了响应者,但是,参数中gestureState是undefined
[图片上传失败...(image-5cb757-1580929245556)]
官网中说:它提供了一个对触摸响应系统响应器的可预测的包装。对于每一个处理函数,它在原生事件之外提供了一个新的gestureState对象。
所以不用PanResponder.create
得不到gestureState对象
2.通过重写解构出来的{...this.panResponder}
后的onResponderGrant
将index放到state中
List.map(li => (
{
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
});
}}
>
))
项目中使用了第二种方法,因为拖拽时需要得到gestureState对象
[站外图片上传中...(image-ff863f-1580929245556)]
{
this.areaScrollView = view;
}}
>
{
scheduleList.map((li, index) => ())
}
{
scheduleList.map((li, index) => ())
}
{
scheduleSelectList.map((li, index) => ())
}
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中无效
解决方案
// 青色区域,top - 25, 高度 + 50
// 内部边框区域 margin 25
[图片上传失败...(image-6670c6-1580929245556)]
这个时候,按钮就在区域内了,可以点击按钮全部位置了
接下来就遇到第二个问题
2个box之间间隔一个区域,这个时候就不能选择这个区域了,2个box区域重叠,上面一个box的高度向下25,下面一个box的top向上25,中间的一个区域不能点击
设置区域position: 'absolute', zIndex: 100
会导致按钮的3/4
能点击,左下角1/4
不能点击问题
[图片上传失败...(image-11774f-1580929245556)]
解决方案
// 一块区域
// 不定位
// 定位(宽度80%)
解决之后
[图片上传失败...(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的体验等级,能用,凑合,流畅,丝滑