Nativebase: Tabs too long (Tab height)

Created on 4 Sep 2019  路  15Comments  路  Source: GeekyAnts/NativeBase

Hi.
Since a while I have the problem that my tabs always take the length of the longest tab ...
With prerenderingSiblingsNumber = {0} (default) it is the case that the first time the
length is right, I change then in Tab 2 or 3, which are longer than the first and then
back again, the first tab is much too long and shows a lot of white space at the end.

I have gone through these following points

Issue Description

node, npm, react-native, react and native-base version, expo version if used, xcode version

Node v11.8.0
npm 6.5.0
react-native 0.58.6
native-base 2.12.0 (same with version 2.13.5)

Expected behaviour

The individual tabs should only be as long as the content

Actual behaviour

The tabs are all as long as the longest tab (in my case, the last tab contains a list and can be very long)

Steps to reproduce


Imports
import {ScrollableTab, Tab, TabHeading, Tabs} from 'native-base';

Inside main View
{/* CONTENT */} <Animated.ScrollView ref={ref => this._scrollView = ref} scrollEventThrottle={5} showsVerticalScrollIndicator={false} onScroll={Animated.event([{nativeEvent: {contentOffset: {y: this.nScroll}}}], {useNativeDriver: true})} style={{zIndex: 0}} contentContainerStyle={{paddingTop: this.state.tabIndex > 0 ? HEADER_HEIGHT : IMAGE_HEIGHT}}> <Tabs // prerenderingSiblingsNumber={0} onChangeTab={({i}) => { this.setState({contextMenu: {modalVisible: false, callContext: false}}); // set header height for reading details this.animationByClick(i); // scroll each tab to top this._scrollView.getNode().scrollTo({y: 0, animated: true,}); }} tabBarUnderlineStyle={{backgroundColor: StylingVariables.Colors.main_blue}} renderTabBar={(props) => <Animated.View style={{ transform: [{translateY: this.tabY}], zIndex: 1, width: '100%', backgroundColor: 'white', marginBottom: 22,}}> <ScrollableTab {...props} tabsContainerStyle={styles.styleTabsContainer} 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: StylingVariables.Colors.white}}> <TabHeading scrollable style={{backgroundColor: 'transparent', paddingLeft: 40, paddingRight: 40, paddingTop: 15,}} active={active}> <Animated.Text style={{ fontFamily: StylingVariables.Fonts.Text.Regular, color: active ? StylingVariables.Colors.main_blue : StylingVariables.Colors.anthrazite, fontSize: 16, }}> {name} </Animated.Text> </TabHeading> </Animated.View> </TouchableOpacity> )}/> <LinearGradient style={styles.shadow} colors={['rgba(0,0,0,0.07)', 'transparent']}/> </Animated.View> } > <Tab heading={'Tab1'}> <ShortTab/> </Tab> <Tab heading={'Tab2'}> <MiddleTab/> </Tab> <Tab heading={'Tab3'}> <LongTab/> </Tab> </Tabs> </Animated.ScrollView>

Is the bug present in both iOS and Android or in any one of them?

both, Android and iOS

Any other additional info which would help us debug the issue quicker.

I also tried wrapping each tab with a content-Tag, but the problem remains the same

awaiting response duplicate

Most helpful comment

@appify-waheed I'll try to make a snack and update here in a few days.

All 15 comments

I had this problem too a while ago. Make sure you wrap your Animated.ScrollView in provided by native base (Container should be the first tag in the class you use for the tabs). Also, for the content of each tab to be displayed properly, you need to wrap each child component of each tab in a . This is what worked for me.
For example :
native base fix1.pdf

I had faced the same issue, I got it fixed by wrapping the Tabs component with the Container of the native-base itself.

In my case i had long list in the 3rd tab so for the 3rd tab I had to specifically put Container style as height of 100% to make it scrollable, 1st and 2nd tab css I kept it as flex:1.

For doing the same i gave the css to Container as

This worked for me like a charm.

Hi @599markus, please provide minimal snack reproduction for the same.

Same issue here tabs are taking the height of the longest tab, As mentioned here.
https://github.com/ptomasroos/react-native-scrollable-tab-view/issues/415
A fix could be in this
https://github.com/turfaa/react-native-scrollable-tab-view-universal

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}

@pragupnewzera This will work for the fixed height of the tabs but if the content size is dynamic then content will cut down from bottom after specified height.

@appify-waheed Even if the content in the tabs is dynamic it would be rendered in the scroll view of tabs of given parent height. So basically every tab has height of the given parent (width/0.8 in this case) and nested ScrollView would come into effect afterwards when we try to scroll in the tabs.

@prafgup but if nested scroll is enable it is also causing problem while scrolling, sometimes scroll gets stuck with nested scroll.

@waheed25 Scrolling doesnt get stuck if you have manually disabled other scroll views inside the tabs and wrapped whole tab with nested Scroll View.

@prafgup could you please give an example. What i did, disabled the inner scroll of the list and add height of on the root view inside the scroll and also nested scroll is enabled so it scrolls only to given height not according to content height.

@prafgup could you please give an example. What i did, disabled the inner scroll of the list and add height of on the root view inside the scroll and also nested scroll is enabled so it scrolls only to given height not according to content height.

Create a createMaterialTopTabNavigator
const Tab = createMaterialTopTabNavigator()

Data used to just render The list view depending upon key

const Data = [
  {
    id: '1'
  },
  {
    id: '2',
    otherData : ......
  },
  {
    id: '3'
  }
]

Renders A List View

