Hi all , Facing issue in tab bar,
When Tabview is inside scrollview, getting empty views if height differs in children scenes , I mean Tabs
import React, { Component } from 'react';
import {
Animated,
Platform,
StatusBar,
StyleSheet,
Text,
View,
ScrollView
} from 'react-native';
import { TabViewAnimated, TabBar,TabViewPagerScroll, TabViewPagerPan } from 'react-native-tab-view';
const HEADER_MAX_HEIGHT = 300;
const HEADER_MIN_HEIGHT = Platform.OS === 'ios' ? 0 : 0;
const HEADER_SCROLL_DISTANCE = HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT;
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
scrollY: new Animated.Value(0),
ydis:0,
index: 0,
routes: [
{ key: '1', title: 'First' },
{ key: '2', title: 'Second' },
],
};
this.onScroll=this.onScroll.bind(this);
}
_main: Object;
onScroll(e){
var yDist=e.nativeEvent.contentOffset.y;
console.log('====================================');
console.log(yDist);
console.log('====================================');
const direction = (yDist > 0 && yDist > this.state.ydis)
? 'down'
: 'up'
if(direction=='down'){
if(yDist>=this.state.ydis){
if(yDist>=0 && yDist<=HEADER_MAX_HEIGHT){
var yScroll= new Animated.Value(yDist);
this.setState({scrollY:yScroll});
}else{
var yScroll= new Animated.Value(HEADER_MAX_HEIGHT);
this.setState({scrollY:yScroll});
}
}
}else{
if(yDist>=40 ){
var yScroll= new Animated.Value(yDist);
this.setState({scrollY:yScroll});
}else{
var yScroll= new Animated.Value(0);
this.setState({scrollY:yScroll});
}
}
this.setState({ydis:yDist});
}
_renderPager = (props) => {
return (Platform.OS === 'ios') ? <TabViewPagerScroll {...props} /> : <TabViewPagerPan {...props} />
}
render() {
const headerTranslate = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [0, -HEADER_SCROLL_DISTANCE],
extrapolate: 'clamp',
});
const imageOpacity = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE / 2, HEADER_SCROLL_DISTANCE],
outputRange: [1, 1, 0],
extrapolate: 'clamp',
});
const imageTranslate = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [0, 100],
extrapolate: 'clamp',
});
return (
<View style={[styles.fill]}>
<Animated.ScrollView
scrollEventThrottle={1}
style={{}}
ref={el => (this._main = el)}
automaticallyAdjustContentInsets={true}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }],
{ useNativeDriver: true },
)}
>
<TabViewAnimated
style={[styles.container,{marginTop:HEADER_MAX_HEIGHT}]}
navigationState={this.state}
renderScene={this._renderScene}
renderHeader={this._renderHeader}
onRequestChangeTab={this._handleChangeTab}
renderPager={this._renderPager}
/>
</Animated.ScrollView>
<Animated.View
style={[
styles.header,
{ transform: [{ translateY: headerTranslate }] },
]}
>
<Animated.Image
style={[
styles.backgroundImage,
{
opacity: imageOpacity,
transform: [{ translateY: imageTranslate }],
},
]}
source={{uri: 'https://az616578.vo.msecnd.net/files/responsive/cover/main/desktop/2016/09/12/636092494089079016-677881086_art.jpg'}}
/>
</Animated.View>
</View>
);
}
_first: Object;
_second: Object;
_handleChangeTab = (index) => {
this._main._component.scrollTo({ y: 0 });
this.setState({ index });
};
_handleTabItemPress = ({ route }) => {
if (route !== this.state.routes[this.state.index]) {
return;
}
switch (route.key) {
case '1':
if (this._first) {
this._first.scrollTo({ y: 0 });
this._main._component.scrollTo({ y: 0 });
}
break;
case '2':
if (this._second) {
this._second.scrollTo({ y: 0 });
this._main._component.scrollTo({ y: 0 });
}
break;
}
};
_renderHeader = (props) => {
return <TabBar {...props}
onTabPress={this._handleTabItemPress}/>;
};
_renderScene = ({ route }) => {
switch (route.key) {
case '1':
return( <ScrollView
ref={el => (this._first = el)}
>
<View style={[ styles.page, { backgroundColor: '#ff4081' } ]} />
</ScrollView>);
case '2':
return(<ScrollView
ref={el => (this._second = el)}
>
<View style= { {backgroundColor: 'teal' , height:20, } } />
</ScrollView>);
default:
return null;
}
};
}
const styles = StyleSheet.create({
fill: {
flex: 1,
},
content: {
flex: 1,
},
container: {
flex:1,
},
page: {
height:2000,
alignItems: 'center',
},
header: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: 'transparent',
overflow: 'hidden',
height: HEADER_MAX_HEIGHT,
},
backgroundImage: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
width: null,
height: HEADER_MAX_HEIGHT,
resizeMode: 'cover',
},
bar: {
backgroundColor: 'transparent',
marginTop: Platform.OS === 'ios' ? 28 : 38,
height: 32,
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
top: 0,
left: 0,
right: 0,
},
title: {
color: 'white',
fontSize: 18,
},
scrollViewContent: {
marginTop: HEADER_MAX_HEIGHT,
},
row: {
height: 40,
margin: 16,
backgroundColor: '#D3D3D3',
alignItems: 'center',
justifyContent: 'center',
},
});
Above is the source code
Hi. just add height:1000 in the style.fill or Animated.ScrollView add height
Hi @Juxtlie , no effect , problem persists
solved the isuue,
Find the answer in below comments
Closing since the issue is resolved.
@ashrithks can u share your solution
@ashrithks
There's one thing worse: a single followup reading just
Never mind, I figured it out.
This isn't an issue affecting me personally, but if you solve an issue you've requested help from the community on, please do post your solution.
Hi Folks,
Sorry for the late reply...
import React, { Component } from 'react';
import {
Animated,
Platform,
StatusBar,
StyleSheet,
Text,
View,
ScrollView,
Dimensions
} from 'react-native';
import { TabViewAnimated, TabBar, TabViewPagerScroll, TabViewPagerPan } from 'react-native-tab-view';
const HEADER_MAX_HEIGHT = 300;
const HEADER_MIN_HEIGHT = Platform.OS === 'ios' ? 0 : 0;
const HEADER_SCROLL_DISTANCE = HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT;
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
scrollY: new Animated.Value(0),
ydis: 0,
index: 0,
routes: [
{ key: '1', title: 'First' },
{ key: '2', title: 'Second' },
],
headerHeight: 0,
tab1Height: 0,
tab2Height: 0
};
this.onScroll = this.onScroll.bind(this);
}
_main: Object;
onScroll(e) {
var yDist = e.nativeEvent.contentOffset.y;
console.log('====================================');
console.log(yDist);
console.log('====================================');
const direction = (yDist > 0 && yDist > this.state.ydis)
? 'down'
: 'up'
if (direction == 'down') {
if (yDist >= this.state.ydis) {
if (yDist >= 0 && yDist <= HEADER_MAX_HEIGHT) {
var yScroll = new Animated.Value(yDist);
this.setState({ scrollY: yScroll });
} else {
var yScroll = new Animated.Value(HEADER_MAX_HEIGHT);
this.setState({ scrollY: yScroll });
}
}
} else {
if (yDist >= 40) {
var yScroll = new Animated.Value(yDist);
this.setState({ scrollY: yScroll });
} else {
var yScroll = new Animated.Value(0);
this.setState({ scrollY: yScroll });
}
}
this.setState({ ydis: yDist });
}
_renderPager = (props) => {
return (Platform.OS === 'ios') ? <TabViewPagerScroll {...props} /> : <TabViewPagerPan {...props} />
}
onLayout(e) {
const { nativeEvent: { layout: { height } } } = e;
const hed = height + 50;
this.setState({ headerHeight: hed })
}
render() {
const headerTranslate = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [0, -HEADER_SCROLL_DISTANCE],
extrapolate: 'clamp',
});
const imageOpacity = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE / 2, HEADER_SCROLL_DISTANCE],
outputRange: [1, 1, 0],
extrapolate: 'clamp',
});
const imageTranslate = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [0, 100],
extrapolate: 'clamp',
});
let scrollHeight = 0;
if (this.state.index === 0) {
scrollHeight = this.state.headerHeight + 20;
} else {
scrollHeight = this.state.headerHeight + 2000;
}
return (
<View style={[styles.fill]}>
<Animated.View
style={[
styles.header,
{ transform: [{ translateY: headerTranslate }] },
]}
onLayout={this.onLayout.bind(this)}
>
<Animated.Image
style={[
styles.backgroundImage,
{
opacity: imageOpacity,
transform: [{ translateY: imageTranslate }],
},
]}
source={{ uri: 'https://az616578.vo.msecnd.net/files/responsive/cover/main/desktop/2016/09/12/636092494089079016-677881086_art.jpg' }}
/>
</Animated.View>
<Animated.ScrollView
scrollEventThrottle={1}
style={{
}}
contentContainerStyle={{ height: scrollHeight }}
ref={el => (this._main = el)}
automaticallyAdjustContentInsets={true}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }],
{ useNativeDriver: true },
)}
>
<TabViewAnimated
style={[styles.container, { marginTop: HEADER_MAX_HEIGHT }]}
navigationState={this.state}
renderScene={this._renderScene}
renderHeader={this._renderHeader}
onIndexChange={this._handleChangeTab}
renderPager={this._renderPager}
/>
</Animated.ScrollView>
</View >
);
}
_first: Object;
_second: Object;
_handleChangeTab = (index) => {
this._main._component.scrollTo({ y: 0 });
this.setState({ index });
};
_handleTabItemPress = ({ route }) => {
if (route !== this.state.routes[this.state.index]) {
return;
}
switch (route.key) {
case '1':
if (this._first) {
this._first.scrollTo({ y: 0 });
this._main._component.scrollTo({ y: 0 });
}
break;
case '2':
if (this._second) {
this._second.scrollTo({ y: 0 });
this._main._component.scrollTo({ y: 0 });
}
break;
}
};
_renderHeader = (props) => {
return <TabBar {...props}
onTabPress={this._handleTabItemPress} />;
};
_renderScene = ({ route }) => {
switch (route.key) {
case '1':
return (<ScrollView
ref={el => (this._first = el)}
>
<View style={[styles.page, { backgroundColor: '#ff4081' }]} />
</ScrollView>);
case '2':
return (<ScrollView
ref={el => (this._second = el)}
>
<View style={{ backgroundColor: 'teal', height: 2000, }} />
</ScrollView>);
default:
return null;
}
};
}
const styles = StyleSheet.create({
fill: {
flex: 1,
},
content: {
flex: 1,
},
container: {
flex: 1,
},
page: {
height: 20,
alignItems: 'center',
},
header: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: 'transparent',
overflow: 'hidden',
height: HEADER_MAX_HEIGHT,
},
backgroundImage: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
width: null,
height: HEADER_MAX_HEIGHT,
resizeMode: 'cover',
},
bar: {
backgroundColor: 'transparent',
marginTop: Platform.OS === 'ios' ? 28 : 38,
height: 32,
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
top: 0,
left: 0,
right: 0,
},
title: {
color: 'white',
fontSize: 18,
},
scrollViewContent: {
marginTop: HEADER_MAX_HEIGHT,
},
row: {
height: 40,
margin: 16,
backgroundColor: '#D3D3D3',
alignItems: 'center',
justifyContent: 'center',
},
});
@melihberberolu , @Oblongmana ...
I calculate the height of header and + 50 is tabheader height,,,
then added a prop to scrollview...
contentContainerStyle={{ height: scrollHeight }}
i change the scrollheight based on tabs
if (this.state.index === 0) {
scrollHeight = this.state.headerHeight + 20;
} else {
scrollHeight = this.state.headerHeight + 2000;
}
i hard coded the tab heights,
U can use onlayout Function to get the dynamic height of tabs
@Oblongmana ,
Contributors closed this issue, with out asking the solution.
so ,,i didnt revisit this issue till yesterday when i saw mails regarding this.
Sorry for the late reply
For dynamic tab height example
import React, { Component } from 'react';
import {
Animated,
Platform,
StatusBar,
StyleSheet,
Text,
View,
ScrollView,
Dimensions
} from 'react-native';
import { TabViewAnimated, TabBar, TabViewPagerScroll, TabViewPagerPan } from 'react-native-tab-view';
const HEADER_MAX_HEIGHT = 300;
const HEADER_MIN_HEIGHT = Platform.OS === 'ios' ? 0 : 0;
const HEADER_SCROLL_DISTANCE = HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT;
const deviceHeight = Dimensions.get('window').height;
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
scrollY: new Animated.Value(0),
ydis: 0,
index: 0,
routes: [
{ key: '1', title: 'First' },
{ key: '2', title: 'Second' },
],
headerHeight: 0,
tab1Height: 0,
tab2Height: 0
};
this.onScroll = this.onScroll.bind(this);
}
_main: Object;
onScroll(e) {
var yDist = e.nativeEvent.contentOffset.y;
console.log('====================================');
console.log(yDist);
console.log('====================================');
const direction = (yDist > 0 && yDist > this.state.ydis)
? 'down'
: 'up'
if (direction == 'down') {
if (yDist >= this.state.ydis) {
if (yDist >= 0 && yDist <= HEADER_MAX_HEIGHT) {
var yScroll = new Animated.Value(yDist);
this.setState({ scrollY: yScroll });
} else {
var yScroll = new Animated.Value(HEADER_MAX_HEIGHT);
this.setState({ scrollY: yScroll });
}
}
} else {
if (yDist >= 40) {
var yScroll = new Animated.Value(yDist);
this.setState({ scrollY: yScroll });
} else {
var yScroll = new Animated.Value(0);
this.setState({ scrollY: yScroll });
}
}
this.setState({ ydis: yDist });
}
_renderPager = (props) => {
return (Platform.OS === 'ios') ? <TabViewPagerScroll {...props} /> : <TabViewPagerPan {...props} />
}
onLayout(e) {
const { nativeEvent: { layout: { height } } } = e;
const hed = height + 50;
this.setState({ headerHeight: hed })
}
onLayoutTab1(e) {
const { nativeEvent: { layout: { height } } } = e;
this.setState({ tab1Height: height })
}
onLayoutTab2(e) {
const { nativeEvent: { layout: { height } } } = e;
this.setState({ tab2Height: height })
}
render() {
const headerTranslate = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [0, -HEADER_SCROLL_DISTANCE],
extrapolate: 'clamp',
});
const imageOpacity = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE / 2, HEADER_SCROLL_DISTANCE],
outputRange: [1, 1, 0],
extrapolate: 'clamp',
});
const imageTranslate = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [0, 100],
extrapolate: 'clamp',
});
let scrollHeight = deviceHeight;
if (this.state.index === 0) {
if (this.state.tab1Height > (deviceHeight - this.state.headerHeight)) {
scrollHeight = this.state.headerHeight + this.state.tab1Height;
}
} else {
if (this.state.tab2Height > (deviceHeight - this.state.headerHeight)) {
scrollHeight = this.state.headerHeight + this.state.tab2Height;
}
}
return (
<View style={[styles.fill]}>
<Animated.View
style={[
styles.header,
{ transform: [{ translateY: headerTranslate }] },
]}
onLayout={this.onLayout.bind(this)}
>
<Animated.Image
style={[
styles.backgroundImage,
{
opacity: imageOpacity,
transform: [{ translateY: imageTranslate }],
},
]}
source={{ uri: 'https://az616578.vo.msecnd.net/files/responsive/cover/main/desktop/2016/09/12/636092494089079016-677881086_art.jpg' }}
/>
</Animated.View>
<Animated.ScrollView
scrollEventThrottle={1}
style={{
}}
contentContainerStyle={{ height: scrollHeight }}
ref={el => (this._main = el)}
automaticallyAdjustContentInsets={true}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }],
{ useNativeDriver: true },
)}
>
<TabViewAnimated
style={[styles.container, { marginTop: HEADER_MAX_HEIGHT }]}
navigationState={this.state}
renderScene={this._renderScene}
renderHeader={this._renderHeader}
onIndexChange={this._handleChangeTab}
renderPager={this._renderPager}
/>
</Animated.ScrollView>
</View >
);
}
_first: Object;
_second: Object;
_handleChangeTab = (index) => {
this._main._component.scrollTo({ y: 0 });
this.setState({ index });
};
_handleTabItemPress = ({ route }) => {
if (route !== this.state.routes[this.state.index]) {
return;
}
switch (route.key) {
case '1':
if (this._first) {
this._first.scrollTo({ y: 0 });
this._main._component.scrollTo({ y: 0 });
}
break;
case '2':
if (this._second) {
this._second.scrollTo({ y: 0 });
this._main._component.scrollTo({ y: 0 });
}
break;
}
};
_renderHeader = (props) => {
return <TabBar {...props}
onTabPress={this._handleTabItemPress} />;
};
_renderScene = ({ route }) => {
switch (route.key) {
case '1':
return (<ScrollView
ref={el => (this._first = el)}
>
<View
onLayout={this.onLayoutTab1.bind(this)}
style={[styles.page, { backgroundColor: '#ff4081' }]} />
</ScrollView>);
case '2':
return (<ScrollView
ref={el => (this._second = el)}
>
<View
onLayout={this.onLayoutTab2.bind(this)}
style={{ backgroundColor: 'teal', height: 2000, }} />
</ScrollView>);
default:
return null;
}
};
}
const styles = StyleSheet.create({
fill: {
flex: 1,
},
content: {
flex: 1,
},
container: {
flex: 1,
},
page: {
height: 20,
alignItems: 'center',
},
header: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: 'transparent',
overflow: 'hidden',
height: HEADER_MAX_HEIGHT,
},
backgroundImage: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
width: null,
height: HEADER_MAX_HEIGHT,
resizeMode: 'cover',
},
bar: {
backgroundColor: 'transparent',
marginTop: Platform.OS === 'ios' ? 28 : 38,
height: 32,
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
top: 0,
left: 0,
right: 0,
},
title: {
color: 'white',
fontSize: 18,
},
scrollViewContent: {
marginTop: HEADER_MAX_HEIGHT,
},
row: {
height: 40,
margin: 16,
backgroundColor: '#D3D3D3',
alignItems: 'center',
justifyContent: 'center',
},
});
Expo link for the same ,,
https://snack.expo.io/HyHCMrQvZ
Most helpful comment
Expo link for the same ,,
https://snack.expo.io/HyHCMrQvZ