简体   繁体   中英

How to create a sticky tab selector with nested scrollviews like twitter or instagram profile screens [REACT-NATIVE]

I'm trying to create a ScrollView which contains one sticky selector, that allow the selection between two nested ScollViews. It's like the twitter profile screen, or the instagram screen, where you can switch between my posts and posts where I was tagged. Now my problem actually is that this two nested ScollViews, let's say "MY POSTS" and "TAGGED" could have different sizes, but the RootScrollView consider only the biggest height of the two scrollviews, so if in the first I've 20 items, and let's say height=1000, in the second if I don't have items, or less items, I'll have an empty space y offset like the first.

I know it's not so clear, but if you open instagram or twitter profile screens you'll immediately get it, the problem of the different heights.

Now as you'll see, what I've tried to do is create a RootScrollView, put inside it two views, the header and the sticky selector, in twitter it's the "Tweet", "Tweets and replies"... , and the a NestedScrollView which initially has scrollEnabled=false, and then, by scroll the root I'll update it to true and to false the root one. But it seems not to work correctly.

推特个人资料 代码说明

Here's the code:

const HEADER_HEIGHT = height / 3;
const STIKY_SELECTOR_HEIGHT = 100;

const App = () => {
  const rootScrollRef = useRef();
  const nestedScrollRef = useRef();

  const [offset, setOffset] = useState(0);
  const [scrollEnabled, setScrollEnabled] = useState(false);

  const onRootScroll = ({
    nativeEvent: {
      contentOffset: { y },
    },
  }) => {
    const direction = y > offset ? "down" : "up";
    setOffset(y);

    if (y > HEADER_HEIGHT - 10 && direction == "down") {
      setScrollEnabled(true);
    }
  };

  const onNestedScroll = ({
    nativeEvent: {
      contentOffset: { y },
    },
  }) => {
    if (y < 20) setScrollEnabled(false);
  };

  const renderItem = () => {
    return <View style={styles.cell} />;
  };

  return (
    <View style={{ flex: 1 }}>
      {/* ROOT SCROLLVIEW */}

      <ScrollView
        simultaneousHandlers={nestedScrollRef}
        scrollEventThrottle={16}
        ref={rootScrollRef}
        onScroll={onRootScroll}
        stickyHeaderIndices={[1]}
        scrollEnabled={!scrollEnabled}
        style={{ flex: 1, backgroundColor: "gray" }}
      >
        {/* HEADER */}

        <View
          style={{ width, height: HEADER_HEIGHT, backgroundColor: "darkblue" }}
        ></View>

        {/* STIKY SELECTOR VIEW */}
        <View
          style={{ height: STIKY_SELECTOR_HEIGHT, backgroundColor: "red" }}
        ></View>

        {/* NESTED SCROLLVIEW */}

        <View style={{ height: height - STIKY_SELECTOR_HEIGHT }}>
          <FlatList
            data={[1, 2, 3, 4, 5, 6, 7]}
            ref={nestedScrollRef}
            scrollEventThrottle={16}
            onScroll={onNestedScroll}
            scrollEnabled={scrollEnabled}
            renderItem={renderItem}
            numColumns={2}
            contentContainerStyle={{
              justifyContent: "space-between",
            }}
          />
        </View>
      </ScrollView>
    </View>
  );
};

If someone is facing the same problem there a component for that react-native-collapsible-tab-view

<Tabs.Container
  renderHeader={Header}
  headerHeight={HEADER_HEIGHT} // optional>
  <Tabs.Tab name="A">
    <Tabs.FlatList
      data={DATA}
      renderItem={renderItem}
      keyExtractor={identity}
    />
  </Tabs.Tab>
  <Tabs.Tab name="B">
    <Tabs.ScrollView>
      <View style={[styles.box, styles.boxA]} />
      <View style={[styles.box, styles.boxB]} />
    </Tabs.ScrollView>
  </Tabs.Tab>
</Tabs.Container>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM