React Native How to show an element above bottom tab navigator - react-native

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 ?

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>

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>

I just solved this problem
import BottomTabBar
call tabBar props in tab navigator
wrap it with empty tag
import and insert your component above the BottomTabBar
import { BottomTabBar} from '#react-navigation/bottom-tabs';
import SmallVideoPlay from 'YOUR_PATH_OF_THE_COMPONENT';
<Tab.Navigator
tabBar={(props) => (
<>
< SmallVideoPlay />
<BottomTabBar {...props} />
</>
)}
>
<Tab.Screen name="HomeStack" component={Home}/>
....
</Tab.Navigator/>

Related

How To Add Logout Button in React native Drawer.Navigator?

I am creating Drawer in react native using Drawer.Navigator. But the issue is that how to move to Login screen if click on Logout button?
Any suggestion? my code is below. All remaining code is working fine. I only want to navigate the login screen by clicking on logout button.
import * as React from 'react';
import { Button, View, Text, TouchableOpacity } from 'react-native';
import {
createDrawerNavigator, DrawerContentScrollView,
DrawerItemList,
DrawerItem,
} from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import Resources from '../DrawerScreens/Resources';
import Themes from '../DrawerScreens/Themes';
import AboutUs from '../DrawerScreens/AboutUs';
import CustomSidebarMenu from './CustomSidebarMenu';
import Login from '../Validation/Login';
const Drawer = createDrawerNavigator();
export default function DrawerSetting({ navigation }) {
return (
<NavigationContainer independent={true} >
<Drawer.Navigator initialRouteName="Resources" drawerContent={(props) => <CustomSidebarMenu {...props} />}
>
<Drawer.Screen name="Resources" component={Resources}
options={{ drawerLabelStyle: { fontSize: 16, color: 'black', } }}
/>
<Drawer.Screen name="Themes" component={Themes}
options={{ drawerLabelStyle: { fontSize: 16, color: 'black', } }}
/>
<Drawer.Screen name="About Us" component={AboutUs}
options={{ drawerLabelStyle: { fontSize: 16, color: 'black', } }}
/>
</Drawer.Navigator>
</NavigationContainer>
);
}
I used to create Another component for creating the logout button,
import React from 'react';
import {
SafeAreaView,
View,
StyleSheet,
Image,
Text,
Linking,
TouchableOpacity,
BackHandler
} from 'react-native';
import {
DrawerContentScrollView,
DrawerItemList,
DrawerItem, Drawer,
} from '#react-navigation/drawer';
const CustomSidebarMenu = (props) => {
const BASE_PATH = '';
function logout(){
alert("Hello");
// props.navigation.navigate("Login");
// BackHandler.exitApp();
}
return (
<SafeAreaView style={{ flex: 1 }}>
{/*Top Large Image */}
<Image
source={require("../../assets/images/g_logo_blue.png")}
style={styles.sideMenuProfileIcon}
/>
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
{/* { <DrawerItem
label="Visit Us"
onPress={() => {props.navigation.navigate('Login')}}
/> } */}
{/* <View style={styles.customItem}>
<Text
onPress={() => {
Linking.openURL('https://aboutreact.com/');
}}>
Rate Us
</Text>
<Image
source={{ uri: BASE_PATH + 'star_filled.png' }}
style={styles.iconStyle}
/>
</View> */}
<TouchableOpacity onPress={logout}>
<Text style={{ fontSize: 16, fontWeight: 'bold', textAlign: 'left', color: 'blue', marginLeft: 20, }}>
Logout
</Text>
</TouchableOpacity>
</DrawerContentScrollView>
<Text style={{ fontSize: 16, textAlign: 'center', color: 'blue' }}>
https://www.glocoach.com/
</Text>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
sideMenuProfileIcon: {
// resizeMode: 'cover',
width: "70%",
height: 70,
marginTop: 20,
marginBottom: -40,
marginLeft: -50,
// borderRadius: 100 / 2,
alignSelf: 'center',
},
iconStyle: {
width: 15,
height: 15,
marginHorizontal: 5,
},
customItem: {
padding: 16,
flexDirection: 'row',
alignItems: 'center',
},
});
export default CustomSidebarMenu;
Normally what I would do in this situation is have two navigators. One for the logged-out screens and one for the logged-in screens. Then I would bind this to a check-in JSX like:
<NavigationContainer>
{!isLoggedIn ? (<LoggedOutNavigator />) : (<LoggedInNavigator />)}
</NavigationContainer>
After that, all you have to do when the button is pressed is to change the isLoggedIn value. you can save isloggedIn in redux and then just dispatch an action to handle the change.
if you only have one navigator and really don't want to change it, then you can add a useEffect hook to navigate to the log in screen once isLoggedIn is set to false.

how to make background blur when modal open ups in reactnative

import React from 'react'
import { View, StyleSheet, Text, TouchableOpacity, Modal } from 'react-native'
const ModalContent = ({ visiblity, toggleModal }) => {
return (
<Modal animationType='slide' transparent={true} visible={visiblity} onRequestClose={() => {
toggleModal()
}} >
<View style={styles.container}>
<TouchableOpacity>
<Text style={styles.textButton}>Edit</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.textButton}>Invite</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.textButton}>Delete</Text>
</TouchableOpacity>
</View>
</Modal>
)
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
borderTopRightRadius: 25,
borderTopLeftRadius: 25,
height: 150,
alignItems: 'center',
elevation: 10,
alignItems: 'flex-start',
justifyContent: 'space-around',
paddingLeft: 20,
marginTop: 420
},
textButton: {
fontSize: 13,
color: 'black',
}
})
export default ModalContent
<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>
import React from 'react'
import { View, StyleSheet, Text, TouchableOpacity, Modal } from 'react-native'
const ModalContent = ({ visiblity, toggleModal }) => {
return (
<Modal animationType='slide' transparent={true} visible={visiblity} onRequestClose={() => {
toggleModal()
}} >
<View style={styles.container}>
<TouchableOpacity>
<Text style={styles.textButton}>Edit</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.textButton}>Invite</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.textButton}>Delete</Text>
</TouchableOpacity>
</View>
</Modal>
)
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
borderTopRightRadius: 25,
borderTopLeftRadius: 25,
height: 150,
alignItems: 'center',
elevation: 10,
alignItems: 'flex-start',
justifyContent: 'space-around',
paddingLeft: 20,
marginTop: 420
},
textButton: {
fontSize: 13,
color: 'black',
}
})
export default ModalContent
just simply adding backgroundcolor with opacity>>>>
backgroundColor: rgba(255, 0, 0, 0.2);
because in modal there is view contains view so if you give background color to that conatining view it will added blacky effect
In case you are using expo use
import { BlurView } from 'expo-blur';
When I added a blurView to my project, I browsed around for some third party libs and ended up with adding react-native-unimodules.
https://www.npmjs.com/package/#react-native-community/blur
you can use blurview so you can trigger blur when the bottomsheet opens or else make it normal
.
.
.
.
const [opensheet,setopensheet]=useState(false)
const [blur,setblur]=useState(0)
const ViewRef=useRef()
useEffect(
()=>
{
const changeBlur=()=>
{
if(opensheet)
setblur(25)
else
setblur(0)
}
changeBlur()
},
[opensheet]
)
.
.
.
return
(
<BlurView
ref={ViewRef}
blurAmount={blur}
>
.
.
.
)
--here opensheet is state of your modal which is defined by bool open/true and close/false
you have multiple way to solve this
one is using this library
https://github.com/Kureev/react-native-blur
one is with image with opacity blurradius
<Image
style={{opacity:0.8}
resizeMode='cover'
source={path}
blurRadius={1}
/>
another approach would to drop shadow with transparent background
i would go with first option becuase i already tried it

How to fix react navigation displacing my component from top of screen?

I am working on a react native application and am trying to understand how to deal with react navigation as it affects my styling. Essentially when I navigate to a page, react navigation's top arrow with header is displacing my components (I'd like to move my black header bar up and use react navigation's arrow ideally):
I have react navigation set up in the following manner:
App.js
const ProfileNavigator = createStackNavigator({
//Profile: { screen: Profile},
QR: { screen: GenerateQR },
EditAccount: { screen: EditAccount }
});
const AppNavigator = createSwitchNavigator({
tabs: bottomTabNavigator,
profile: ProfileNavigator
})
const AppContainer = createAppContainer(AppNavigator);
I have a header component I put together for styling that I use on top of each page:
pageTemplate
import React, {Component} from 'react';
import {Text,View, StyleSheet} from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { Ionicons } from '#expo/vector-icons';
class PageTemplate extends Component {
render() {
return (
<View
style={{
flexDirection: 'row',
height: 130,
alignSelf: 'stretch',
width: '100%'
}}>
<View style={{backgroundColor: 'black', alignSelf: 'stretch',width: '100%'}} />
<View style=
{{position:'absolute',
marginTop: '16%',
marginLeft: '3%',
display: 'flex',
flexDirection: 'row',
flex:1
}}>
<TouchableOpacity onPress={this.props.navigate}>
<Ionicons name="ios-arrow-dropleft" size={32} color="white" />
</TouchableOpacity>
</View>
<Text
style={{
position: 'absolute',
marginTop: '15%',
marginLeft: '12%',
color: 'white',
fontSize: 30}}
>
{this.props.title}
</Text>
</View>
);
}
}
export default PageTemplate;
I have a tab called profile which navigates through a list item to get to an account edits page:
Profile
import React from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, TouchableHighlight } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import { List, ListItem } from 'react-native-elements'
import GenerateQR from './generateQR';
import PageTemplate from './smallComponents/pageTemplate';
import pic from '../assets/bigRate.png'
export default class Profile extends React.Component {
render() {
const { navigate } = this.props.navigation;
navigateBack=()=>{
navigate('Queue')
}
return(
<React.Fragment>
<PageTemplate title={'Profile Settings'} navigate={navigateBack} />
{/*<Image source={pic} />*/}
{/** Frst Section */}
<View style={{
//backgroundColor:'blue'
}}>
<Text style={styles.section}>Account Information</Text>
</View>
<TouchableOpacity
onPress={()=>{navigate('EditAccount')}}
style={{position: 'absolute',
marginTop:'32%',
flex:1,
flexDirection: 'row',
flexWrap: 'wrap'}}>
<View style={{
marginLeft:'5%',
flex:1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'flex-start',
//backgroundColor:'yellow',
alignItems: 'center',
//borderRadius:50,
//height:'60%'
}} >
<Ionicons style={{marginLeft:'20%'}} name="ios-person" size={72} />
</View>
<View style={{paddingTop:50,
marginRight:'40%',
flex:2,
flexDirection: 'row',
flexWrap: 'wrap',
//backgroundColor: 'red'
}}
>
<Text>Sylvester Stallone</Text>
<Text>+1 646-897-0098</Text>
<Text>SlyLone#gmail.com</Text>
</View>
</TouchableOpacity>
{/**add line section */}
</React.Fragment>
);
}
}
const styles = StyleSheet.create({
option : {
//position: 'absolute',
marginLeft:'7%',
alignSelf: 'stretch',
width: '100%',
height: '15%',
//flexWrap: 'wrap',
justifyContent:'space-between',
//padding:20
},
section : {
fontSize:20,
marginLeft:'5%'
}
})
/**
*
*
*
<View style={styles.option}>
<Ionicons name="ios-gift" size={32} />
<TouchableHighlight>
<Text>Rewards</Text>
</TouchableHighlight>
</View>
*
*/
Ideally it be nice to drop the arrow icon and move the header up keeping react-navigations arrow.
If you want to get rid of the arrows, you can create your own headers.
Example
class LogoTitle extends React.Component {
render() {
return (
<Image
source={require('#expo/snack-static/react-native-logo.png')}
style={{ width: 30, height: 30, alignSelf:"center" }}
/>
);
}
}
class HomeScreen extends React.Component {
static navigationOptions = {
// headerTitle instead of title
headerTitle: () => <LogoTitle />,
headerLeft: () => (
<Button
onPress={() => alert('This is a button!')}
title="back"
color="#fff"
/>
),
};

React Native Modal: Transparent Background & Layout Problem

I am using the React Native Modal, I want the background of the Modal
to be transparent and I want the Modal display to behalf of the
screen
How to achieve the same requirement, where I am going wrong?
Below is the code for the same, please have a look at this:
import React, { Component } from 'react'
import { Modal, View, Text, Dimensions, Platform, TouchableOpacity, Alert, StyleSheet, Button } from 'react-native'
import Icon from 'react-native-vector-icons/Entypo'
const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;
export class MyComponent extends Component {
render = () => {
const message = 'Do you want to upload the video now or wait until you are connected to wi-fi?'
return (
<Modal
animationType='slide'
transparent={true}
style={{backgroundColor: 'black'}}
>
<View style={styles.content}>
<View style={styles.closeBtn}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('PreInspection_VideoPlayer')} style={styles.closeBtn}>
<Icon name="cross" color="#000" size={26} />
</TouchableOpacity>
</View>
<Text style={{
fontSize: 18,
fontFamily: 'Montserrat-Bold',
paddingTop: Platform.OS === 'android' ? 40 : 20,
paddingVertical: 10
}}>Warning! 🚨</Text>
<View style={{ paddingHorizontal: 40 }}>
<Text style={{ fontSize: 18, justifyContent: 'center', alignItems: 'center', textAlign: 'center' }}>{message}</Text>
</View>
<Button
title='Upload My Video'
style={styles.bigButtons}
onPress={() => { Alert.alert('Uploading Video') }}
/>
<Button
title='Upload Video Later'
style={styles.bigButtons}
onPress={() => { Alert.alert('Uploading Video Later') }}
/>
</View>
</Modal>
)
}
}
const styles = StyleSheet.create({
closeBtn: {
padding: 10
},
bigButtons: {
width: 240,
marginTop: 20
},
content: {
backgroundColor: 'red',
width: windowWidth * 0.8,
height: windowHeight * 0.7,
alignSelf: 'center',
top: windowHeight * 0.15,
borderRadius: windowHeight * 0.03,
alignItems: 'center',
justifyContent: 'center'
},
})
Any help would be appreciated. Thanks in advance :)
You can achieve this easily with React Native Community Modal
Here is an example:
import React, { useState } from "react";
import { Text, View, Dimensions } from "react-native";
import Modal from "react-native-modal";
const { width: ScreenWidth, height: ScreenHeight } = Dimensions.get("window");
const ModalExample = props => {
const [visibility, setVisibility] = useState(true);
return (
<View>
<Modal
backdropColor="transparent"
isVisible={visibility}
style={{
alignItems: "center",
justifyContent: "center"
}}
onBackdropPress={() => setVisibility(false)}
>
<View
style={{
borderRadius: 16,
alignItems: "center",
justifyContent: "center",
width: ScreenWidth * 0.7,
backgroundColor: "#fdfdfd",
height: ScreenHeight * 0.5
}}
>
<Text>I am the modal content!</Text>
</View>
</Modal>
</View>
);
};
export default ModalExample;

