Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >反应本机-如何在水平滚动列表中模拟RefreshControl

反应本机-如何在水平滚动列表中模拟RefreshControl
EN

Stack Overflow用户
提问于 2017-07-19 06:49:26
回答 1查看 2.1K关注 0票数 5

问题

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

对于垂直ScrollView,当视图位于视图的最顶端时,将出现一个标准的RefreshControl。但对于横向版本,没有标准的解决方案。

我的实验

这个想法

我尝试添加一个PanResponder来捕捉感人和感人的事件。请注意,我在应用程序中使用的是VirtualizedList。基本的逻辑是:

  • 我创建一个隐藏的View (默认情况下宽度设置为0),其中包含一个ActivityIndicator,并将此视图作为ListHeaderComponent插入到VirtualizedList
  • 我听VirtualizedListonScroll事件,并继续保存最新的滚动位置。
  • 当滚动位置接近于0时,用户右击(通过PanResponder捕获的事件手势),然后我用ActivityIndicator动画显示隐藏视图的宽度,以模拟RefreshControl行为

结果

但是,PanResponder没有正确捕获所需的事件。大多数情况下,当我在VirtualizedList开始时(在安卓设备上)时,只会出现标准的边缘动画(一个渐变的蓝色图层)。

通过添加一些日志,我发现可以偶尔触发onPanResponderGrant,但是onPanResponderMoveonPanResponderReleaseonPanResponderTerminateonPanResponderTerminationRequest都不会触发。

onPanResponderGrant被触发时,隐藏的ActivityIndicator偶尔会出现。“向右拉”的效果只会在很短的时间内出现,并且总是会立即停止,而隐藏视图的一个非常狭窄的部分就会出现。

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

当ScrollView滚动到顶部时,有没有人知道如何正确地捕捉触摸和移动事件?或者有另一种可行的方法来实现RefreshControl的水平版本

实验规范

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react'
import {
  Text, View, ActivityIndicator, ScrollView, VirtualizedList,
  Dimensions, PanResponder, Animated, Easing
} from 'react-native'


let DATA = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];

class Test extends React.PureComponent {

  constructor(props) {
    super(props);

    this.state = {
      refreshIndicatorWidth: new Animated.Value(0),
    };

    this.onScroll = evt => this._scrollPos = evt.nativeEvent.contentOffset.x;
    this.onPullToRefresh = dist => Animated.timing(this.state.refreshIndicatorWidth, {
      toValue: dist,
      duration: 0,
      easing: Easing.linear,
    }).start();
    this.resetRefreshStatus = () => {
      Animated.timing(this.state.refreshIndicatorWidth, {
        toValue: 0,
      }).start();
    };

    const shouldRespondPan = ({dx, dy}) => (this._scrollPos||0) < 50 && dx > 10 && Math.abs(dx) > Math.abs(dy);
    this._panResponder = PanResponder.create({
      onMoveShouldSetPanResponder: (evt, gestureState) => {
        return shouldRespondPan(gestureState)
      },
      onMoveShouldSetPanResponderCapture: (evt, gestureState) => {
        return shouldRespondPan(gestureState)
      },
      onPanResponderGrant: (evt, gestureState) => {
        console.warn('----pull-Grant: ' + JSON.stringify(gestureState));
      },
      onPanResponderMove: (evt, gestureState) => {
        console.warn('----pull-Move: ' + JSON.stringify(gestureState));
        this.onPullToRefresh(gestureState.dx)
      },
      onPanResponderTerminationRequest: () => {
        console.warn('----pull-TerminationRequest: ' + JSON.stringify(gestureState));
        return false
      },
      onPanResponderRelease: (evt, gestureState) => {
        console.warn('----pull-Release: ' + JSON.stringify(gestureState));
        this.props.refreshMoodList();
      },
      onPanResponderTerminate: () => {
        console.warn('----pull-Terminate: ' + JSON.stringify(gestureState));
        this.resetRefreshStatus();
      },
    });

    this.renderRow = this.renderRow.bind(this);
  }

  componentDidUpdate(prevProps, prevState, prevContext) {
    console.warn('----updated: ' + JSON.stringify(this.props));
    this.resetRefreshStatus();
  }

  renderRow({item, index}) {
    return (
      <View style={{flex: 1, alignItems: 'center', justifyContent: 'center', width: Dimensions.get('window').width, height: '100%'}}>
        <Text>{item}</Text>
      </View>
    );
  }

  render() {
    /******* Test with a VirtualizedList *******/
    return (
      <VirtualizedList
        {...this._panResponder.panHandlers}
        data={DATA}
        ListEmptyComponent={<View/>}
        getItem={getItem}
        getItemCount={getItemCount}
        keyExtractor={keyExtractor}
        renderItem={this.renderRow}
        horizontal={true}
        pagingEnabled={true}
        showsHorizontalScrollIndicator={false}
        ListHeaderComponent={(
          <Animated.View style={{flex: 1, height: '100%', width: this.state.refreshIndicatorWidth, justifyContent: 'center', alignItems: 'center'}}>
            <ActivityIndicator size="large"/>
          </Animated.View>
        )}
        onScroll={this.onScroll}
      />
    );
    /******* Test with a ScrollView *******/
    return (
      <View style={{height:Dimensions.get('window').height}}>
        <ScrollView
          {...this._panResponder.panHandlers}
          horizontal={true}
        >
          <View style={{width: Dimensions.get('window').width * 2, height: 100, backgroundColor: 'green'}}>
            <Text>123</Text>
          </View>
        </ScrollView>
      </View>
    );
  }
}

const getItem = (data, index) => data[index];
const getItemCount = data => data.length;
const keyExtractor = (item, index) => 'R' + index;

export default Test;

