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时,用户向右拉(通过
捕捉到的事件手势),然后我用ActivityIndicator设置隐藏视图宽度的动画,以模拟刷新控制行为PanResponder
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}