React-Native-ViewPager
React-Native-ViewPager copied to clipboard
DOES NOT WORK IN SCROLLVIEW
Hi, thanks for the library. It was pretty cool before I found out that viewpager does not work in scroll view in ios. Would you please help me out? :)
This does not work (no content is displayed)
<ScrollView style={{ flex: 1 }}>
<IndicatorViewPager
pagerStyle={style.viewPager}
style={style.container}
initialPage={activeTab === 'products' ? 0 : 1}
indicator={
<PagerTitleIndicator
itemTextStyle={style.pagerTitleText}
selectedItemTextStyle={style.pagerSelectedText}
selectedBorderStyle={style.pagerSelectedBorder}
style={style.pager}
titles={['Products', 'Brands']}
/>}
>
<View>
<ItemsList navigator={navigator} items={topProducts} type="product" />
</View>
<View>
<ItemsList navigator={navigator} items={topBrands} type="brand" />
</View>
</IndicatorViewPager>
</ScrollView>
This works as expected:
<View style={{ flex: 1 }}>
<IndicatorViewPager
pagerStyle={style.viewPager}
style={style.container}
initialPage={activeTab === 'products' ? 0 : 1}
indicator={
<PagerTitleIndicator
itemTextStyle={style.pagerTitleText}
selectedItemTextStyle={style.pagerSelectedText}
selectedBorderStyle={style.pagerSelectedBorder}
style={style.pager}
titles={['Products', 'Brands']}
/>}
>
<View>
<ItemsList navigator={navigator} items={topProducts} type="product" />
</View>
<View>
<ItemsList navigator={navigator} items={topBrands} type="brand" />
</View>
</IndicatorViewPager>
</View>
Could you paste your viewpager style code here ?
const style = StyleSheet.create({
container: {
flex: 1,
},
pagerTitleText: {
color: 'darkgray',
},
pagerSelectedText: {
color: 'black',
},
pagerSelectedBorder: {
backgroundColor: 'black',
},
pager: {
backgroundColor: AppStyles.windowBackground,
height: 50,
position: 'absolute',
top: 0,
left: 0,
right: 0,
},
pagerBackground: {
backgroundColor: 'white',
},
viewPager: {
marginTop: 50,
},
})
You should specify the height and width in the style sheet of viewpager.
Cool but how do I do that?
I mean what if I don't know the size of the content in advance?
Or maybe you can set flex:1 in the style sheet of viewpager. Refer this
Flex does not work.
Even worse is that in order to render the content the view pager NEEDS some height. When I set some initial height manually then it renders its content and only then are onLayout methods executed in the content of the viewer. So I can set the actual height of the viewpager. I don't know what am I gonna do but I am fucked up a lot because of this.
Maybe you can set some initial height, and when the content view's onLayout methods called back, then you change the height of viewpager by setState. Anyway you must think out a way to calc the height of your content.
I have already done that. I created TabContent component that adds layout height to the total height of the tab but it is not good solution. I have to set initial height in order to set the actual height. Initial height must be bigger that the first element that is supposed to be rendered in the tab. I have to do shitload of unnecessary calculations. For some reason when I made it work ... it worked until I clicked on 2nd+ tab then the component is rerendering indefinitely.
ViewPager:
<IndicatorViewPager
ref={viewPager => {
this.viewPager = viewPager
}}
pagerStyle={styles.viewPager}
style={styles.container}
initialPage={0}
onPageSelected={eve => {
this.handleChangeTabIndex(eve.position)
}}
indicator={<PagerTitleIndicator
itemTextStyle={styles.pagerTitleText}
selectedItemTextStyle={styles.pagerSelectedText}
selectedBorderStyle={styles.pagerSelectedBorder}
style={styles.pager}
onClick={this.handleChangeTabIndex}
titles={['Information', 'Activity']}
/>}
>
<View style={{ flex: 1, padding: 20 }}>
{productCategory && productCategory.count() > 0 && (
<TabContent name="category" addHeight={(key, height) => this.handleAddTabContent('first_tab', key, height)}>
<ProductDetailInformation
title="Category"
value={productCategory.get('name')}
/>
</TabContent>
)}
<TabContent name="description" addHeight={(key, height) => this.handleAddTabContent('first_tab', key, height)}>
<ProductDetailInformation
title={'Product detail'}
value={product.get('description')}
/>
</TabContent>
</View>
<View style={{ paddingTop: 20 }}>
<TabContent name="second_tab_first_content" addHeight={(key, height) => this.handleAddTabContent('second_tab', key, height)}>
<Text>Second tab content</Text>
</TabContent>
</View>
</IndicatorViewPager>
Component methods:
handleAddTabContent(tabName, key, height) {
const tabsContent = this.state.tabsContent
tabsContent[tabName][key] = height
this.setState({ tabsContent })
}
getTabContentHeight() {
const { tab, tabsContent } = this.state
let activityTabHeight = 0
let detailTabHeight = 0
Object.keys(tabsContent.activity).forEach(key => {
activityTabHeight += tabsContent.activity[key]
})
Object.keys(tabsContent.detail).forEach(key => {
detailTabHeight += tabsContent.detail[key]
})
if (!activityTabHeight || !detailTabHeight) {
return windowHeight
}
if (detailTabHeight < windowHeight) {
detailTabHeight = windowHeight
}
if (activityTabHeight < windowHeight) {
activityTabHeight = windowHeight
}
switch (tab) {
case 0:
return detailTabHeight
case 1:
return activityTabHeight
default:
return 0
}
}
Tab content component
import React from 'react'
import PropTypes from 'prop-types'
import {
View,
} from 'react-native'
const TabContent = ({ children, name, addHeight }) => (
<View
onLayout={
event => {
const layout = event.nativeEvent.layout
addHeight(name, layout.height)
}
}
>
{children}
</View>
)
TabContent.propTypes = {
children: PropTypes.node,
name: PropTypes.string,
addHeight: PropTypes.func,
}
export default TabContent
I am basically fucked.
@developer239 Is there any other way?