React Native Tabbar Icon is not displaying on the a real device - javascript

I have a react native application in which I on the tab bar I am displaying an image as my tab bar icon. The issue is that it displays completely fine on the android simulator but when I run the same app on a real device the tab bar icon (which is a static image) is showing.
Here is the code snippet that I am using
<Tab.Screen
name="NFT Market"
component={NftMarketplace}
options={{
headerShown: false,
tabBarHideOnKeyboard: true,
tabBarIcon: ({focused}) => (
<View
style={{
justifyContent: 'center',
alignItems: 'center',
}}>
<Image
source={customIcons.nftmaketplace}
resizeMode="contain"
style={{
width: 50,
height: 50,
}}
/>
</View>
),
tabBarButton: props => <CustomTabbarButtom {...props} />,
}}
/>
Following is the CustomTabbarButtom
const CustomTabbarButtom = ({children, onPress}) => {
return (
<TouchableOpacity onPress={onPress} style={styles.customTabbarButtom}>
<View style={styles.view__customTabbarButtom}>{children}</View>
</TouchableOpacity>
);
};
Here the Image source customIcons.nftmaketplace is a static image I have imported at the top of my file.

Related

React Navigation | How do I change the buttons on a Tab Navigator from a child screen nested in a Stack Navigator?

I have a tab bar that looks like this:
The two side buttons are stack navigators (Learn and Journal) and the middle button needs to navigate the Journal Stack, and depending on what screen in the Journal Stack the user is on, it needs to say and do different things.
const Tab = createBottomTabNavigator();
const TabBarIcon = ({ icon, title, focused }) => {
return (
<View style={styles.iconContainer}>
<FontAwesomeIcon
icon={icon}
color={focused ? Colors.neutral[4] : Colors.neutral[6]}
size={24}
style={styles.icon}
/>
<Text style={[styles.iconText, focused && styles.iconTextFocused]}>
{title}
</Text>
</View>
);
};
const NullScreen = () => null;
const TabNavigator = () => {
return (
<Tab.Navigator
initialRouteName="Journal"
screenOptions={({ route }) => ({
...defaultNavOptions,
headerShown: false,
tabBarStyle: { backgroundColor: Colors.neutral[3] },
tabBarShowLabel: false,
})}
>
<Tab.Screen
name="Learn"
component={LearnStackNavigator}
options={{
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
title={'Learn'}
icon={faUserGraduate}
/>
),
}}
/>
<Tab.Screen
name="Null Screen"
component={NullScreen}
options={{
tabBarButton: ({ focused }) => (
<View
style={{
position: 'relative',
bottom: 25,
width: 80,
height: 80,
borderRadius: '50%',
backgroundColor: 'grey',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
shadowColor: 'black',
shadowOpacity: 0.3,
shadowOffset: { width: 0, height: 2 },
shadowRadius: 3,
}}
>
<TouchableOpacity onPress={() => Alert.alert('hello world')}> // This is the button that I want use for useful things
<View style={[styles.iconContainer, styles.paddingBottom10]}>
<FontAwesomeIcon
icon={faPlus}
color={focused ? Colors.neutral[4] : Colors.neutral[6]}
size={32}
/>
<Text style={styles.iconText}>{'Add Sport'}</Text>
</View>
</TouchableOpacity>
</View>
),
}}
/>
<Tab.Screen
name="Journal"
component={LogbookStackNavigator}
options={{
tabBarIcon: ({ focused }) => (
<TabBarIcon focused={focused} title={'Journal'} icon={faPenAlt} />
),
}}
/>
</Tab.Navigator>
);
};
And here is what the LogbookStackNavigator looks like:
const LogbookStack = createStackNavigator();
const LogbookStackNavigator = () => {
return (
<LogbookStack.Navigator
screenOptions={{
...defaultNavOptions,
headerBackTitleVisible: false,
}}
>
<LogbookStack.Screen
name="Screen1"
component={screen1Component}
options={defaultNavOptions}
/>
<LogbookStack.Screen
name="Screen2"
component={screen2Component}
options={defaultNavOptions}
/>
<LogbookStack.Screen
name="Screen3"
component={screen3Component}
options={entryScreenOptions}
/>
<LogbookStack.Screen
name="Screen4"
component={screen4Component}
options={SaveLogbookScreenOptions}
/>
<LogbookStack.Screen
name="Screen5"
component={screen1Component5}
options={defaultNavOptions}
/>
</LogbookStack.Navigator>
);
};
I know how to use navigation.setOptions, but it only affects the immediate parent navigator, not the grandparent navigator.
Another thing I tried was to make the big circle button on the page itself, but it always rendered underneath the Tab Navigator. If there was a way to make it render above, I think I could just use that. I tried 'position: 'absolute', etc and it always rendered underneath the tab navigator. As it is, I had to basically make a dummy screen in the tab navigator to give me the button on top.
What I need to be able to do, is use big circle button on the Tab Navigator, to navigate to different screens in the LogbookStackNavigator. How do I do that?
Also, I need the title to change from "Add Sport" to "Add " depending on what screen the LogbookStackNavigator is on. How do I do that?
Thanks for your help
Finally figured this out. You have to use react-native-portalize. Just wrap the elements you want to be rendered on top in a
<Portal></Portal>. This will place it above a Bottom Tab navigator.
import { Portal } from 'react-native-portalize';
const FooterButton = () => {
return(
<Portal>
<View>
<Text>I appear above the Tab Navigator!</Text>
</View>
</Portal>
);
export default FooterButton;
Don't forget to wrap the whole app in the the Host:
//In app.js
import { Host } from 'react-native-portalize';
const App = () => {
return (
<Host>
<NavigationContainer>
<AppNavigator />
</NavigationContainer>
</Host>
)
}
export default App;
NOTE: The elements inside the Portal, do not clear when the navigator navigates to another screen. So to get around this, you have to only display the Portal, when the screen is active. Thankfully React Navigation 5+ provides a useIsFocused hook that accomplishes this perfectly.
import { Portal } from 'react-native-portalize';
import { useIsFocused } from '#react-navigation/native';
const FooterButton = () => {
const isFocused = useIsFocused();
// Only display the button when screen is focused. Otherwise, it doesn't go away when you switch screens
return isFocused ? (
<Portal>
<View style={styles.buttonContainer}>
<View style={styles.footer}>{props.children}</View>
</View>
</Portal>
) : null;
};
export default FooterButton;
If you want a modal-style popup, you can wrap react-native-modalize and wrap it with react-native-modalize
Thanks to livin52 on Reddit for the solution

Using a variable for a createDrawerNavigation

I am working on a simple React Native e-commerce app and i ran into a issue. I am trying to add the option to change the language, and it has worked so far with the Redux but now i need to dynamically change the sidebar menu and I cant because it is hardcoded as a prop.The code for the menu is this.
const ShopNavigator = createDrawerNavigator(
{
Produktetee: ProductsNavigator,
Rezervimet: OrdersNavigator,
Postoni: AdminNavigator},
{
contentOptions: {
activeTintColor: MyColors.primary
},
contentComponent: props => {
const {log_out} = useSelector(state => state.language)
const dispatch = useDispatch();
return (
<View style={{ flex: 1, paddingTop: 50 }}>
<SafeAreaView forceInset={{ top: "always", horizontal: "never" }}>
<DrawerItems {...props} />
<Button
title={log_out}
color={MyColors.primary}
onPress={() => {
dispatch(authActions.logOut());
// props.navigation.navigate("Auth");
}}
/>
<View style={{flexDirection: 'row'}}>
<View style={{flex:1 , marginRight:10, marginTop: 5,}} >
<Button
title="English"
type="outline"
color={MyColors.primary}
onPress={()=>{
dispatch(index.selectLanguage(languages.english))
}}
/>
</View>
<View style={{flex:1, marginTop: 5,}} >
<Button
title="Shqip"
type="outline"
color={MyColors.primary}
onPress={()=>{
dispatch(index.selectLanguage(languages.albanian))
}}
/>
</View>
</View>
</SafeAreaView>
</View>
);
}
}
);
I am trying to use the hook, but I can't. If somebody could help me I would be very grateful.

Is there a way to make a sized and functional FlatList inside a Modal?

Good evening!
I have been trying to create a modal with a scrollable FlatList inside, but such FlatList should have its height size reduced. The modal is going to search a wide list of airports, so basically a lot data might be shown, hence why FlatList is the best tool for this occasion. Basically, the modal screen would look like this picture below:
However, I can't make the scroll inside FlatList work no matter what. Here is the code, with the FlatList that is somewhat functional, but it has a warning:
const styles = StyleSheet.create({
modalContainer: {
backgroundColor: 'rgba(50,50,50,0.6)',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
modalActivityContainer: {
backgroundColor: colors.colorWhite,
borderColor: colors.colorLightBlack,
borderWidth: 2,
borderRadius: 20,
padding: props.padding ? Number(props.padding) : 10,
maxWidth: '85%',
},
modalHeader: {
flexDirection: 'row',
justifyContent: 'center',
},
headerAirportModal: {
backgroundColor: colors.colorGrey,
borderTopRightRadius: 20,
borderTopLeftRadius: 20,
paddingHorizontal: 5,
paddingVertical: 10,
width: '100%',
justifyContent: 'center',
},
searchAirportBarContainer: {
backgroundColor: colors.colorWhite,
height: 40,
},
...
<Modal
onRequestClose={() => props.onRequestClose()}
animationType="fade"
transparent
visible={props.showModal}>
<TouchableWithoutFeedback
onPress={() => {
props.onRequestClose();
}}>
<View style={styles.modalContainer}>
<TouchableWithoutFeedback>
<View style={styles.modalActivityContainer}>
<View style={styles.modalHeader}>
<View style={styles.headerAirportModal}>
<Item style={styles.searchAirportBarContainer} rounded>
<Icon
style={styles.iconSearchAirport}
type="FontAwesome5"
name="search"
/>
<Input
style={styles.searchAirportBarText}
placeholderTextColor={colors.colorLightBlack}
placeholder="Search by Airport, Country or City"
/>
</Item>
</View>
</View>
<View>
<View style={styles.modalHeader}>
<Grid style={styles.headerAirportModalBackground}>
<Text style={styles.headerAirportModalText}>Latest Searches</Text>
<TouchableOpacity style={styles.clearButtonLatestContainer}>
<View>
<Text style={styles.clearButtonAirport}>Clear</Text>
</View>
</TouchableOpacity>
</Grid>
</View>
</View>
<View style={{maxHeight: 250}}>
<ScrollView>
<View onStartShouldSetResponder={() => true}>
<FlatList
data={airportElements}
renderItem={renderAirportItem}
keyExtractor={(item) => item.id}
/>
</View>
</ScrollView>
</View>
<Button
backgroundColor={colors.colorRed}
alignSelf="stretch"
buttonStyle={styles.finishButton}
onPress={() => {
setModalSelectAirport(false);
}}>
Cancel
</Button>
</View>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
</Modal>
If I use the FlatList inside the ScrollView like shown above, the code works as intended. However, I got this warning:
VirtualizedLists should never be nested inside plain ScrollViews
with the same orientation - use another VirtualizedList-backed
container instead.
Because of that, I can't use FlatList properly. Also, I have managed to make it work with .map, but it was advised to not use it as I am going to load a list with a lot of elements and that might cause lag.
I have managed to implement FlatList in another way like this:
<View
style={styles.airportLatestSearchListContainer}>
<FlatList
contentContainerStyle={styles.airportLatestSearchlist}
data={airportElements}
renderItem={renderAirportItem}
keyExtractor={(item) => item.id}
/>
</View>
This, however, prevents the user to scroll. The list remains static and the user can't scroll at all.
I have tried using {flex: 1, flexGrow: 1} in the parent View and FlatList itself, both don't work at all, even inside the FlatList container or the style.
Can someone please help me with this one? I really appreciate the time and effort! Thanks!

The last result from the search is hidden by the bottomTabNavigaor

The problem is that the last result from the search is hidden by the bottomTabNavigaor and I can't scroll the last result above it.
I need to see the bottomTabNavigaor not to hide it.
return (
<View>
<ScrollView style={{ backgroundColor: '#DEFEFC'}}>
{musicList.map(songObj => {
return (
<View key={songObj.Song_ID} >
<TouchableOpacity style={styles.resultsContainer}
onPress={this.GetListViewItem.bind(this, songObj.Song_ID)}
>
<Text style={{ fontSize: 16, flex:1}} key={songObj.Song_ID}>
{songObj.Song_Name}
</Text>
<Image source={{ uri: songObj.Image }} style={styles.img} />
</TouchableOpacity>
</View>
);
})}
</ScrollView>
</View>
);
my bottomTabNavigator:
const HomeStack = createStackNavigator({
Home: HomeScreen
});
HomeStack.navigationOptions = {
tabBarLabel: "Home",
tabBarIcon: (
<Image
style={{ width: 27, height: 27 }}
source={{uri: bottomImage+ "/home.png"}}
/>
)
};
const SearchStack = createStackNavigator({
Search: SearchScreen
});
SearchStack.navigationOptions = {
tabBarLabel: "Search Music",
tabBarIcon: (
<Image
style={{ width: 27, height: 27 }}
source={{uri: bottomImage +"/search_1.jpg"}}
/>
)
};
/////----{ I shorten it you can guess the others} ---
export default createBottomTabNavigator({
HomeStack,
ArtistsStack,
SearchStack,
PlaylistStack,
ShowDataStack
});
if any additional code is needed please tell me and I'll put it here.
This issue is not due to the navigator we had the same issue with the Scroll view the easiest way to sort it will be using a padding at the bottom for the scroll view.
<ScrollView style={{ backgroundColor: '#DEFEFC',paddingBottom: 50}}>
</ScrollView>
Update the padding value based on the height of your item.

React Native - iOS - Local image invisible (works on android)

I'm mapping TouchableOpacity with an Image nested inside of it. It works great on Android but on iOS the image is invisible. There is still a 75x75 touchable opacity that I can tap but the image is invisible in the modal that pops up and just in general.
How does this work?
I'm using Expo SDK FileSystem to get the path of each image.
For example: file://path/to/container/progress/myfilehash.jpg
I push this to my state and map it in the component. the require() function WILL NOT WORK for the way I am doing this. I think it is purely a problem with the rendering.
Map code:
{this.state.images.map((val, key) => (
<TouchableOpacity
key={key}
onPress={() => this.setState({active: val, modal: true})}
>
<Image
style={{width: 75, height: 75}}
source={{isStatic: true, uri: val}}
/>
</TouchableOpacity>
))}
Modal:
<Container style={Colors.Backdrop}>
<Header style={Colors.Navbar}>
<Left>
<TouchableHighlight
onPress={() => {
this.setState({modal: false})
}}>
<Icon
name="arrow-back"
style={{color: 'white'}}
/>
</TouchableHighlight>
</Left>
<Body></Body>
<Right>
<TouchableOpacity
onPress={() => {
this._deleteImage(this.state.active);
}}>
<Text
style={[
Colors.ErrorText, {
fontSize: 24,
marginRight: 10
}
]}>×</Text>
</TouchableOpacity>
</Right>
</Header>
<Content>
<View
style={{flex: 1}}
>
<FitImage
source={{uri: this.state.active}}
/>
</View>
</Content>
</Container>
Code for fetching image paths. (NOTE: I tried not truncating "file://" from ios with same exact result)
_getAllImagesInDirectory = async() => {
let dir = await FileSystem.readDirectoryAsync(FileSystem.documentDirectory + 'progress');
dir.forEach((val) => {
this.state.images.push(Platform.OS === 'ios' ? FileSystem.documentDirectory.substring(7, FileSystem.documentDirectory.length) : FileSystem.documentDirectory + 'progress/' + val);
});
await this.setState({images: this.state.images, loading: false});
}
I also faced this problem once, I solved it by pasting the image in the root folder and then used that path in the source of Image tag.

Categories