I am trying to show a media player above the bottom tab navigator just like in spotify app. It should stay there in same state across all the screens (bottom tabs).
Any suggestions or approaches to implement this in React native ?
CodePudding user response:
You just need to calculate the height of Bottom Navbar and make a View with Position:'absolute' and to keep it above Bottom Navbar assign the height of Navbar to 'bottom' of this View.
<View>
<View
style={{
position: "absolute",
backgroundColor: "#4470AE",
bottom: 75,
flexDirection: "row",
width: "90%",
height: 60,
paddingVertical: "3%",
alignSelf: "center",
borderRadius: 12,
margin: "3%",
}}
></View>
<View
style={{
position: "absolute",
backgroundColor: "orange",
bottom: 0,
height: 75,
flexDirection: "row",
width: "100%",
justifyContent: "space-around",
paddingVertical: "3%",
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
}}
>
</View>
</View>
CodePudding user response:
I would suggest to use an React.Context as you wanna show the same object (music control panel) on each screen with same state and not an replica on each screen.
For positioning I suggest using an absolute
position. This works together with "react-navigation" because header and bottom areas are changed.
This means bottom:0
is no longer the screens bottom within a tab navigator it's right above the TabBar.
Here is an example:
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { MusicControlPanelContext, MusicControlPanelConsumer } from './components/MusicControlContext';
import {MusicControlPanel} from './components/MusicContorlPanel'
function HomeScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
<MusicControlPanelConsumer/>
</View>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
<MusicControlPanelConsumer/>
</View>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<MusicControlPanelContext.Provider value={MusicControlPanel}>
<>
<NavigationContainer>
<Tab.Navigator
tabBarOptions={{
activeTintColor: '#000000',
inactiveTintColor: 'gray',
activeBackgroundColor: '#ff0000',
inactiveBackgroundColor: '#ff0000',
style: {
backgroundColor: '#ffffff',
},
}}>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
</>
</MusicControlPanelContext.Provider>
);
}
import * as React from 'react';
import { MusicControlPanelContext } from './MusicControlPanelContext';
import { View } from 'react-native';
function MusicControlPanelConsumer() {
return (
<MusicControlPanelContext.Consumer>
{(Component) => <Component/>}
</MusicControlPanelContext.Consumer>
);
}
export { MusicControlPanelConsumer };
import * as React from 'react';
import {MusicControlPanel} from '../MusicContorlPanel'
export const MusicControlPanelContext = React.createContext<React.FC>(MusicControlPanel);
import * as React from 'react';
import { View, Text, Pressable } from 'react-native';
export const MusicControlPanel: React.FC = () => {
const [startStop, setStartStop] = React.useState(false);
return (
<View
style={{
position: 'absolute',
width: '90%',
height: 100,
backgroundColor: '#ff00ff',
bottom: 10,
justifyContent: 'center',
alignItems: 'center'
}}>
<Pressable
onPress={() =>
setStartStop((val) => {
return !val;
})
}>
<Text>{startStop ? 'Start' : 'Stop'}</Text>
</Pressable>
</View>
);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>