我如何在 React Native 中嵌套水平 ScrollView?

How can I have nested horizontal ScrollViews in React Native?

我从 React Native Nested ScrollView Can`t Scroll on Android Device

看到 React Native 提供了嵌套的垂直滚动视图

问题是它似乎不适用于 Android 上的嵌套水平滚动视图。有关示例,请参见此代码:

https://snack.expo.io/@harrytravelchime/broken-horizontal-scroll

import React from 'react';
import _ from 'lodash';
import { View, ScrollView, StyleSheet, Text, SafeAreaView } from 'react-native';

export default class App extends React.PureComponent {
  render() {
    return (
      <SafeAreaView style={styles.container}>
        <ScrollView
          style={{ height: '100%', width: '100%' }}
          horizontal
          nestedScrollEnabled
        >
          <View style={{ flexDirection: 'row' }}>
            <ScrollView
              style={{ width: 200, height: '100%' }}
              horizontal
              nestedScrollEnabled
            >
              <View style={{ flexDirection: 'row' }}>
                {_.times(200, n => (
                  <View key={1000 + n} style={{ marginRight: 10 }}>
                    <Text>{1000 + n}</Text>
                  </View>
                ))}
              </View>
            </ScrollView>
            {_.times(200, n => (
              <View key={n} style={{ marginRight: 10 }}>
                <Text>{n}</Text>
              </View>
            ))}
          </View>
        </ScrollView>
      </SafeAreaView>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'stretch',
    paddingVertical: 50,
  },
});

另一方面,除了垂直滚动之外,相同的代码完全有效: https://snack.expo.io/@harrytravelchime/working-vertical-scroll

有没有办法使嵌套水平滚动起作用?

我想出的一个解决方案是 TouchableWithoutFeedback 跟踪用户在内部 ScrollView 中的任何触摸。一旦检测到触摸,它就会禁用外部 ScrollView 上的滚动,这会导致内部 ScrollView 接收事件。

以上代码的主要变化是:

  1. 添加状态outerScrollViewScrollEnabled
  2. 当通过 TouchableWithoutFeedback 触摸内部 ScrollView 时,更改该状态
  3. 使外部 ScrollView 的 scrollEnabled 依赖于它
import React from "react";
import _ from "lodash";
import {
  View,
  ScrollView,
  StyleSheet,
  Text,
  SafeAreaView,
  TouchableWithoutFeedback
} from "react-native";

interface State {
  outerScrollViewScrollEnabled: boolean;
}

export default class App extends React.PureComponent {
  state = { outerScrollViewScrollEnabled: true };

  handleInnerPressIn = () => this.setState({ outerScrollViewScrollEnabled: false });
  handleInnerPressOut = () => this.setState({ outerScrollViewScrollEnabled: true });

  render() {
    const { outerScrollViewScrollEnabled } = this.state;

    return (
      <SafeAreaView style={styles.container}>
        <ScrollView
          style={{ height: "100%", width: "100%" }}
          horizontal
          scrollEnabled={outerScrollViewScrollEnabled}
        >
          <View style={{ flexDirection: "row" }}>
            <ScrollView style={{ width: 200, height: "100%" }} horizontal>
              <TouchableWithoutFeedback
                onPressIn={this.handleInnerPressIn}
                onPressOut={this.handleInnerPressOut}
              >
                <View style={{ flexDirection: "row" }}>
                  {_.times(200, n => (
                    <View key={1000 + n} style={{ marginRight: 10 }}>
                      <Text>{1000 + n}</Text>
                    </View>
                  ))}
                </View>
              </TouchableWithoutFeedback>
            </ScrollView>
            {_.times(200, n => (
              <View key={n} style={{ marginRight: 10 }}>
                <Text>{n}</Text>
              </View>
            ))}
          </View>
        </ScrollView>
      </SafeAreaView>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: "column",
    justifyContent: "center",
    alignItems: "stretch",
    paddingVertical: 50
  }
});

如果您使用的是 react-native-gesture-handler,还有一种更简单的解决方案

import { ScrollView } from 'react-native'
import { ScrollView as GestureHandlerScrollView } from 'react-native-gesture-handler'

<ScrollView horizontal>
    <GestureHandlerScrollView horizontal />
</ScrollVIew>

我从 react-native 那里得到了这个答案 github issue