I am creating a map application with two simple components: a search bar, using react-native-paper and a map, using react-native-maps. By now, only the UI is implemented.
When placing only the search bar, everything works fine. I am able to type my search query and the keyboard pops up when I click on the bar:
import { StatusBar } from 'expo-status-bar';
import * as React from 'react';
import MapView, { Marker } from 'react-native-maps';
import { StyleSheet, View, Dimensions, PermissionsAndroid } from 'react-native';
import {
Provider as PaperProvider,
DarkTheme,
Drawer,
DefaultTheme,
BottomNavigation,
Text,
Appbar,
Theme,
TextInput,
Searchbar,
} from 'react-native-paper';
const styles=StyleSheet.create({
searchBar:{
width: '90%',
position: 'absolute',
top: '7%',
alignSelf: 'center',
}
})
const MyComponent = () => {
const [searchQuery, setSearchQuery] = React.useState('');
const onChangeSearch = query => setSearchQuery(query);
return (
<View style={{width: "100%", height: "100%"}}>
<Searchbar style={styles.searchBar}
placeholder="Search"
onChangeText={onChangeSearch}
value={searchQuery}
/>
</View>
);
};
export default MyComponent;
After adding the map, nothing happens when clicking the search box. If I type something on my physical keyboard, the input seems to be captured as the icon displays an animation, but nothing else happens.
import * as React from 'react';
import MapView, { Marker } from 'react-native-maps';
import { StyleSheet, View, Dimensions, PermissionsAndroid } from 'react-native';
import {
Provider as PaperProvider,
DarkTheme,
Drawer,
DefaultTheme,
BottomNavigation,
Text,
Appbar,
Theme,
TextInput,
Searchbar,
} from 'react-native-paper';
const styles=StyleSheet.create({
searchBar:{
width: '90%',
position: 'absolute',
top: '7%',
alignSelf: 'center',
}
})
const MyComponent = () => {
const [searchQuery, setSearchQuery] = React.useState('');
const { height, width } = Dimensions.get( 'window' );
const onChangeSearch = query => setSearchQuery(query);
return (
<View style={{width: "100%", height: "100%"}}>
<Searchbar style={styles.searchBar}
placeholder="Search"
onChangeText={onChangeSearch}
value={searchQuery}
/>
<MapView
style={{flex: 1}}
showsUserLocation={true}
showsMyLocationButton={true}
//onMapReady={_onMapReady}
region={{
latitude: -8.327352784611014,
longitude: -36.14413540428909,
latitudeDelta: 55.5,
longitudeDelta: 55.5 * (width / height),
}}></MapView>
</View>
);
};
export default MyComponent;
Any help is appreciated! This is my first react project.
have you tried messing around with zIndex?
maybe adding zIndex: 10 to the text input style
You have to change the order of TextInput and Mapview as you can find in their readme file: https://github.com/react-native-maps/react-native-maps#inputs-dont-focus
Bad:
<View>
<TextInput/>
<MapView/>
</View>
Good:
<View>
<MapView/>
<TextInput/>
</View>
Related
I'm currently having a problem with the clickable size of a reusable button which includes an icon and text. When I run this code it seems like the entire row becomes clickable when I only want the icon and text to become clickable. Does anyone know how to solve this problem? Thanks
App.js
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import IconTextButton from './components/iconTextButton';
export default function App() {
return (
<View style={styles.container}>
<Text style={{marginTop: 100}}>My First React App! Sike </Text>
<IconTextButton iconFont="ionicons" iconName="pencil" iconSize={25} text="Add Items"/>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'powderblue',
},
});
iconTextButton.js
import React from 'react';
import { StyleSheet, TouchableOpacity, Text, View } from 'react-native';
import Ionicon from 'react-native-vector-icons/Ionicons';
export default function IconTextButton({ iconFont, iconName, iconSize, text, onPress }) {
const getIconFont = (iconFont) => {
switch (iconFont) {
case "ionicons":
return Ionicon;
}
};
const FontIcon = getIconFont(iconFont);
return (
<TouchableOpacity onPress={onPress} style={styles(iconSize).container>
<FontIcon name={iconName} size={iconSize} style={styles(iconSize).buttonIcon}>
<Text style={styles(iconSize).buttonText}>{text}</Text>
</FontIcon>
</TouchableOpacity>
)
}
const styles = (size) => StyleSheet.create({
container: {
backgroundColor: 'pink',
},
buttonIcon: {
backgroundColor: 'yellow',
width: size,
},
buttonText: {
backgroundColor: 'green'
},
})
Along with the code I've tried, I've also tried to keep and as seperate contents whilst adding a flexDirection: 'row' inside styles.container. This keeps the contents in the same line but it still makes the whole row clickable. I've also tried putting everything in a and moving the styles.container to the component and adding a height: size into styles.container. This makes the clickable component limited however, the component is hidden underneath due to the restricted height. I have also tried simply just using instead of making a reusable const that its an input. The same thing applies.
You can wrap your Icon and Text Component in a View component and then wrap it inside a TouchableOpacity Component
Try this or do something like this :
import React from 'react';
import { StyleSheet, TouchableOpacity, Text, View } from 'react-native';
import Ionicon from 'react-native-vector-icons/Ionicons';
export default function IconTextButton({ iconFont, iconName, iconSize, text, onPress }) {
const getIconFont = (iconFont) => {
switch (iconFont) {
case "ionicons":
return Ionicon;
}
};
const FontIcon = getIconFont(iconFont);
return (
<TouchableOpacity onPress={onPress} style={styles(iconSize).container}>
<View style={styles(iconSize).iconTextContainer}>
<FontIcon name={iconName} size={iconSize} style={styles(iconSize).buttonIcon} />
<Text style={styles(iconSize).buttonText}>{text}</Text>
</View>
</TouchableOpacity>
)
}
const styles = (size) => StyleSheet.create({
container: {
backgroundColor: 'pink',
},
iconTextContainer: {
flexDirection: 'row',
alignItems: 'center',
},
buttonIcon: {
backgroundColor: 'yellow',
width: size,
},
buttonText: {
backgroundColor: 'green'
},
})
I have this HomeScreen file, in it I have added Card component(Dashboard & Highlights), I have Customized the Card Components with the TitleCard to reuse the styling,
In each card there is "View All" Button to navigate to its individual Screens,
When I don't use the Cards and put the entire code in home screen and Click on the View All Button on home screen then it navigates to that page, but when I use the Cards and use its props to navigate to the link provided as forwardLink props then
I get this error
"ReferenceError: Can't find variable: navigation"
Also when I add this.props.navigation.navigate('{props.forwardLink}') in TitleCard
I get this error message:
TypeError: undefined is not an object (evaluating '_this.props.navigation')
Here are the codes for each file
TitleCards
import React from 'react';
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native';
const TitleCards = props => {
return (<View style={styles.textTitlesContainer}>
<Text style={styles.textTitle}>{props.leftTitle}</Text>
<TouchableOpacity
onPress={() => navigation.navigate('{props.forwardLink}')}>
<Text style={[styles.textTitle, {color: '#F483A7'}]}>
{props.rightTitle}
</Text>
</TouchableOpacity>
</View>)
};
const styles = StyleSheet.create({
textTitlesContainer: {
flex: 1,
width: '100%',
flexDirection: 'row',
justifyContent: 'space-between',
padding: 5,
},
textTitle: {
fontSize: 20,
fontWeight: '800',
color: '#fff',
},
});
export default TitleCards;
HomeScreen
import React, {Component} from 'react';
import {
SafeAreaView,
ScrollView,
StyleSheet,
} from 'react-native';
import {CustomHeader} from '../index';
import Colors from '../constants/Colors';
import DashboardCard from './DashboardCard';
import HighlightCard from './HighlightCard';
export class HomeScreen extends Component {
render() {
return (
<SafeAreaView style={{flex: 0, backgroundColor: Colors.primary}}>
<CustomHeader
title="Home"
isHome={true}
navigation={this.props.navigation}
/>
<ScrollView style={styles.container}>
<DashboardCard />
<HighlightCard />
</ScrollView>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
height:900, backgroundColor: Colors.mainBackground,
paddingTop:6,
},
});
export default HomeScreen;
HighlightCard
import React, {Component} from 'react';
import {Text, View} from 'react-native';
import {CustomHeader} from '../../index';
const HighlightCard = (prop) => {
return (
<Card>
<TitleCards leftTitle="Highlights" rightTitle="View More" forwardLink="Highlights">
</TitleCards>
<View>
<Text>News Feed</Text>
</View>
</Card>
);
};
export default HighlightCard;
const styles = StyleSheet.create({
textTitle: {
fontSize: 20,
fontWeight: '800',
color: '#fff',
},
});
When I use the HighlightCard codes directly in HomeScreen then it navigates to that page, below is that code which works if I use it directly in Home Screen
*{/* <Text style={styles.textTitle}>Highlights</Text>
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Highlights')}>
<Text style={[styles.textTitle, {color: '#F483A7'}]}>View All</Text>
</TouchableOpacity> */}*
I think there is something wrong I am doing is using the props or referencing to the navigation page
I also tried creating a const for navigation
const {navigate} = this.props.navigation
this didn't worked either
I'm not sure why JS thread drops frames when I'm toggling the height of the View when using react-native-reanimated v2? When I press the button JS frames are around 50-55 and UI thread fps stay 60. Thank you.
My code is pretty simple:
import React, {useEffect} from 'react';
import {
Button,
ImageBackground,
StatusBar,
StyleSheet,
Text,
ViewStyle,
} from 'react-native';
import Animated, {
useAnimatedStyle,
useSharedValue,
withTiming,
} from 'react-native-reanimated';
export const TestingScreen: React.FC<TestingScreenProps> = () => {
const height = useSharedValue(0);
const style = useAnimatedStyle(() => {
return {
height: withTiming(height.value),
};
});
return (
<>
<StatusBar barStyle="dark-content" />
<ImageBackground
style={styles.container}
source={require('./../../../assets/images/cinema.jpg')}
resizeMode={'cover'}>
<Animated.View style={[styles.form, style]}>
<View
style={{
width: 150,
height: 150,
backgroundColor: 'red',
}}></View>
</Animated.View>
<Button
title={'Toogle'}
onPress={() =>
(height.value =SCREEN_HEIGHT * Math.random())
}
/>
<Text
style={{fontSize: 23, color: 'white', fontFamily: 'OpenSans-Italic'}}>
TESTING
</Text>
</ImageBackground>
</>
);
};
I think this is because button pressing function (onPress prop) is in the JS side. So the pressing part happening in the JS thread. That's why JS frames drop when you hit the button.
What would be the way to achieve this.
callback with Animated.event works fine
callback with block gives no feedback :(
import React, { useState, useEffect } from "react";
import { View, Text, FlatList, Dimensions, Image } from "react-native";
import Animated from "react-native-reanimated";
import { PanGestureHandler, TapGestureHandler, State } from "react-native-gesture-handler";
const { Value, event, call, set, add, block } = Animated;
const bottom = new Value(100);
//want to achieve something like this
const onHandlerStateChange = block([set(bottom, add(bottom, 10))]);
// the line below Does work
// const onHandlerStateChange = event([{ nativeEvent: { y: bottom } }]);
const Comp = () => {
return (
<TapGestureHandler onHandlerStateChange={onHandlerStateChange}>
<Animated.View style={{ flex: 1}}>
<Animated.View style={{ flex: 1, position: "absolute", bottom: bottom }}>
<Text> some text</Text>
</Animated.View>
</Animated.View>
</TapGestureHandler>
);
};
export default Comp;
*const onHandlerStateChange = block([set(bottom, add(bottom, 10))]); * Doesn't work here
Here's the solution that works
Tip :
Understanding how reanimated evaluates nodes will be very useful
Here's the link to offical doc that might help you understand
https://software-mansion.github.io/react-native-reanimated/about-reanimated.html#at-most-once-evaluation-the-algorithm-
import React, { useState, useEffect } from "react";
import { View, Text, FlatList, Dimensions, Image } from "react-native";
import Animated from "react-native-reanimated";
import {
PanGestureHandler,
TapGestureHandler,
State,
} from "react-native-gesture-handler";
const { Value, event, call, set, add, cond, eq, block } = Animated;
const gstate = new Value(-1);
const onHandlerStateChange = event([{ nativeEvent: { state: gstate } }]);
let bottom = new Value(100);
bottom = cond(eq(gstate, State.END), [set(bottom, add(bottom, 10))], bottom);
const Comp = () => {
return (
<TapGestureHandler onHandlerStateChange={onHandlerStateChange}>
<Animated.View style={{ flex: 1, backgroundColor: "pink" }}>
<Animated.View
style={{ flex: 1, position: "absolute", bottom: bottom }}
>
<Text> some text</Text>
</Animated.View>
</Animated.View>
</TapGestureHandler>
);
};
export default Comp;
I am trying to set a gradient color for android status bar using react-native. But setBackgroundColor is taking color string.
Is it possible to use gradient color for status bar color?
You can use translucent={true} and backgroundColor={'transparent'} properties with StatusBar and wrap them with react-native-linear-gradient
like this:
<LinearGradient colors={["#79e3fe","#635df8","#42385D"]} style={{flex: 1}}>
<StatusBar translucent={true} backgroundColor={'transparent'} />
</LinearGradient >
You can tweak that.
In my case I use wix/react-native-navigation to navigate between screen in my application. So I use theses options for displaying my screens.
navigatorStyle: {
navBarHidden: true,
statusBarColor: 'transparent',
drawUnderStatusBar: true
},
An after you need to import react-native-linear-gradient to tweak your status bar. (create a component and add it to your pages)
<View>
<LinearGradient colors={yourArrayOfColors} style={styles.header}/>
</View>
... //and in your style
header: {
height: (Platform.OS === 'ios' ? 20 : StatusBar.currentHeight),
}
That could do the trick !
It works out for me with the following steps.
Add React Navigation as root component for React Native.
Create a custom header and make a gradient background for it. react-native-linear-gradient is needed of course. The following code demonstrates how to do it.
// #flow
import React from "react";
import { View, Platform, StatusBar } from "react-native";
import { createStackNavigator, createAppContainer } from "react-navigation";
import { Header, StackViewTransitionConfigs } from "react-navigation";
import LinearGradient from "react-native-linear-gradient";
import MainScreen from "./MainScreen";
const GradientBackground = props => (
<LinearGradient
colors={["#FFD801", "#FF8040"]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
{...props}
/>
);
const AppNavigator = createStackNavigator(
{
MainScreen: { screen: MainScreen }
},
{
headerBackTitleVisible: false,
initialRouteName: "MainScreen",
defaultNavigationOptions: {
header: props => {
return (
// When StatusBar is translucent, the StatusBar will be offset up by "StatusBar.currentHeight" points.
// That's why the height of the Header is "Header.HEIGHT + StatusBar.currentHeight".
<View style={{ height: Header.HEIGHT + StatusBar.currentHeight }}>
<GradientBackground style={{ height: StatusBar.currentHeight }} />
<Header {...props} />
</View>
);
},
headerTintColor: "#FFF",
headerBackground: (
<GradientBackground style={{ height: Header.HEIGHT }} />
),
headerStyle: {
backgroundColor: "transparent"
}
},
headerLayoutPreset: "center"
}
);
const MainStack = createAppContainer(AppNavigator);
export default MainStack;
Add StatusBar to the root component and set StatusBar translucent.
// #flow
// #format
import React, { Component } from "react";
import { Button, TextInput, StyleSheet, StatusBar } from "react-native";
import { View, Text, FlatList } from "react-native";
import { NavigationScreenProp, NavigationState } from "react-navigation";
type Props = {
navigation: NavigationScreenProp<NavigationState>
};
/**
* 程序主页
* #export MainScreen
* #class MainScreen
* #extends {Component}
*/
export default class MainScreen extends Component<Props> {
static navigationOptions = {
headerTitle: "MainScreen"
};
render() {
const { navigation } = this.props;
return (
<View style={[styles.screenContainer]}>
<StatusBar
barStyle="light-content"
translucent={true}
backgroundColor="transparent"
/>
</View>
);
}
}
const styles = StyleSheet.create({
screenContainer: {
flex: 1
}
});
Enjoy!
If the description above is not clear to you, feel free to download the ReactNavigationGradientStatusbar Project and check it out.
1.add react-native-linear-gradient to your project
use this code :
import {View , StyleSheet,StatusBar} from 'react-native'
import LinearGradient from 'react-native-linear-gradient';
render(){
const StatusBarHeight = StatusBar.currentHeight
return(
<View>
<View style={{ height : StatusBarHeight , width : '100%' }}>
<LinearGradient
start={{x: 0.0, y: 0.5}}
end={{x: 0.5, y: 1.0}}
locations={[0,0.3,0.6]}
colors={['#4c669f', '#3b5998', '#192f6a']} style={style.Container}>
</LinearGradient>
</View>
</View>
)
}
and this :
const style = StyleSheet.create({
Container : {
flex : 1,
backgroundColor : '#2980b9',
justifyContent : 'center',
alignItems : 'center',
flexDirection : 'row'
}
})
As the documentation states at this point it only accepts a string, so no, you cannot. And, besides, I can't even come up with an app using a gradient on their status bar.
If the StatusBar would accept a component you could try using the Expo.io API to do so. Check https://docs.expo.io/versions/latest/sdk/linear-gradient.html if you are curious about it.