3

Looking at this example from React Navigation website, between Chat and Contacts, the heights are independent of each other. However, When I tried to implement a top bar, the heights are the same. It takes the height of which ever tab has the most content in it.

But in the example, you can see in Contacts that there may be more contacts where you can scroll, and in Chat, the input field is at the bottom, making it look like that's where it stops.

Here's a screen shot from the example:

Chat tab

enter image description here

Contacts tab

enter image description here

Here's some of my code and what I'm experiencing:

<View style={{backgroundColor: 'orange'}}>
  {!loading &&
    !loadingProfileInfo &&
    typeof data.infoByUser !== 'undefined' && (
      <FlatList
        data={data.infoByUser}
        ListHeaderComponent={
          <View>
            <UserInfo />

            <Tab.Navigator>
              <Tab.Screen 
                name="Test" 
                component={TestComponent} />
              <Tab.Screen
                name="New Tab"
                component={NewTabComponent}
              />
            </Tab.Navigator>
          </View>
        }
        numColumns={2}
        renderItem={({item}) => (
          <View>
           // ...
          </View>
        )}
        keyExtractor={item => item._id}
      />
    )}
</View>

TestComponent

<View style={{backgroundColor: 'grey'}}>
  <View>
    <Text>Test Test</Text>
  </View>
  <View>
    <Text>Test Test</Text>
  </View>
  <View>
    <Text>Test Test</Text>
  </View>
  <View>
    <Text>Test Test</Text>
  </View>
  <View>
    <Text>Test Test</Text>
  </View>
</View>

NewTabComponent

<View style={{backgroundColor: 'red'}}>
  <Text>new tab</Text>
</View>

enter image description here enter image description here

Notice how the New Tab has a big gap between the red and the orange, that's from the Test tab's height.

hellomello
  • 8,219
  • 39
  • 151
  • 297

4 Answers4

1

You are rendering your entire navigator as the FlatList 'header'. You shouldn't even use Flatlist in this component. Each screen has a different number of items, and should have its own Flatlist.

To fix this:

  • Remove the FlatList from your main component (with backgroundColor: 'orange'), and just render the Tab Navigator in that render function.

  • Inside of TestComponent and NewTabComponent, render a ScrollView (or FlatList) if you need it.

  • All screens (TestComponent and NewTabComponent) should have a height: '100%' or flex: 1 if you want all screens to take all up all the space of the screen, even when its real height is less than the screen height.

Ben Butterworth
  • 22,056
  • 10
  • 114
  • 167
  • I added screen shot and code, you can see that my tabs height are not based on the content. – hellomello Apr 15 '20 at 21:31
  • If the TestComponent and NewTabeComponent each have their own scroll, then how do I scroll the main component? In my main component, I have user information at the top (similar to Instagram's profile section), how do I scroll with this? These tabs are below the userinformation section – hellomello Apr 18 '20 at 17:45
  • If you want your 'user information' to scroll away, then it should also be in the same ScrollView. Is there a reason why you want to keep it outside the Scrollview? Are you showing the user information in both tabs? This [tutorial](https://www.youtube.com/watch?v=9g_73wEbX8E) might be useful. – Ben Butterworth Apr 18 '20 at 18:24
  • Thanks for the tutorial link. It looks like he doesn't even use a flatlist or any scrollview, not even sure how he's able to view, perhaps I need to watch all his tutorials. But the reason why I've chosen to have a flatlist is because of performance. From my understanding, that was why the flatlist was created? Also, he's not using react native navigation tabs, perhaps his method of just checking which tab to click is a preferred method? – hellomello Apr 18 '20 at 19:12
  • I can't see a way of putting something outside of `createMaterialTopTabNavigator` in the same screen. I think why some youtube tutorials go with less common libraries is for the flexibility that you need. – Ben Butterworth Apr 18 '20 at 19:41
  • Did you get it done? Some time ago I tried to handle this flexbox equal height directly touching the rn tab viene component – Victor Molina Nov 28 '20 at 19:22
1

To have heights according to the content inside the particular tab, use Scrollview inside each tab screen. Thank me later if this works perfectly. :)

import * as React from "react";
import { ScrollView, Text, View } from "react-native";
import { createMaterialTopTabNavigator } from "@react-navigation/material-top-tabs";

function Screen1() {
  return (
    <ScrollView>
      <View style={{ flex: 1, alignItems: "center" }}>
        <Text style={{ padding: 10 }}>Screen1 </Text>
      </View>
    </ScrollView>
  );
}

function Screen2() {
  return (
    <ScrollView>
      <View style={{ flex: 1, alignItems: "center" }}>
        <Text style={{ padding: 10 }}>Screen2</Text>
      </View>
    </ScrollView>
  );
}

function Screen3() {
  return (
    <ScrollView>
      <View style={{ flex: 1, alignItems: "center" }}>
        <Text style={{ padding: 10 }}>Screen3 </Text>
      </View>
    </ScrollView>
  );
}

const Tab = createMaterialTopTabNavigator();

export default function TopBarNavigator() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Screen1" component={Screen1} />
      <Tab.Screen name="Screen2" component={Screen2} />
      <Tab.Screen name="Screen3" component={Screen3} />
    </Tab.Navigator>
  );
}
Harshal
  • 7,562
  • 2
  • 30
  • 20
0

I'm having no idea why you're rendering it inside FlatList as it also inherits props from Scroll View.

<View style={{backgroundColor: 'orange'}}>
  <Tab.Navigator>
      <Tab.Screen 
        name="Test" 
        component={TestComponent} />
      <Tab.Screen
        name="New Tab"
        component={NewTabComponent}
      />
  </Tab.Navigator>
</View>

and move the FlatList and other business logics inside the TestComponent or the NewTabComponent.

The point is don't render Tabs inside ScrollView or FlatList or SectionList as they both inherit the props of ScrollView.

Ashwin Mothilal
  • 2,462
  • 1
  • 16
  • 21
  • I did it this way because I wanted some type of header, like how Instagram's profile page works. So when you scroll, the tabs will scroll with the profile information that's at the top of the screen – hellomello Apr 17 '20 at 17:42
  • @hellomello I am experienced exactly the same issue, did you fix that? I think it is because of wrapping the Tab inside the FlatList Footer – Victor Molina Aug 26 '20 at 23:09
0

After a long research I found out that your problem is because react-native-tab-view (which is used by material-tob-tabs), has this code :

_defineProperty(this, "handleLayout", e => {
  const {
    height,
    width
  } = e.nativeEvent.layout;

  if (this.state.layout.width === width && this.state.layout.height === height) {
    return;
  }

  this.setState({
    layout: {
      height,
      width
    }
  });

With option lazy={true} , and using the "New Tab" component on first tab and "Test" on second, you get the right height until you change the tab. When you press on "Test" the layout changes so the height is bigger. After changing tab the height does't change anymore because the layout stays the same ("New Tab" fits perfectly in the bigger height) and doesn't trigger handleLayout from react-native-tab-view.

Hope you can find a way to change the layout again when you change tabs.

CevaComic
  • 2,056
  • 2
  • 6
  • 12