【问题标题】:Child ScrollView does not scroll when parent ScrollView stops scrolling父 ScrollView 停止滚动时子 ScrollView 不滚动
【发布时间】:2020-09-26 17:20:58
【问题描述】:

App with scroll

在我绘制的图像中,您可以看到两个区域,黄色的区域是 ScrollView,红色的区域是平面列表。 当我从红色区域滚动时,我希望选项卡向上移动到标题,一旦它们接触到标题,就开始滚动 FlatList 的红色区域。 为此,当标签触摸标题时,我将黄色区域的 scrollEnabled 设置为 false,问题是红色区域在我停止按下并再次按下之前不会滚动。

我希望它具有的行为类似于 instagram 个人资料,其中有一些标签,然后是照片列表,当标签触摸标题时,您可以继续从图像滚动。

【问题讨论】:

    标签: react-native scroll scrollview react-native-flatlist flatlist


    【解决方案1】:

    我会添加一些选项

    1. 第一个是小吃,再次使用父子滚动视图 Collapsible Header Tabs Snack

    问题:这在 Android 上存在问题。当父和子滚动视图都在滚动时,android 上的滚动会卡住。

    1. 其次是github repoReact-Native-Collapsing-TabView

    问题:如果其中一个选项卡被滚动并且您转到另一个选项卡,那么顶部会有空白。issue

    1. 使用原生基础。
    import React, {Component} from "react";
    import {Animated, Dimensions, Platform, Text, TouchableOpacity, View} from "react-native";
    import {Body, Header, List, ListItem as Item, ScrollableTab, Tab, TabHeading, Tabs, Title} from "native-base";
    import LinearGradient from "react-native-linear-gradient";
    
    const {width: SCREEN_WIDTH} = Dimensions.get("window");
    const IMAGE_HEIGHT = 250;
    const HEADER_HEIGHT = Platform.OS === "ios" ? 64 : 50;
    const SCROLL_HEIGHT = IMAGE_HEIGHT - HEADER_HEIGHT;
    const THEME_COLOR = "rgba(85,186,255, 1)";
    const FADED_THEME_COLOR = "rgba(85,186,255, 0.8)";
    
    export default class ParallaxDemo extends Component {
      nScroll = new Animated.Value(0);
      scroll = new Animated.Value(0);
      textColor = this.scroll.interpolate({
        inputRange: [0, SCROLL_HEIGHT / 5, SCROLL_HEIGHT],
        outputRange: [THEME_COLOR, FADED_THEME_COLOR, "white"],
        extrapolate: "clamp"
      });
      tabBg = this.scroll.interpolate({
        inputRange: [0, SCROLL_HEIGHT],
        outputRange: ["white", THEME_COLOR],
        extrapolate: "clamp"
      });
      tabY = this.nScroll.interpolate({
        inputRange: [0, SCROLL_HEIGHT, SCROLL_HEIGHT + 1],
        outputRange: [0, 0, 1]
      });
      headerBg = this.scroll.interpolate({
        inputRange: [0, SCROLL_HEIGHT, SCROLL_HEIGHT + 1],
        outputRange: ["transparent", "transparent", THEME_COLOR],
        extrapolate: "clamp"
      });
      imgScale = this.nScroll.interpolate({
        inputRange: [-25, 0],
        outputRange: [1.1, 1],
        extrapolateRight: "clamp"
      });
      imgOpacity = this.nScroll.interpolate({
        inputRange: [0, SCROLL_HEIGHT],
        outputRange: [1, 0],
      });
      tabContent = (x, i) => <View style={{height: this.state.height}}>
        <List onLayout={({nativeEvent: {layout: {height}}}) => {
          this.heights[i] = height;
          if (this.state.activeTab === i) this.setState({height})
        }}>
          {new Array(x).fill(null).map((_, i) => <Item key={i}><Text>Item {i}</Text></Item>)}
        </List></View>;
      heights = [500, 500];
      state = {
        activeTab: 0,
        height: 500
      };
    
      constructor(props) {
        super(props);
        this.nScroll.addListener(Animated.event([{value: this.scroll}], {useNativeDriver: false}));
      }
    
      render() {
        return (
          <View>
            <Animated.View style={{position: "absolute", width: "100%", backgroundColor: this.headerBg, zIndex: 1}}>
              <Header style={{backgroundColor: "transparent"}} hasTabs>
                <Body>
                <Title>
                  <Animated.Text style={{color: this.textColor, fontWeight: "bold"}}>
                    Tab Parallax
                  </Animated.Text>
                </Title>
                </Body>
              </Header>
            </Animated.View>
            <Animated.ScrollView
              scrollEventThrottle={5}
              showsVerticalScrollIndicator={false}
              onScroll={Animated.event([{nativeEvent: {contentOffset: {y: this.nScroll}}}], {useNativeDriver: true})}
              style={{zIndex: 0}}>
              <Animated.View style={{
                transform: [{translateY: Animated.multiply(this.nScroll, 0.65)}, {scale: this.imgScale}],
                backgroundColor: THEME_COLOR
              }}>
                <Animated.Image
                  source={{uri: "https://upload.wikimedia.org/wikipedia/commons/c/c5/Moraine_Lake_17092005.jpg"}}
                  style={{height: IMAGE_HEIGHT, width: "100%", opacity: this.imgOpacity}}>
                  {/*gradient*/}
                  {/* <LinearGradient
                    colors={["rgba(255,255,255,0.9)", "rgba(255,255,255,0.35)", "rgba(255,255,255,0)"]}
                    locations={[0, 0.25, 1]}
                    style={{position: "absolute", height: "100%", width: "100%"}}/> */}
                </Animated.Image>
              </Animated.View>
              <Tabs
                prerenderingSiblingsNumber={3}
                onChangeTab={({i}) => {
                  this.setState({height: this.heights[i], activeTab: i})
                }}
                renderTabBar={(props) => <Animated.View
                  style={{transform: [{translateY: this.tabY}], zIndex: 1, width: "100%", backgroundColor: "white"}}>
                  <ScrollableTab {...props}
                                 renderTab={(name, page, active, onPress, onLayout) => (
                                   <TouchableOpacity key={page}
                                                     onPress={() => onPress(page)}
                                                     onLayout={onLayout}
                                                     activeOpacity={0.4}>
                                     <Animated.View
                                       style={{
                                         flex: 1,
                                         height: 100,
                                         backgroundColor: this.tabBg
                                       }}>
                                       <TabHeading scrollable
                                                   style={{
                                                     backgroundColor: "transparent",
                                                     width: SCREEN_WIDTH / 2
                                                   }}
                                                   active={active}>
                                         <Animated.Text style={{
                                           fontWeight: active ? "bold" : "normal",
                                           color: this.textColor,
                                           fontSize: 14
                                         }}>
                                           {name}
                                         </Animated.Text>
                                       </TabHeading>
                                     </Animated.View>
                                   </TouchableOpacity>
                                 )}
                                 underlineStyle={{backgroundColor: this.textColor}}/>
                </Animated.View>
                }>
                <Tab heading="Tab 1">
                  {this.tabContent(30, 0)}
                </Tab>
                <Tab heading="Tab 2">
                  {this.tabContent(15, 1)}
                </Tab>
              </Tabs>
            </Animated.ScrollView>
          </View>
        )
      }
    }
    

    问题:所有屏幕由于相同的偏移量而滚动

    1. 第四个是模块Sticky parallax header,你可以从这里使用标签页眉

    问题:由于它的模块没有很大的定制空间,但也有足够的空间。而且当我使用它时,由于相同的偏移量,现在可能已经解决了一些问题,例如所有屏幕滚动。

    所以基本上说他们都有一些问题,你以后必须解决。 但我会推荐使用 netguru 的sticky-parallax-header 的第四个选项。

    【讨论】:

    • 非常感谢!一个非常完整的答案。在等待答案时,我得到了您解释的第 4 点,现在我正在测试该模块。现在我有点挣扎,因为我不希望在滚动标题并且标签触及顶部之前显示标题,如果您知道任何解决方案,我将非常感激。我想为你投赞成票,但我仍然没有必要的观点,仍然非常感谢你:D
    • 没关系。对于您需要的内容,您必须自己提出问题或编辑模块。顺便说一句,这些示例中并没有给出每个道具。所以检查节点模块内容,看看是否有你可以使用的东西。抱歉,我帮不上什么忙。
    猜你喜欢
    • 2011-09-04
    • 1970-01-01
    • 2022-11-06
    • 2012-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多