【问题标题】:"Sticky" center element of horizontal React Native ListView水平 React Native ListView 的“粘性”中心元素
【发布时间】:2017-04-25 05:06:16
【问题描述】:

我针对这个问题的完整源代码发布为 Expo 应用程序:https://exp.host/@kevinoldlifeway/swipe-scrollview-of-webviews 以及 Github https://github.com/kevinold/swipe-scrollview-of-webviews

我正在 React Native 中构建书籍视图。使用 ScrollView,我想左右滑动浏览可能有几百到几千个标题的页面。

既然如此,我的目标是只使用最少量的数据,以便用户能够在页面之间滑动,查看上一页和下一页。

我正在加载一个 3 元素数组,如下所示:

[Previous, Current, Next]

这将由 Redux 在 state 中更新(为了简单起见,此处未使用),并将重新渲染和重新聚焦列表。

我的目标是我的ScrollView 始终位于“当前”页面的“中心”。

页面滚动到上一页和下一页由 handleScroll 方法处理,该方法加载适当的预计算数组,以便当前页面保持焦点,但上一页和下一页(屏幕外)会适当更新。

    handleScroll (event) {
    //const x = event.nativeEvent.contentOffset.x;

    const { activeIndex, scrollTimes } = this.state;

    const windowWidth = Dimensions.get('window').width;
    const eventWidth = event.nativeEvent.contentSize.width;
    const offset = event.nativeEvent.contentOffset.x;
    console.log('event width: ', eventWidth);
    console.log('event offset: ', offset);

    console.log('scrollTimes: ', scrollTimes);
    //if (scrollTimes <= 1 ) return;

    if (windowWidth + offset >= eventWidth) {
        //ScrollEnd, do sth...
        console.log('scrollEnd right (nextPage)', offset);
        const nextIndex = activeIndex + 1;
        console.log('nextIndex: ', nextIndex);

  // Load next page
  this.loadMore()

    } else if (windowWidth - offset <= eventWidth) {
        //ScrollEnd, do sth...
        console.log('scrollEnd left (prevPage)', offset);

  // Load prev page
  this.loadPrev()
    }

    this.setState({ scrollTimes: scrollTimes + 1 });
}

我尝试使用以下组合来平衡“当前”页面:

contentOffset={{ x: width, y: 0 }}ScrollView

componentDidMount() {
    // Attempt to keep "center" element in array as focused "screen" in the horizontal list view
    this.scrollView.scrollTo({ x: width, y: 0, animated: false });
}

我也尝试在this.setState之后的回调中scrollTo,但没有任何运气。

我想知道这种“居中”是否可以通过使用Animated 来完成。

【问题讨论】:

    标签: react-native react-native-android react-native-ios react-native-scrollview react-animated


    【解决方案1】:

    我试了一下,但我不完全确定我理解了这个问题,而且我不确定这会持续多久。

    基本上我只是显着简化了 handleScroll 函数。首先检查我们是否处于滚动完成状态,如果是,则确定我们到达该屏幕时是“上一个”屏幕还是“下一个”屏幕 - 如果它已经是中间屏幕,则什么也不做。

    我认为在您的代码中,问题在于如果它是中间屏幕,而不仅仅是第一个或最后一个屏幕,它会触发并加载数据。因此,每次转换都会触发两次。

    这是我认为适合你的handleScroll。

    handleScroll (event) {
      const offset = event.nativeEvent.contentOffset.x;
      const mod = offset % width;
    
      if (mod === 0) { // only transition on scroll complete
        if (offset === width * 2) { // last screen
          console.log('load more')
          this.loadMore();
          this.scrollView.scrollTo({ x: width, y: 0, animated: false });
        } else if (offset !== width) { // first screen
          console.log('load prev')
          this.loadPrev();
          this.scrollView.scrollTo({ x: width, y: 0, animated: false });
        }
      }
    }
    

    还有一个Snack 进行演示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-17
      • 2022-01-01
      • 2017-07-03
      • 2021-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多