createMaterialTopTabNavigator inside ScrollView with dynamic height

Viewed 4708

Is there any way to create something like a ScrollView with dynamic height?

Details on what we're trying to do:

We created a Top Tab Bar (using createMaterialTopTabNavigator) within a ScrollView. Everything works fine, except the height of the ScrollView. Let's assume there are 3 tab screens with different heights: TabScreen1: 800, TabScreen2: 400, TabScreen3: 300... At rendering, the ScrollView takes the greatest height, and when Tab2 or 3 is selected, the height of our ScrollView remains at 800, so there is empty space for scrolling in Tab2 and 3. enter image description here

3 Answers

As I promised, here is how we solved it.

In your class where you have your ScrollView you need a state like

const [activeTab, setActiveTab] = useState('tab1') //your default (first) tab

Later, you want to change that state every time you change tab:

<TabsStack.Screen
  name={'tab1'}
  component={
    activeTab === 'tab1' ? Tab1Screen : DefaultScreen
  }
  listeners={{ focus: () => setActiveTab('tab1') }}
/>

Now every time a tab is unselected or rather not focused it will show DefaultScreen which is an empty view and has no height like:

const DefaultScreen = () => (
  <Box
    flex={1}
    py={20}
    alignItems="center"
    justifyContent="center"
    bg="background"
  >
    <ActivityIndicator size="large" color="white" animating />
  </Box>
)

In my case (see question above), every time I switch from Tab1.1.1 to Tab1.1.2, Tab1.1.1 will change to DefaultScreen

Try something like this, Fix the height of the parent widget to the maximum screen height you want that Tab Navigator to have.

<ListView or ScrollView>
 <View style={{height:  (width)/(0.8)}} >
    <Tab.Navigator tabBar={(props) => <TabBar {...props} />}>
      <Tab.Screen name="T1" component={T1} />
      <Tab.Screen name="T2" component={T2} />
      <Tab.Screen name="T3" component={T3} />
    </Tab.Navigator>
   </View>
</ ListView or ScrollView>

And for tabs do Something like this

T1 ->

<View style={styles.container}>
  <ScrollView nestedScrollEnabled={true}>
    <FlatList
      numColumns={3}
      data={allMedia}
      keyExtractor={(item) => item.id}
      listKey={(post) => `${post.id}D`}
      renderItem={({ item }) => (Anything)}
      scrollEnabled ={false}
    />
  </ScrollView>
</View>

Remember to disable the scroll view Inside the FlatList of tabs and wrap with a ScrollView with nestedScrollEnabled={true}

There is no need to put TabNavigator inside ScrollView. Put ScrollView inside of each TabScreen instead

Answering your question: if your ScrollView is the same height as the content then it doesn't scroll. You are probably talking about height of a contentContainer of a ScrollView. And the only wayto set it dynamically is to use onLayout to measure content height of currently selected tab, save this number to state and apply it as a height of in contentContainerStyle prop of a ScrollView. I don't recommend hacking it this way unless absolutely necessary though

Related