簡體   English   中英

React-native:panResponder 內的滾動視圖

[英]React-native: scrollview inside of panResponder

我在 PanResponder 中使用了 ScrollView。 在 Android 上它工作正常,但在 iOS 上 ScrollView 不會滾動。 我做了一些調查,這里有一些事實:

  1. 如果我在PanResponder.onMoveShouldSetPanResponder()放置一個斷點,在我跨過去之前,scrollView 將正常滾動,但是一旦我釋放斷點,scrollView 就會停止工作。

  2. 如果我修改 ScrollResponder.js,並在scrollResponderHandleStartShouldSetResponderCapture()返回 true - 它曾經在運行時返回 false; 並在scrollResponderHandleTerminationRequest()返回 false ,scrollView 工作正常,但當然,因為它吞下了事件,外部PanResponder將不會獲得該事件。

所以問題是:

  1. 我想讓滾動視圖工作,而不是吞下事件。 有人知道是什么方法嗎?
  2. 響應系統如何在 iOS 上工作? react-native 響應系統文檔沒有向我解釋這一點。

我最終通過將滾動視圖包裹在視圖中來解決這個問題,並將滾動視圖的樣式設置為有限的高度。

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,
  }
});

在這里輸入鏈接描述我花了很多時間來解決這個問題。希望這會幫助那些對同樣問題感到困惑的人。

PanResponder 中有一個返回當前觸摸位置的事件。 您可以使用它來比較 2 個值以執行滾動。

我不知道它現在是否有用,但您可以添加該行,

return !(gestureState.dx === 0 && gestureState.dy === 0)

在 PanResponder 的 'onMoveShouldSetPanResponder' 屬性中,以 evt 和gestureState 作為參數。

您的 PanResponder 應如下所示:

this._panResponder = PanResponder.create({
  onMoveShouldSetPanResponder(evt, gestureState){
    return !(gestureState.dx === 0 && gestureState.dy === 0)
  },
  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(){

  }
})

我已經通過向 ScrollView 的所有內容添加onPress處理程序解決了這個問題 - 如果處理程序是無操作的,滾動視圖仍然可以正常工作。

我通過這樣做解決了這個問題

onMoveShouldSetPanResponder: (event, gesture) => {
  if (gesture?.moveX > gesture?.moveY) {
    return false;
  }
  return true;
},

就我而言,我在 PanResponder 中有一個水平 Flatlist ......

要在具有 PanResponder 的父級的子級 ScrollView 中啟用滾動,您必須確保 ScrollView 是其中任何手勢的響應者。 默認情況下,手勢事件從最深的組件冒泡到父組件。 為了通過 ScrollView 捕獲事件,您可以添加一個內部帶有 PanResponder 的視圖。 請參閱下面的(偽)示例,其中ChildComponent是具有 PanResponder 的父級的子級。

const ChildComponent = ({ theme }) => {
    const panResponder = React.useRef(
        PanResponder.create({
            // Ask to be the responder:
            onStartShouldSetPanResponder: (evt, gestureState) => true,
            onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
        })
    ).current;

    return (
        <ScrollView style={{ height: 500 }}>
            <View {...panResponder.panHandlers}>
                ...
            </View>
        </ScrollView>
    );
};

我不確定你是否還需要這個,但我也會幫助別人

如果將 panResponder 放在 ScrollView 的同級視圖上,則 ScrollView 的行為正常。 然后您可以定位該兄弟視圖

這是解決方法的示例

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM