I am able to get it to the center without the mapview but I cant seem to get the image to the center with mapview. anyone able to do it on react native?
render() {
return (
<View style = { styles.container }>
<MapView style = { styles.mapView }></MapView>
<View style = { styles.mapCenterMarkerView }>
<Image style={styles.mapCenterMarker}
source={{uri: this.state.markerIcon}}/>
</View>
);
}
var styles = StyleSheet.create({
container: {
flex: 1,
},
mapView: {
flex: 1
},
mapCenterMarkerView: {
top: 0,
position: 'absolute',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0)',
},
mapCenterMarker: {
width: 32,
height: 32,
},
});
I was able to get the result you're looking for, but I had to remove the flex styling from the MapView.
https://rnplay.org/apps/TQGKjA
It looks like MapView doesn't allow child nodes. There's probably a way to do this without resorting to position: 'absolute' for the MapView but I'd have to play with it some more.
If you're new to flexbox like me, I've found this to be a good resource:
flexboxin5.com
class SampleApp extends React.Component {
render() {
return (
<View style={ styles.container }>
<MapView style={ styles.mapView }></MapView>
<View style={styles.mapCenterMarker} />
</View>
);
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0)',
},
mapView: {
position: 'absolute',
top: 20,
bottom: 0,
left: 0,
right: 0,
},
mapCenterMarkerView: {
flex: 1,
},
mapCenterMarker: {
width: 32,
height: 32,
backgroundColor: 'black'
},
});
I move the justifyContent: 'center' down from container for it to work. thank to you because i have a inside the .
container: {
flex: 1,
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0)',
},
mapView: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
},
mapCenterMarkerView: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'rgba(0,0,0,0)',
},
mapCenterMarker: {
width: 32,
height: 32,
backgroundColor: 'rgba(0,0,0,0)'
},
Related
How can I achieve this in react native?
So far I have this and I want to implement the middle curve. I don't know to either handle it with a transparent view or switch to SVG completely
and this the tabBar component
/* eslint-disable react/prop-types */
import React, { Component } from 'react'
import { TouchableOpacity, Text, StyleSheet, View } from 'react-native'
import { Colors } from 'App/Theme'
export default class TabBar extends Component {
render() {
let {
renderIcon,
getLabelText,
activeTintColor,
inactiveTintColor,
onTabPress,
onTabLongPress,
getAccessibilityLabel,
navigation,
showLabel,
} = this.props
let { routes, index: activeRouteIndex } = navigation.state
return (
<View style={styles.tabBar}>
{routes.map((route, routeIndex) => {
let isRouteActive = routeIndex === activeRouteIndex
let tintColor = isRouteActive ? activeTintColor : inactiveTintColor
return (
<TouchableOpacity
key={routeIndex}
style={styles.tab}
onPress={() => {
onTabPress({ route })
}}
onLongPress={() => {
onTabLongPress({ route })
}}
accessibilityLabel={getAccessibilityLabel({ route })}
>
{renderIcon({ route, focused: isRouteActive, tintColor })}
{showLabel ? <Text>{getLabelText({ route })}</Text> : null}
</TouchableOpacity>
)
})}
</View>
)
}
}
const styles = StyleSheet.create({
tab: {
alignItems: 'center',
flex: 1,
justifyContent: 'center',
},
tabBar: {
alignSelf: 'center',
backgroundColor: Colors.primary,
borderRadius: 50,
bottom: 10,
elevation: 2,
flexDirection: 'row',
height: 65,
position: 'absolute',
width: '95%',
},
infinity: {
width: 80,
height: 100,
},
infinityBefore: {
position: 'absolute',
top: 0,
left: 0,
width: 0,
height: 0,
borderWidth: 20,
borderColor: 'red',
borderStyle: 'solid',
borderTopLeftRadius: 50,
borderTopRightRadius: 50,
borderBottomRightRadius: 50,
borderBottomLeftRadius: 0,
transform: [{ rotate: '-135deg' }],
},
infinityAfter: {
position: 'absolute',
top: 0,
right: 0,
width: 0,
height: 0,
borderWidth: 20,
borderColor: 'red',
borderStyle: 'solid',
borderTopLeftRadius: 50,
borderTopRightRadius: 0,
borderBottomRightRadius: 50,
borderBottomLeftRadius: 50,
transform: [{ rotate: '-135deg' }],
},
})
here is a demo: https://snack.expo.io/#nomi9995/cf371e
you need to use react-native-svg
yarn add react-native-svg
import React, { Component } from "react";
import {
Text,
StyleSheet,
View,
Dimensions,
TouchableHighlight,
} from "react-native";
import Svg, { Circle, Path } from "react-native-svg";
const tabs = [1, 2, 3, 4, 5];
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
pathX: "357",
pathY: "675",
pathA: "689",
pathB: "706",
};
}
render() {
return (
<View style={[styles.container]}>
<View style={[styles.content]}>
<View style={styles.subContent}>
{tabs.map((_tabs, i) => {
return (
<TouchableHighlight
key={i}
underlayColor={"transparent"}
onPress={() => console.log("onPress")}
>
<View>
</View>
</TouchableHighlight>
);
})}
</View>
<Svg
version="1.1"
id="bottom-bar"
x="0px"
y="0px"
width="100%"
height="100"
viewBox="0 0 1092 260"
space="preserve"
>
<Path
fill={"#373A50"}
stroke={"#373A50"}
d={`M30,60h${this.state.pathX}.3c17.2,0,31,14.4,30,31.6c-0.2,2.7-0.3,5.5-0.3,8.2c0,71.2,58.1,129.6,129.4,130c72.1,0.3,130.6-58,130.6-130c0-2.7-0.1-5.4-0.2-8.1C${this.state.pathY}.7,74.5,${this.state.pathA}.5,60,${this.state.pathB}.7,60H1062c16.6,0,30,13.4,30,30v94c0,42-34,76-76,76H76c-42,0-76-34-76-76V90C0,73.4,13.4,60,30,60z`}
/>
<Circle
fill={"#7EE6D2"}
stroke={"#7EE6D2"}
cx="546"
cy="100"
r="100"
/>
</Svg>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
overflow: "hidden",
},
content: {
flexDirection: "column",
zIndex: 0,
width: Dimensions.get("window").width - 30,
marginBottom: "4%",
left: "4%",
right: "4%",
position: "absolute",
bottom: "1%",
},
subContent: {
flexDirection: "row",
marginLeft: 15,
marginRight: 15,
marginBottom: 10,
zIndex: 1,
position: "absolute",
bottom: 5,
}
});
i hope this will help you.
Here is 2 solution according to your requirement.
If you want this type of design without selection then this code will help you :
https://github.com/alex-melnyk/clipped-tabbar
And if you need on each tab selection then here is other easy library for you :
https://github.com/Jm-Zion/rn-wave-bottom-bar
It's not obvious that this can be done with only <View/> components. I would split the TabBar into a flex row container with three subviews, and create an SVG with the filled inverted radius to be used in the center subview. To render the SVG, use react-native-svg. See a rough layout below:
...
import { SvgXml } from 'react-native-svg';
import TabCenterSvg from ‘assets/my-svg.svg’
export default class TabBar extends Component {
render() {
return (
<View style={styles.tabBar}>
<View style={styles.leftContainer}>
{/* Left Buttons */}
</View>
<View style={styles.centerContainer}>
<View style={styles.centerInnerTopContainer}>
{/* Add Button */}
</View>
<View style={styles.centerInnerBottomContainer}>
<SvgXml xml={TabCenterSvg} />
</View>
</View>
<View style={styles.rightContainer}>
{/* Right Icons */}
</View>
</View>
)
}
}
const styles = StyleSheet.create({
tabBar: {
alignSelf: 'center',
borderRadius: 50,
bottom: 10,
elevation: 2,
flexDirection: 'row',
height: 65,
position: 'absolute',
width: '95%',
},
leftContainer: {
flex: 1,
flexDirection: 'row',
borderBottomLeftRadius: 50,
borderTopLeftRadius: 50,
borderTopRightRadius: 50,
backgroundColor: Colors.primary,
},
centerContainer: {
flex: 1,
flexDirection: 'column',
},
centerInnerTopContainer: {
flex: 1,
},
centerInnerBottomContainer: {
flex: 1,
},
rightContainer: {
flex: 1,
flexDirection: 'row',
borderTopLeftRadius: 50,
borderTopRightRadius: 50,
borderBottomRightRadius: 50,
backgroundColor: Colors.primary,
},
})
Use this library's code and customize according to your UI
https://www.npmjs.com/package/curved-bottom-navigation-bar
Note: I'll not recommend this library as there are low weekly downloads.
Rather than using the whole library, you can use its code.
I have a list that shows results matching the user's input. The onPress of the touchableOpacity is not working in this list. This list is positioned absolutely and positioned below its parent view (positioned relative). The only time I can get the onPress to work is when I remove the top:48 style from list and the onPress works for the single element which is directly onTop of the parent.
export default function IndoorForm(props) {
return (
<View style={styles.container}>
<View style={styles.parent}>
<Autocomplete
style={styles.autocomplete}
autoCompleteValues={autoCompleteValues}
selectedLocation={props.getDestination}
></Autocomplete>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignSelf: "center",
position: "absolute",
top: Platform.OS === "android" ? 25 + 48 : 0 + 48,
width: Dimensions.get("window").width - 30,
zIndex: 500
},
parent: {
position: "relative",
flex: 1,
borderWidth: 2,
borderColor: "#AA2B45",
height: 48,
backgroundColor: "#fff",
flexDirection: "row",
alignItems: "center",
paddingLeft: 16,
paddingRight: 16,
justifyContent: "space-between"
}
}
export default function AutoComplete(props: AutoCompleteProps) {
const { autoCompleteValues } = props;
return (
<View style={styles.container}>
<FlatList
data={autoCompleteValues}
renderItem={({ item }: { item: POI }) => (
<TouchableOpacity onPress={() => console.log("Haal")} key={item.displayName} style={styles.list}>
<Text style={styles.text}>{item.displayName}</Text>
<Entypo name={"chevron-thin-right"} size={24} color={"#454F63"} />
</TouchableOpacity>
)}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
position: "absolute",
flex: 1,
width: Dimensions.get("window").width - 30,
top: 48,
borderWidth: 2,
borderColor: "#F7F7FA",
backgroundColor: "#F7F7FA",
zIndex: 999
},
list: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingTop: 15,
paddingLeft: 10,
paddingBottom: 10,
borderBottomColor: "rgba(120, 132, 158, 0.08)",
borderBottomWidth: 1.4,
zIndex: 999
}
}
I know you solved your issue already, but you can use this magical library react-native-gesture-handler, import your Touchables from there and they don't care about being inside the parent views. You can touch them regardless.
Resolved this by dynamically adjusting the container height so that the touchableOpacity is within the container. The issue was I positioned the list outside of the parent (as intended by styling) but for onPress to work it has to be inside the parent.
let autocompleteHeight = autoCompleteValues.length * 65
<View style={[styles.container, {height: autocompleteHeight}]}>
The problem is the Card View is not showing. I tried to apply it with index and position but nothing works. I need other's perspective. Thank you.
This is what I want to achieve:
Here are my codes:
return(
<View style={styles.container}>
{/* <StatusBar backgroundColor={'transparent'} translucent={true}/> */}
<MapView
style={styles.map}
initialRegion={this.state.focusedLocation}
onPress={this.pickLocationHandler}
showsUserLocation={true}
ref={ref => this.map = ref} //For animating map movement
>
{userMarker}
{this.state.markers.map((marker, index) => {
const scaleStyle = {
transform: [
{
scale: interpolations[index].scale,
},
],
};
const opacityStyle = {
opacity: interpolations[index].opacity,
};
return (
<MapView.Marker key={index} coordinate={marker.coordinate}>
<Animated.View style={[styles.markerWrap, opacityStyle]}>
<Animated.View style={[styles.ring, scaleStyle]}/>
<View style={styles.marker}/>
</Animated.View>
</MapView.Marker>
);
})}
</MapView>
<Animated.ScrollView
horizontal={true}
scrollEventThrottle={1}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
snapToInterval={CARD_WIDTH}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
x: this.animation,
},
},
},
],
{ useNativeDriver: true }
)}
style={styles.scrollView}
contentContainerStyle={styles.endPadding}
>
{this.state.markers.map((marker, index) => {
<View style={styles.card} key={index}>
<Image
source={marker.image}
style={styles.cardImage}
resizeMode="cover"
/>
<View style={styles.textContent}>
<Text numberOfLines={1} style={styles.cardtitle}>{marker.title}</Text>
<Text numberOfLines={1} style={styles.cardDescription}>
{marker.description}
</Text>
</View>
</View>
})}
</Animated.ScrollView>
{/* <TouchableOpacity onPress={this.getLocationHandler} style={styles.iconContainer}>
<Icon name="md-locate" size={30} color="blue"/>
</TouchableOpacity> */}
</View>
);
For the StyleSheet:
const styles = StyleSheet.create({
container: {
alignItems: 'center',
},
map: {
height: '100%',
width: '100%'
},
iconContainer: {
position: 'absolute',
top: 60,
right: 15,
zIndex: 1
},
//--- Style for Marker -----//
markerWrap: {
alignItems: 'center',
justifyContent: 'center',
},
marker: {
width: 8,
height: 8,
borderRadius: 4,
backgroundColor: "rgba(130,4,150, 0.9)",
},
ring: {
width: 24,
height: 24,
borderRadius: 12,
backgroundColor: "rgba(130,4,150, 0.3)",
position: "absolute",
borderWidth: 1,
borderColor: "rgba(130,4,150, 0.5)",
},
scrollView: {
position: "absolute",
bottom: 30,
left: 0,
right: 0,
paddingVertical: 10,
},
endPadding: {
paddingRight: width - CARD_WIDTH,
},
card: {
padding: 10,
elevation: 2,
backgroundColor: "#FFF",
marginHorizontal: 10,
shadowColor: "#000",
shadowRadius: 5,
shadowOpacity: 0.3,
shadowOffset: { x: 2, y: -2 },
height: CARD_HEIGHT,
width: CARD_WIDTH,
overflow: "hidden",
},
cardImage: {
flex: 3,
width: "100%",
height: "100%",
alignSelf: "center",
},
textContent: {
flex: 1,
},
cardTitle: {
fontSize: 12,
marginTop: 5,
fontWeight: "bold",
},
cardDescription: {
fontSize: 12,
color: "#444",
}
})
Try using these styles:
container: {
flex: 1
},
map: {
flex: 1,
...StyleSheet.absoluteFillObject,
top: 0, left: 0, right: 0, bottom: 25
},
scrollView: { // Or for a simple View or Card
// ...
position: 'absolute',
bottom: 0,
zIndex: 100,
}
I am trying to place an Avatar element over my TextInput so that it will look like a conventional search bar, but it doesn't go over the TextInput Please isn't it working, or can another better method of putting the search icon over the TextInput be suggested, Thank you
import { Avatar } from 'react-native-elements';
import FontAwesome
from './node_modules/#expo/vector-icons/fonts/FontAwesome.ttf';
import MaterialIcons
from './node_modules/#expo/vector-icons/fonts/MaterialIcons.ttf';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {timePassed: false};
}
state = {
fontLoaded: false
};
async componentWillMount() {
try {
await Font.loadAsync({
FontAwesome,
MaterialIcons
});
this.setState({ fontLoaded: true });
} catch (error) {
console.log('error loading icon fonts', error);
}
}
render() {
setTimeout(() => {
this.setState({timePassed: true})
}, 4000);
if (!this.state.timePassed) {
return <Splash/>;
} else {
return (
<View style={BackStyles.container}>
<Avatar style={BackStyles.searchIcon} icon={{ name: 'search', size: 25, }}/>
<TextInput placeholder="Search for your herbs.."
underlineColorAndroid={'transparent'} style={BackStyles.textBox}
/></View>
);
}
}
}
const BackStyles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'flex-start',
alignSelf: 'stretch',
flex: 1,
backgroundColor: '#E2E2E2',
marginTop: 20,
// width: '100%'
},
textBox: {
flex: 1,
height: 45,
padding: 4,
// textAlignVertical: 'top',
paddingLeft: 20,
// marginRight: 5,
flexGrow: 1,
// fontSize: 18,
color: '#000',
backgroundColor: '#fff',
// textAlign: 'center'
},
searchIcon:{
position: 'absolute',
alignSelf: 'stretch',
height: 45,
flex: 1,
top: 50,
flexGrow: 1,
padding: 4
}
});
You can use Flexbox's justifyContent feature to force the TextInput to the left and the search icon to the right. If you put a border on the container and not the TextInput, the entire thing will appear as there is a search icon fixed onto the right of the TextInput, when, in reality, they are two separate components.
// styles
const styles = StyleSheet.create({
searchBox: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
borderWidth: 1,
borderColor: 'black',
},
});
// the component
<View style={styles.searchBox}>
<TextInput ...yourprops />
<Avatar ...yourprops />
</View>
If you want to read more about justifyContent and how godly Flexbox is, you should check out Chris Coyier's Flexbox guide.
I am making an simple iOS app using react-native and having some problems with navigator I delcared two views but got nothing rendered but a blank page
The followed is my code:
'use strict';
var Dimensions = require('Dimensions');
import React, {
Component,
StyleSheet,
MapView,
Text,
View,
Animated,
Navigator,
TouchableHighlight,
TouchableOpacity,
Image,
PropTypes,
Modal
} from 'react-native';
var {
height: deviceHeight,
width: deviceWidth
} = Dimensions.get('window');
var BasicConfig = Navigator.SceneConfigs.FloatFromLeft;
var CustomLeftToRightGesture = Object.assign({}, BasicConfig.gestures.pop, {
snapVelocity:8,
edgeHitWidth: deviceWidth,
});
var CustomSceneConfig = Object.assign({}, BasicConfig, {
springTension: 100,
springFriction: 1,
gestures:{
pop:CustomLeftToRightGesture,
}
});
var MainMap = React.createClass({
watchID: (null: ?number),
getInitialState: function() {
return {
latitude: 0,
longitude: 0,
initialPosition: 'unknown',
lastPosition: 'unknown',
};
},
openMenu(){
this.props.navigator.push({id: 2,});
},
render: function(){
console.log("123456")
return (
<View style = {styles.container}>
<View style = {styles.TopBarContainer}>
<TouchableOpacity style={styles.toolbarButton}
onPress={this.openMenu}>
<Text style={styles.toolbarButtonText}>{"MENU"}</Text>
</TouchableOpacity>
<Text style={styles.toolbarTitle}>{"Simply Park"}</Text>
<TouchableOpacity style={styles.toolbarButton}
onPress={this.openSeacrh}>
<Image source={require('image!search')} style={styles.toolbarSeacrhImage}/>
</TouchableOpacity>
</View>
<MapView
style={styles.map}
showsUserLocation={true}
followUserLocation={true}
/>
</View>
);
}
});
var ControlPanel = React.createClass({
_handlePress(){
this.props.navigator.pop();
},
render: function() {
console.log("paaaaaaaaanel")
return (
<View style={styles.container}>
<Text style={styles.controlText}>{"Control Panel"}</Text>
<TouchableOpacity style={styles.button} onPress={this._handlePress}>
<Text>{"Close Drawer"}</Text>
</TouchableOpacity>
</View>
)
}
});
var Main = React.createClass({
_renderScene(route, navigator){
if (route.id === 2){
console.log("id is 2");
return <ControlPanel navigator={navigator} />
}else{
console.log("id is 1");
return <MainMap navigator={navigator} />
}
},
_configureScene(route){
return CustomSceneConfig;
},
render(){
console.log("hihihihihihi");
return(
<Navigator
initialRoute={{
id: 1,
}}
renderScene = {this._renderScene}
configureScene = {this._configureScene}
/>
);
}
});
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
justifyContent: 'flex-end',
alignItems: 'center',
},
TopBarContainer:{
position: 'absolute',
backgroundColor: '#3b5998',
top: 0,
left: 0,
right: 0,
bottom: 580,
flexDirection:'row'
},
toolbarButton:{
paddingTop:35,
paddingLeft: 7,
width: 50,
alignItems:'center'
},
toolbarButtonText:{
paddingTop: 5,
color:'#fff',
fontWeight: 'normal',
fontSize: 13,
},
toolbarTitle:{
paddingTop:35,
color:'#fff',
textAlign:'center',
fontWeight:'bold',
fontSize: 18,
flex:1,
},
toolbarSeacrhImage:{
paddingTop: 20,
width: 18,
height:18,
},
map: {
position: 'absolute',
top: 70,
left: 0,
right: 0,
bottom: 0,
},
controlText: {
color: 'white',
},
button: {
backgroundColor: 'white',
borderWidth: 1,
borderColor: 'black',
padding: 10,
bottom: 500,
},
});
module.exports = Main;
I put console.log() for debug use. The debug texts displayed properly on the debug xcode dubug console however the MainMap view is not displayed. I am wondering if this is a problem with my view styles but no clue after several tries.
An answer to my question is I am using modal to transit between previous scene to this scene, and removed justifyContent: 'flex-end', alignItems: 'center' from the previous scene where this view is rendered。
Try adding style={{flex: 1}} to the navigator.
<Navigator
style={{ flex: 1 }}
initialRoute={{
id: 1,
}}
renderScene = {this._renderScene}
configureScene = {this._configureScene}
/>