react-native-scrollable-tab-view icon indicating copy to clipboard operation
react-native-scrollable-tab-view copied to clipboard

Each tab has the same height if ScrollableTabView is placed inside a ScrollView

Open ak-paca opened this issue 7 years ago • 20 comments

I have the following code structure:

<ScrollView>
  {header}
  <ScrollableTabView>
    <View tabLabel="tab1">{smallContent}</View>
    <View tabLabel="tab2">{largeContent}</View>
  </ScrollableTabView>
</ScrollView>

the problem here is that the smallContent will have the same scrolling capacity as largeContent. Maybe someone faced the same issue? I'm also not quite sure whether it is a ScrollableTabView problem or not.

ak-paca avatar Aug 24 '17 15:08 ak-paca

have the same problem...

chuhangyu avatar Sep 06 '17 09:09 chuhangyu

main.js

  _handleTabHeight(obj){
    console.log(this.refs[obj.ref.props.tabLabel].state.name)
    this.refs[obj.ref.props.tabLabel].gogogo((x,y,w,h,l,t) => {
      if(h!==0){
        this.setState({tabViewStyle: {height: h}})
      }
    })
  }
        <ScrollableTabView
           onChangeTab={(obj) => this._handleTabHeight(obj)}
           style={this.state.tabViewStyle}
        >
            <ReactPage ref='high1' tabLabel="high1" />
            <ReactPage2 ref='high2' tabLabel="high2" />
            <ReactPage3 ref='high3' tabLabel="high3" />
        </ScrollableTabView>

ReactPage.js/ReactPage2.js/ReactPage3.js

  gogogo(cb) {
      this.refs.test.measure(cb)
  }
  render() {
    return (
      <View
        ref='test'
        style={{
          height: 300,
          backgroundColor: 'blue'
        }}
      >
      </View>
    );
  }
}

worked~!

laclys avatar Sep 08 '17 09:09 laclys

Has it been fixed ?

aijason avatar Dec 01 '17 02:12 aijason

I has the same problem

aijason avatar Dec 01 '17 02:12 aijason

+1

zhouyingkai1 avatar Jan 16 '18 08:01 zhouyingkai1

+1

orcunorcun avatar May 21 '18 10:05 orcunorcun

@laclys Thanks, your method really works. In addition, when you apply tabViewStyle's height to ScrollableTabView' style, you should plus tabBar's height. And in my practice, you can apply it to contentProps directly. like the following code:

<ScrollableTabView
  contentProps={{style:{...tabViewStyle}}}
>
</ScrollableTabView>

chulinyin avatar Jun 27 '18 03:06 chulinyin

#814 #866

hpmax00 avatar Jul 25 '18 06:07 hpmax00

Has it been fixed ? Why close this bug?

HowardTangHw avatar Dec 24 '18 03:12 HowardTangHw

I have same issue.

bharatidudhrejiya avatar Feb 11 '19 04:02 bharatidudhrejiya

Please can we re-open this issue? I don't believe there is a clear solution to the problem? @laclys is very old and I don't believe ref's work like this anymore in react-native?

alexpchin avatar Feb 19 '19 19:02 alexpchin

I'm just adding a comment to this... I'm not 100% sure if I'm correct but I believe this might solve our problem?

<ScrollableTabView style={{ flex: 1 }}>
  <FlatList tabLabel="First" contentContainerStyle={{ flexGrow: 1 }} /> // Could be inside a named component...
  <FlatList tabLabel="Second" contentContainerStyle={{ flexGrow: 1 }} /> // Could be inside a named component...
</ScrollableTabView>

alexpchin avatar Mar 05 '19 11:03 alexpchin

Yes, this needs to reopen, @laclys answer doesn't work anymore, as this.refs doesn't work like that anymore...

summerkiflain avatar Jun 13 '19 10:06 summerkiflain

Yeah, This needs to be re-open.

waheedakhtar694 avatar Apr 06 '20 11:04 waheedakhtar694

Feel free to send a pr

ptomasroos avatar Apr 06 '20 15:04 ptomasroos