暂时的解决办法(不是很完美)

  • 通过这种方式,直接在onPanResponderGrant:内部触发刷新事件(以及动画),我仍然无法跟踪触摸动作。因此滚动窗格不能跟随触点。
  • onPanResponderMove 中的操作移动到带有附加条件(例如添加自己的“授予”条件判断)的 onMoveShouldSetPanResponder :这样,我可以跟踪触摸动作,但由于没有真正的“授权”,所以无法捕获*Release/*Terminate/*End事件(也就是说,我不知道触摸事件何时结束,因此永远不知道何时触发刷新事件!)

完美解

等你的主意..。

EN

回答 1

Stack Overflow用户

发布于 2017-07-19 12:04:15

您可以使用contentOffset来确定用户是否在水平列表上“拉出刷新”。下面的内容应该同时适用于FlatListScrollView

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
onScroll={(e) => {
  const xOffset = e.nativeEvent.contentOffset.x;

  // logic goes here to handle a negative value

}}
scrollEventThrottle={16}

当xOffset到达某个值时,您可以正常地做一些事情或设置一个标志。希望这能让你开始!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45194113

复制
相关文章
使用jquery获取url及url参数的方法
使用jquery获取url以及使用jquery获取url参数是我们经常要用到的操作
Jensen_97
2023/07/19
1.5K0
python-获取URL中的json数据
数据源为某系统提供的URL,打开是json文件,python代码获取如下: URL替换成自己的即可。 import urllib.request def get_record(url): resp = urllib.request.urlopen(url) ele_json = json.loads(resp.read()) return ele_json if __name__ == '__main__': print(get_record('http://abc.co/
py3study
2020/01/16
5.5K0
dns url转发_获取url参数的方法
DNSPod是一款免费智能DNS产品,可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。
全栈程序员站长
2022/11/02
6.4K0
使用js获取url中的get参数并转成json格式
写在前面的 没啥说的 上代码 思路就是先获取到?后面的参数区,然后 利用字符串转数组方法获取到各个参数 var json = {}; var url = 'https://www.ba
Theone67
2019/11/21
6.3K0
js获取url参数的方法
js获取url参数的方法有很多。 1.正则分析 function getQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r != null) return unescape(r[2]); return null; } 调用方法: alert(GetQueryString("
水击三千
2018/02/27
19.7K0
封装获取url参数的方法
功能需求:前端页面来回切换需要我们去获取URL的某个参数值。这时封装一个输入参数名获取对应参数值的函数是很有必要的; //取url上的id function getQueryString(name) { //取url上的id var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r !
青梅煮码
2023/02/18
1.7K0
【API架构】使用 JSON API 的好处
在 API 工艺的世界里,没有比设计更受热议的领域了。从 REST、gRPC 到 GraphQL,有许多方法可以设计和标准化 Web API 交互。今天,我们将注意力转向另一种方法,JSON API,JSONAPI.org 上详细介绍的用于构建 API 的规范。
架构师研究会
2022/05/29
2.8K0
图片url地址的生成获取方法
在写博客插入图片时,许多时候需要提供图片的url地址。作为菜鸡的我,自然是一脸懵逼。那么什么是所谓的url地址呢?又该如何获取图片的url地址呢?
全栈程序员站长
2022/11/08
15.9K0
图片url地址的生成获取方法
封装方法,获取url地址上的参数
https://jiangsihan.cn/?id=123&name=hhh getQueryVariable(variable) { var query = window
江一铭
2022/06/17
1.4K0
封装方法,获取url地址上的参数
php – 通过curl从url获取JSON数据「建议收藏」
我试图通过curl连接从URL获取JSON数据.当我打开链接时:它显示{“version”:“N / A”,“success”:true,“status”:true}. 现在,我希望获得以上内容.
全栈程序员站长
2022/07/11
4K0
javascript/jquery获取地址栏url参数的方法
1、jquery获取url window.location.href; 2.通过javascript是如何获取url中的某个参数 function getUrlParam(name) { var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象 var r = window.location.search.substr(1).match(reg); //匹配目标参数 if (r!=null) return unes
Yiiven
2022/12/15
1.9K0
[转载]javascript/jquery获取地址栏url参数的方法
本篇文章主要是对javascript/jquery获取地址栏url参数的方法进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助
小小鱼儿小小林
2020/06/24
3.5K0
如何使用 Go 语言获取 URL?
在 Web 开发和网络爬虫等领域,经常需要获取和处理 URL(统一资源定位符)。Go 语言提供了丰富的标准库来处理 URL,使得获取和解析 URL 变得简单而高效。本文将介绍如何使用 Go 语言获取 URL 的详细步骤,并提供一些实用的示例。
网络技术联盟站
2023/07/03
7810
如何使用 Go 语言获取 URL?
WordPress 获取当前页面 URL 地址的方法
通过 WordPress 原生的函数来,或者自定义函数,都可以获取当前页面的 URL 地址。
Yangsh888
2022/03/24
1.2K0
WordPress 获取 URL 链接路径的几种方法
其实对于 WordPress 开发方面来讲使用 ID 是最为方便快捷的,但是如果在 WordPress 固定链接中也使用文章 ID 等方式来展现虽然足够简单,却也失去了更加漂亮的 URL 以及关键词优化,所以最近子凡在开发百度小程序时需要充分的使用到百度智能小程序的自然搜索功能,需要提交 URL 适配规则,那么对于网站 URL 并不是 ID 的情况来说,小程序如果使用 ID 传参,这个适配规则基本就不在一个空间了。
张子凡
2022/11/02
1.2K0
WordPress 获取 URL 链接路径的几种方法
Akismet插件获取key API的方法
作者:matrix 被围观: 2,308 次 发布时间:2011-09-25 分类:Wordpress 兼容并蓄 | 2 条评论 »
HHTjim 部落格
2022/09/26
6850
Akismet插件获取key API的方法
Python - 使用 Tinyurl API 的 URL 缩短器
在网络时代,简洁的链接对于通过社交网站、短信和其他通信方式分发超链接至关重要。但是,冗长的 URL 可能会在共享时带来挑战,并且在发送消息时可能会被截断。长 URL 通常难以记忆,并且输入起来可能非常笨拙。为了解决手头的问题,创建了诸如TinyURL之类的网址缩短平台来管理职责。Python 提供了一种方便的方法来连接这些选项。在这篇文章中,我们将编写一个Python代码来与TinyURL网站API系统互动。
很酷的站长
2023/08/11
4310
Python - 使用 Tinyurl API 的 URL 缩短器
Vue获取url网址参数的两种方法
2、如果路由中没有传参(https://w3h5.com/detail),会报错页面无法显示。正常链接应该为 https://w3h5.com/detail/234
德顺
2020/04/26
31K1
点击加载更多

相似问题

友好的配置文件URL与控制器混在一起

25

空手道摘要报告在升级到1.0.0后没有显示所有经过测试的特性

12

如何从另一个空手道特性文件中调用依赖JAR中的空手道特性?

10

黄瓜报告中称为特性/场景的空手道显示标题

10

空手道:从被调用的特性文件中处理soap响应

111
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文