向上拖动ScrollView,然后在React Native中继续滚动

时间:2018-11-28 16:05:14

标签: react-native react-native-scrollview

我想要什么(GIF)

这是关于(我要实现的)质量降低的GIF。

enter image description here

我想要的(文本)

我有一个scrollview,它位于屏幕的一半。

我想要的是将scrollview向上拖动,然后在到达某个位置时将drag touch event发送到scrollview本身,以便它可以继续滚动。

我的尝试

  • 将滚动视图全屏显示在前景中,并在其contentContainerStyle上添加一个半屏填充。效果很好,但是我无法单击它后面的视图。有没有办法点击滚动视图的空白区域
  • 我还尝试检测滚动位置,以便相应地向上移动视图

    <ScrollView onScroll={event => moveScrollViewUpIfNeeded(event)}>
        ...
    </ScrollView>
    

    ,但是当我在iOS模拟器上对其进行测试时无法正常工作。事件甚至没有触发。 React Native Docs指出onScroll需要scrollEventThrottle才能工作。但是,scrollEventThrottle仅是available on iOS。就我而言,我也想在Android上使用它。
    而且,如果我成功实现了这一点,我将面临另一个UI问题:向上拖动ScrollView时,如何在视图尚未到达所需位置时阻止它滚动?

那么,请您给我一些技巧来实现这一目标:)?

谢谢

2 个答案:

答案 0 :(得分:7)

我尝试了几种选择。这是我的性能最佳的解决方案。当然,这只是一个可行的示例,您可能需要进一步优化它以完全满足您的需求。

演示:

Demo Gif

说明:

基本思想是将地图始终保持在叠加层的背景中。叠加层是绝对定位的,包含两个视图。一个视图是透明的,我们仍然可以在其中查看和控制地图,另一个视图包含实际的ScrollView。诀窍是设置父叠加层的pointerEvents="box-none",并在要与地图进行交互的View的pointerEvents="none"中禁用指标事件。

基本渲染方法:

  <SafeAreaView style={{flex: 1}}>
     <MapView
      initialRegion={region}
      style={{height: HEIGHT, width: WIDTH}}
      /> 
    <View  pointerEvents="box-none"style={{height: HEIGHT, width: WIDTH, position: 'absolute'}}>
      <View pointerEvents="none" style={{height: this.state.height, backgroundColor: 'transparent'}} />
      <View style={{ height: HEIGHT-this.state.height, backgroundColor: 'white'}}>
        <ScrollView onScroll={(e) => this._onScroll(e)} scrollEventThrottle={10} >
        -- content of scrollview goes here --- 
        </ScrollView>
      </View>
    </View>

  </SafeAreaView>

滚动功能:

如果我们向下滚动ScrollView,则希望缩小空的View,以便ScrollView变为全屏。因此,我们收听ScrollView的onScroll方法。参见下面的代码和注释:

  _onScroll(e){
    // from the nativeEvent we can get the contentOffsett
    var offset_y = e.nativeEvent.contentOffset.y;
    if (offset_y > 0 ) {
     if (this.state.height>=0){
      // we are scrolling down the list, decrease height of the empty view
      this.setState({height: this.state.height-offset_y});
     }
    }
    if (offset_y <0){
      if (this.state.height <= this.state.mapHeight){
        // we are scrolling up the list, increase size of empty view/map view 
        this.setState({height: this.state.height-offset_y});
      }
    }
  }

使用ScrollView的scrollEventThrottle道具,我们可以控制_onScroll方法的调用频率。 (在这里您可能需要微调)

完整代码和工作点心

https://snack.expo.io/@tim1717/rnmapwithoverlay

答案 1 :(得分:0)

我认为最好将MapView和BottomView都放在一个ScrollView中。

它将保存自然的滚动行为,并防止诸如向下滚动时出现白色条纹或向上滚动时消失的副作用。这里的主要问题是如何为MapView设置“冻结”效果。

通过将MapView容器内的Animated相对于滚动事件进行转换,可以使用视差效果。我认为Animated libraryAnimatable components将是解决此类问题的好方法:

   scroll = new Animated.Value(0)
   render() {
      return <Animated.ScrollView ...
          onScroll={Animated.event([{nativeEvent: {contentOffset: {y: this.scroll}}}], {useNativeDriver: true})}>

        <Animated.View 
              style={
                 { ...transform: 
                       [{translateY: Animated.multiply(this.scroll, 0.8)}]}}>
          <MapView />
        </Animated.View>
        <BottomView />
      </Animated.ScrollView>
    }

实际上,如果您不希望有视差效果,可以将Animated.multiply(this.scroll, 0.8)替换为this.scroll

您可以在此处看到完整的示例:Code example

Screen capture