Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-native: scrollview inside of panResponder

Tags:

I am using a ScrollView inside of a PanResponder. On Android it works fine but on iOS the ScrollView will not scroll. I did some investigation and here are some facts:

  1. If I put a break point in PanResponder.onMoveShouldSetPanResponder(), before I step over, the scrollView will scroll as normal but once I release the break point, the scrollView stops working.

  2. If I modify ScrollResponder.js, and return true in scrollResponderHandleStartShouldSetResponderCapture() - it used to return false at runtime; and return false in scrollResponderHandleTerminationRequest(), the scrollView works OK but of course, since it swallows the event the outer PanResponder will not get the event.

So the questions are:

  1. I want to make the scrollview to work, and not to swallow the event. Any one know what's the approach?
  2. How the responding system works on iOS? The react-native responder system doc does not explain that to me.
like image 210
YANG Lei Avatar asked Feb 25 '16 06:02

YANG Lei


1 Answers

I finally solve this by wrap the scrollview inside a view ,and set the style of scrollview a limited height.

import * as React from 'react';
import { Text, View, StyleSheet,PanResponder,Animated,ScrollView,Dimensions} from 'react-native';
import { Constants } from 'expo';

const WINDOW_WIDTH = Dimensions.get("window").width;
const WINDOW_HEIGHT = Dimensions.get("window").height;
// You can import from local files

export default class App extends React.Component {
  constructor(props){
    super(props);
    this.minTop = 100;
    this.maxTop = 500;
    this.state={
      AnimatedTop:new Animated.Value(0),
    }
  }

  componentWillMount(){
    let that = this;
    this._previousTop = 100;
    this._panResponder = PanResponder.create({
      onMoveShouldSetPanResponder(){
        return true;
      },
      onPanResponderGrant(){
        that._previousTop = that.state.AnimatedTop.__getValue();
        return true;
      },
      onPanResponderMove(evt,gestureState){
        let currentTop = that._previousTop + gestureState.dy;
        that.state.AnimatedTop.setValue(that._previousTop+gestureState.dy);

      },
      onPanResponderRelease(){

      }
    })
  }


  render() {
    return (
      <View style={styles.container}>
        <Animated.View
          style={[styles.overlay,{top:this.state.AnimatedTop}]}
          {...this._panResponder.panHandlers}
        >
          <View style={{height:200,backgroundColor:"black"}}></View>
          <View>
            <ScrollView
              style={{height:500}}
            >
              <View style={{backgroundColor:"blue",height:200}}></View>
              <View style={{backgroundColor:"yellow",height:200}}></View>
              <View style={{backgroundColor:"pink",height:200}}></View>
              <View style={{backgroundColor:"red",height:200}}></View>
            </ScrollView>
          </View>
        </Animated.View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  overlay:{
    position:"absolute",
    width:WINDOW_WIDTH,
    height:WINDOW_HEIGHT-100,
  }
});

enter link description here I spent plenty of time to solve this.Hope this will help someone confused with the same problem.

like image 101
Devin Gong Avatar answered Sep 22 '22 06:09

Devin Gong