export const TabContext = createContext({
  heightObj: {},
  changeState: (tabLabel, height) => { }
})
const TabProvider: FC<Props> = (props) => {
  const { children, style = {}, initialPage = 0 } = props
  const [heightObj, setHeightObj] = useState<{ [key: string]: number }>({})
  const [currentIndex, setCurrentIndex] = useState<number>(0)
  const [viewHeight, setViewHeight] = useState<number>(deviceHeight)
  const { y, onLayout } = useLayout()	//@react-native-community/hooks
  const minHeight = deviceHeight - y - 50

  const [tabLabelObj] = useState(() => {
    const obj = {}
    Children.map(children, (item: any, index) => {
      obj[index] = item.props.tabLabel
    })
    return obj
  })

  useEffect(() => {
    setCurrentIndex(0)
  }, [])

  useEffect(() => {
    getHeight()
  }, [currentIndex, tabLabelObj])

  const changeState = (tabName: string, height: number) => {
    heightObj[tabName] = height
    setHeightObj(heightObj)
  }

  const getHeight = () => {
    const data = heightObj[tabLabelObj[currentIndex || 0]]
    const _height = data > minHeight ? data : minHeight
    console.log(_height || deviceHeight)
    setViewHeight(_height || deviceHeight)
  }

  return (
    <TabContext.Provider value={{
      heightObj,
      changeState
    }}>
      <View style={[style, { height: viewHeight + 50 }]} onLayout={onLayout}>
        <ScrollableTabView
          renderTabBar={() => <TabContainer {...props} />}
          initialPage={initialPage}
          prerenderingSiblingsNumber={Infinity}
          onChangeTab={({ i }) => {
            setCurrentIndex(i)
          }}
        >
          {children}
        </ScrollableTabView>
      </View>
    </TabContext.Provider>
  )
}
const TabItem: FC<Props> = ({
  style = {},
  children,
  tabLabel,
}) => {
  const { changeState } = useContext(TabContext)
  const { height, onLayout } = useLayout()	//@react-native-community/hooks

  useEffect(() => {
    changeState(tabLabel, height)
  }, [height])

  return (
    <View
      style={[{ backgroundColor: '#fff' }, style]}
      onLayout={onLayout}
    >
      {children}
    </View>
  )
}
const Main = () => {
  const renderActivity = () => {}
  const renderTools = () => {}
  const renderUser = () => {}
  return (
	<TabProvider>
	  <TabItem tabLabel={'Activity'}>
		{renderActivity()}
	  </TabItem>
	  <TabItem tabLabel={'Tools'}>
		{renderTools()}
	  </TabItem>
	  <TabItem tabLabel={'User'}>
		{renderUser()}
	  </TabItem>
	</TabProvider>
  )
}

I solved it this way A single component is packaged to control all of this, and it is non-intrusive and very simple to the outside

FuzzyFade avatar Apr 07 '20 16:04 FuzzyFade

This is how I am using for auto-height issue inside <ScrollView>

onTabIndexChange = (params) => {
    this.setState({
        index: params.i
    });
};

<ScrollView style={{flex: 1}}>

    ...

    <View style={{flex: 1}}>
        <ScrollableTabView onChangeTab={this.onTabIndexChange}>
            <View tabLabel="First Tab" />
            <View tabLabel="Second Tab" />
            <View tabLabel="Third Tab" />
        </ScrollableTabView>
        {0 === this.state.index ? this.firstTab() : null}
        {1 === this.state.index ? this.secondTab() : null}
        {2 === this.state.index ? this.thirdTab() : null}
    </View>
</ScrollView>

azhararmar avatar Aug 04 '20 02:08 azhararmar

This is how I am using for auto-height issue inside <ScrollView>

onTabIndexChange = (params) => {
    this.setState({
        index: params.i
    });
};

<ScrollView style={{flex: 1}}>

    ...

    <View style={{flex: 1}}>
        <ScrollableTabView onChangeTab={this.onTabIndexChange}>
            <View tabLabel="First Tab" />
            <View tabLabel="Second Tab" />
            <View tabLabel="Third Tab" />
        </ScrollableTabView>
        {0 === this.state.index ? this.firstTab() : null}
        {1 === this.state.index ? this.secondTab() : null}
        {2 === this.state.index ? this.thirdTab() : null}
    </View>
</ScrollView>

but you cant scroll horizontal

hejun041 avatar Oct 15 '20 07:10 hejun041

I need a solution for this, isn't there a solution?

picknamexd avatar Nov 22 '20 18:11 picknamexd

any solution

fixurshitreactnative avatar Feb 23 '21 21:02 fixurshitreactnative