React native React Native-如何在水平滚动列表中模拟RefreshControl 问题

React native React Native-如何在水平滚动列表中模拟RefreshControl 问题,react-native,horizontalscrollview,react-native-scrollview,React Native,Horizontalscrollview,React Native Scrollview,我正在开发一个水平滚动列表,每次滑动时总是滚动整个屏幕(即一个“页面”)。当它在第一页上并且用户再次向右拉时,我需要刷新整个列表 对于垂直滚动视图,如果用户在视图处于最顶端位置时下拉,则会出现标准的刷新控件。但是对于水平版本,没有标准的解决方案 我的实验 想法 我尝试添加一个PanResponder来捕获触摸和移动事件。请注意,我在应用程序中使用的是VirtualizedList。基本逻辑是: 我创建了一个隐藏的视图(其宽度默认设置为0),其中包含活动指示器,并将此视图作为列表头组件插入虚拟化

我正在开发一个水平滚动列表,每次滑动时总是滚动整个屏幕(即一个“页面”)。当它在第一页上并且用户再次向右拉时,我需要刷新整个列表

对于垂直
滚动视图
,如果用户在视图处于最顶端位置时下拉,则会出现标准的
刷新控件
。但是对于水平版本,没有标准的解决方案

我的实验 想法 我尝试添加一个
PanResponder
来捕获触摸和移动事件。请注意,我在应用程序中使用的是
VirtualizedList
。基本逻辑是:

  • 我创建了一个隐藏的
    视图
    (其宽度默认设置为0),其中包含
    活动指示器
    ,并将此视图作为
    列表头组件
    插入
    虚拟化列表
  • 我收听
    VirtualizedList
    onScroll
    事件,并不断保存最新的滚动位置
  • 当then scroll position接近0时,用户向右拉(通过
    PanResponder
    捕捉到的事件手势),然后我用ActivityIndicator设置隐藏视图宽度的动画,以模拟刷新控制行为
结果 但是,
PanResponder
无法正确捕获所需事件。大多数时候,当我在
虚拟化列表
的开头向右拉时(在安卓设备上),只有标准的击中边缘动画出现(蓝色渐变层出现)

通过添加一些日志,我发现,
onPanResponderGrant
偶尔会被触发,但是,
onPanResponderMove
onPanResponderRelease
onPanResponderTerminate
onpanresponderminationrequest
都不会被触发

onPanResponderGrant
被触发时,隐藏的
ActivityIndicator
偶尔会出现。“向右拉”效果只会很快出现,并且始终会立即停止,只显示隐藏视图的非常狭窄的部分

我猜底层的
ScrollView
会窃取事件并阻止我的代码响应。但即使我将
onPanResponderTerminationRequest
设置为始终返回
false
也不会有帮助。即使我直接用
ScrollView
替代
VirtualizedList
,也会产生相同的结果

当ScrollView滚动超过顶部时,有人知道如何正确捕获触摸和移动事件吗?或者有没有其他可行的方法来实现刷新控件的水平版本

实验代码
从“React”导入React
进口{
文本、视图、活动指示器、滚动视图、虚拟化列表、,
尺寸标注、平移响应器、动画、松弛
}从“反应本机”
设数据=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
类测试扩展了React.PureComponent{
建造师(道具){
超级(道具);
此.state={
refreshIndicatorWidth:新的动画.Value(0),
};
this.onScroll=evt=>this.\u scrollPos=evt.nativeEvent.contentOffset.x;
this.onPullToRefresh=dist=>Animated.timing(this.state.refreshIndicatorWidth{
toValue:dist,
持续时间:0,
放松:放松,线性,
}).start();
this.resetRefreshStatus=()=>{
动画。计时(this.state.refreshIndicatorWidth{
toValue:0,
}).start();
};
const shouldRespondPan=({dx,dy})=>(this.| scrollPos | | 0)<50&&dx>10&&Math.abs(dx)>Math.abs(dy);
这是.\u panResponder=panResponder.create({
onMoveShouldSetPanResponder:(evt,手势状态)=>{
返回shouldRespondPan(手势状态)
},
onMoveShouldSetPanResponderCapture:(evt,手势状态)=>{
返回shouldRespondPan(手势状态)
},
onPanResponderGrant:(evt,手势状态)=>{
console.warn('----pullgrant:'+JSON.stringify(gestureState));
},
onPanResponderMove:(evt,手势状态)=>{
console.warn('----pull-Move:'+JSON.stringify(gestureState));
this.onPullToRefresh(gestureState.dx)
},
onPanResponderTerminationRequest:()=>{
console.warn('----pull TerminationRequest:'+JSON.stringify(gestureState));
返回错误
},
onPanResponderRelease:(evt,手势状态)=>{
console.warn('----pull Release:'+JSON.stringify(gestureState));
this.props.refreshMoodList();
},
onPanResponderTerminate:()=>{
console.warn('----pull-Terminate:'+JSON.stringify(gestureState));
此参数为.resetRefreshStatus();
},
});
this.renderRow=this.renderRow.bind(this);
}
componentDidUpdate(prevProps、prevState、prevContext){
console.warn('----更新:'+JSON.stringify(this.props));
此参数为.resetRefreshStatus();
}
renderRow({item,index}){
返回(
{item}
);
}
render(){
/*******使用虚拟化列表进行测试*******/
返回(
);
/*******使用滚动视图进行测试*******/
返回(
123
);
}
}
const getItem=(数据,索引)=>data[index];
const getItemCount=data=>data.length;
常量键提取器=(项,索引)=>“R”+索引;
导出默认测试;
临时解决办法(不太完美)
  • 直接在
    onPanResponderGrant
    内部触发刷新事件(以及动画):这样,我仍然无法跟踪触摸移动。因此滚动窗格无法跟随触摸点

  • 使用附加条件将
    onPanResponderMove
    中的操作移动到
    onMoveShouldSetPanResponder
    (例如添加我的
    onScroll={(e) => {
      const xOffset = e.nativeEvent.contentOffset.x;
    
      // logic goes here to handle a negative value
    
    }}
    scrollEventThrottle={16}