const Something = ({ route, navigation , client }) => {
   // Some Functions Getting Data from API

  const renderitem = ({ item }: Props) => {
    if (item.id === '1') {
      return (
      Something
      )
    }
    if (item.id === '2') {
      return (
        Something
              )

    }
    return (
    <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="MediaTab" component={MediaTab} />
      </Tab.Navigator>
    </View>
    )
  }

  return (
    <View style={styles.container}>
      <FlatList
        data={Data}
        keyExtractor={(item) => item.id}
        renderItem={renderitem}
        stickyHeaderIndices={[0,2]}      //Try Adding Your Tab Navigator as stickyHeader (Works Without it too)
        listKey={(item) => `${item.id}D`}
      />
    </View>
  )
}

Tabs Similer To This

const MediaTab = ({client}) => {
 // Some Functions Creating MediaList from API
  return (
    <View style={styles.container}>
      <ScrollView nestedScrollEnabled={true}>
        <FlatList
          numColumns={3}
          data={allMedia}
          keyExtractor={(item) => item.id}
          listKey={(post) => `${post.id}D`}
          scrollEnabled ={false}
          renderItem={({ item }) => {
            return item.multimedia_type == "IMAGE" ?
            <Image source={{uri : item.url}} style={styles.image} /> 
            : 
            <Video 
            source={{uri : item.url}} 
            style={styles.image} 
            repeat ={true}
            />
          }}
        />
      </ScrollView>
    </View>
  )
}

All Tabs Height are dynamic , as the lists are fetched from api.

Hi.
Since a while I have the problem that my tabs always take the length of the longest tab ...
With prerenderingSiblingsNumber = {0} (default) it is the case that the first time the
length is right, I change then in Tab 2 or 3, which are longer than the first and then
back again, the first tab is much too long and shows a lot of white space at the end.

I have gone through these following points

Issue Description

node, npm, react-native, react and native-base version, expo version if used, xcode version

Node v11.8.0
npm 6.5.0
react-native 0.58.6
native-base 2.12.0 (same with version 2.13.5)

Expected behaviour

The individual tabs should only be as long as the content

Actual behaviour

The tabs are all as long as the longest tab (in my case, the last tab contains a list and can be very long)

Steps to reproduce

Imports
import {ScrollableTab, Tab, TabHeading, Tabs} from 'native-base';

Inside main View

<Animated.ScrollView
    ref={ref => this._scrollView = ref}
    scrollEventThrottle={5}
    showsVerticalScrollIndicator={false}
    onScroll={Animated.event([{nativeEvent: {contentOffset: {y: this.nScroll}}}], {useNativeDriver: true})}
    style={{zIndex: 0}}
    contentContainerStyle={{paddingTop: this.state.tabIndex > 0 ? HEADER_HEIGHT : IMAGE_HEIGHT}}>
    <Tabs
        // prerenderingSiblingsNumber={0}
        onChangeTab={({i}) => {
            this.setState({contextMenu: {modalVisible: false, callContext: false}});
            // set header height for reading details
            this.animationByClick(i);
            // scroll each tab to top
            this._scrollView.getNode().scrollTo({y: 0, animated: true,});
        }}
        tabBarUnderlineStyle={{backgroundColor: StylingVariables.Colors.main_blue}}
        renderTabBar={(props) => <Animated.View
            style={{
      transform: [{translateY: this.tabY}], 
      zIndex: 1, 
      width: '100%', 
      backgroundColor: 'white', 
      marginBottom: 22,}}>
            <ScrollableTab {...props}
                           tabsContainerStyle={styles.styleTabsContainer}
                           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: StylingVariables.Colors.white}}>
                                       <TabHeading scrollable
                                                   style={{backgroundColor: 'transparent', paddingLeft: 40, paddingRight: 40, paddingTop: 15,}}
                                                   active={active}>
                                           <Animated.Text style={{
                                               fontFamily: StylingVariables.Fonts.Text.Regular,
                                               color: active ? StylingVariables.Colors.main_blue : StylingVariables.Colors.anthrazite,
                                               fontSize: 16,
                                           }}>
                                               {name}
                                           </Animated.Text>
                                       </TabHeading>
                                   </Animated.View>
                               </TouchableOpacity>
                           )}/>
            <LinearGradient style={styles.shadow} colors={['rgba(0,0,0,0.07)', 'transparent']}/>
        </Animated.View>
        }
  >
      <Tab heading={'Tab1'}>
          <ShortTab/>
      </Tab>
      <Tab heading={'Tab2'}>
          <MiddleTab/>
      </Tab>
      <Tab heading={'Tab3'}>
          <LongTab/>
      </Tab>
    </Tabs>
</Animated.ScrollView>

Is the bug present in both iOS and Android or in any one of them?

both, Android and iOS

Any other additional info which would help us debug the issue quicker.

I also tried wrapping each tab with a content-Tag, but the problem remains the same

@pragupnewzera could you please make a snack with these native-base components because I think the issue could be in react-native-scrollable-tab-view

https://github.com/ptomasroos/react-native-scrollable-tab-view/issues/415

My implementation is similar as you suggested above I have a native-base Container then I have a ScrollView with nestedScrollEnabled, This ScrollView contains three tabs and every tab have it own FlatList with different height.
I tried every above-mentioned solution but nothing works for me.

@appify-waheed I'll try to make a snack and update here in a few days.

duplicate #1501

@andreeaohno: You could post a full example at https://snack.expo.io?

@waheedakhtar694, @prafgup, @waheed25:
Here is an example of what I am trying: https://snack.expo.io/3TIg!455J
If anyone finds a solution let me know.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kitsune7 picture kitsune7  路  3Comments

sihemhssine picture sihemhssine  路  3Comments

eggybot picture eggybot  路  3Comments

georgemickael-b picture georgemickael-b  路  3Comments

nschurmann picture nschurmann  路  3Comments