React navigation- Wrap button in TabBar

I'm new in React Native and i'm trying to do the TabBar in the image. My problem is to put a button in the tabbar. If someone can help me or have an idea to create this tabbar it could be really nice.
THX
you can check
this link. One of the props to pass TabNavigator is tabBarComponent. If you do not want the default styling or have to make custom tabBar you can specify the how the component should look.
In your case this should work.
import React from 'react';
import {View, Text, TouchableOpacity, Dimensions} from 'react-native';
import {TabNavigator} from 'react-navigation';
import Tab1Screen from '../components/tab1Screen';
import Tab2Screen from '../components/tab2Screen';
var {height, width} = Dimensions.get('window');
const mainRoutes = TabNavigator({
Tab1: {screen: Tab1Screen},
Tab2: {screen: Tab2Screen}
},
{
tabBarComponent:({navigation}) => (
<View style={{flex: 0.1, borderColor: 'green', borderWidth: 1}}>
<View style={{flexDirection:'row', justifyContent: 'space-around', alignItems: 'center', paddingTop: 15}}>
<View style={{width: 40, height: 40, borderRadius: 20, borderColor: 'red', borderWidth: 1, position: 'absolute', left: width/2.5, bottom:13 }}></View>
<TouchableOpacity onPress={() => navigation.navigate('Tab1')}>
<Text>Tab1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('Tab2')}>
<Text>Tab2</Text>
</TouchableOpacity>
</View>
</View>
)});
export default mainRoutes;
I had to do something similar. I'm using React Navigation v5 and in my case, the button had to execute a custom action instead of navigating to a tab. So this is what I did:
import styles from './styles';
// Other needed imports...
// ...
<Tab.Screen
name="Add Recipe"
component={() => null}
options={{
tabBarButton: () => (
<TouchableOpacity
style={styles.addIconWrapper}
onPress={() => {
// Your custom action here
}}
>
<View style={styles.addIconBackground}>
<Image source={assets.add} style={styles.addIconImage} />
</View>
</TouchableOpacity>
),
}}
/>;
And inside styles.js:
// ...
addIconWrapper: {
width: '20%',
justifyContent: 'center',
alignItems: 'center',
},
addIconBackground: {
marginTop: -30,
backgroundColor: '#85c349',
borderColor: 'white',
shadowOffset: { width: 2, height: 2 },
shadowColor: '#999',
shadowOpacity: 0.5,
borderRadius: 1000,
width: 42,
height: 42,
justifyContent: 'center',
alignItems: 'center',
},
addIconImage: {
tintColor: 'white',
},
Final result