How to create an onPress event that dismisses a callout? - react-native

I'm building a gig guide in React Native, using react native maps.
Users are presented with a Map with markers indicating the location of gig. When these markers are tapped, a callout pops up with gig information:
When the user taps the "Next day's gigs" button, the map is rendered with markers showing the upcoming day's gigs. When the user hits this button, I want to make sure that any open callouts on the current day are dismissed when the button is hit. Any suggestions on how to do this?
Here's the code from the component rendering the map:
GigMap.js
import { useState, useMemo } from "react";
import {
StyleSheet,
Text,
View,
Pressable,
Image,
TouchableOpacity,
} from "react-native";
import MapView from "react-native-maps";
import { Marker, Callout } from "react-native-maps";
import CalloutView from "./CalloutView";
import { mapStyle } from "../util/mapStyle";
import { useGigs } from "../hooks/useGigs";
import { AntDesign } from "#expo/vector-icons";
const GigMap = ({ navigation }) => {
const [selectedDateMs, setSelectedDateMs] = useState(Date.now());
const gigs = useGigs();
//generates current date in format DD/MM/YYYY
const selectedDateString = useMemo(() => {
const date = new Date(selectedDateMs);
const dateToString = date.toString().slice(0,15)
return dateToString // returns in form 'Tue Dec 20 2022'
}, [selectedDateMs]);
//Filtering through gigs to return only current day's gigs
const gigsToday = gigs.filter((gig) => {
const gigDate1 = new Date(gig.dateAndTime.seconds*1000)
const gigDate2 = gigDate1.toString().slice(0,15) //return form 'Tue Dec 20 2022'
return gigDate2 === selectedDateString
})
//increments date by amount
const addDays = (amount) => {
setSelectedDateMs((curr) => curr + 1000 * 60 * 60 * 24 * amount);
};
return (
<View style={styles.container}>
<Text style={styles.headerText}>{`Gigs on ${selectedDateString}`}</Text>
<View style={styles.imageText}>
<Text style = {styles.subHeader}>Tap on</Text>
<Image
style={styles.image}
source={require("../assets/Icon_Gold_48x48.png")}
/>
<Text style = {styles.subHeader}> to see gig info</Text>
</View>
<MapView
initialRegion={{
latitude: -41.29416,
longitude: 174.77782,
latitudeDelta: 0.03,
longitudeDelta: 0.03,
}}
style={styles.map}
customMapStyle={mapStyle}
>
{gigsToday.map((gig, i) => (
<Marker
key={i}
coordinate={{
latitude: gig.location.latitude,
longitude: gig.location.longitude,
}}
image={require("../assets/Icon_Gold_48x48.png")}
description = 'test'
>
<Callout
style={styles.callout}
tooltip={true}
onPress={() =>
navigation.navigate("GigDetails", {
venue: gig.venue,
date: selectedDateString,
gigName: gig.gigName,
image: gig.image
})
}
>
<CalloutView
venue={gig.venue}
gigName={gig.gigName}
genre = {gig.genre}
/>
</Callout>
</Marker>
))}
</MapView>
<View style={styles.buttonOptions}>
<TouchableOpacity onPress={() => addDays(-1)} style = {styles.touchable}>
<AntDesign name="caretleft" size={36} color="#778899" />
<Text style = {{fontFamily:'Helvetica-Neue', color:'#778899'}}>Previous day's gigs</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => addDays(1)} style = {styles.touchable}>
<AntDesign name="caretright" size={36} color="#778899" />
<Text style = {{fontFamily:'Helvetica-Neue',color:'#778899'}}>Next day's gigs</Text>
</TouchableOpacity>
</View>
</View>
);
};
CalloutView.js
import { StyleSheet, Text, View } from 'react-native';
const CalloutView = ({ venue,gigName,genre }) => {
const title = gigName.substring(0,25)
return (
<View style = {styles.container}>
<Text style = {styles.header} >{`${title}`}</Text>
<Text style = {styles.details}>{`${venue} | ${genre}`}</Text>
<Text style = {styles.button}>Tap to see details</Text>
</View>
);
}

Try this
import React from "react";
import { IMAGES } from "theme";
import { View, Text, StyleSheet } from "react-native";
import MapView, { PROVIDER_GOOGLE, Marker, Callout } from "react-native-maps";
const GigMap = () => {
return (
<MapView
provider={PROVIDER_GOOGLE} // remove if not using Google Maps
style={styles.map}
region={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.015,
longitudeDelta: 0.0121,
}}
>
<Marker
coordinate={{
latitude: 37.78825,
longitude: -122.4324,
}}
image={IMAGES.MAP_MARKER}
title="Test Title"
description="This is the test description"
>
<Callout tooltip>
<View>
<View style={styles.bubble}>
<Text numberOfLines={1} style={styles.name}>Gig Title</Text>
<Text>A Gig description</Text>
</View>
<View style={styles.arrowBorder} />
<View style={styles.arrow} />
</View>
</Callout>
</Marker>
</MapView>
);
};
export default GigMap;
const styles = StyleSheet.create({
map: {
height: "100%",
},
// Callout bubble
bubble: {
flexDirection: "column",
alignSelf: "flex-start",
backgroundColor: "#fff",
borderRadius: 6,
borderColor: "#ccc",
borderWidth: 0.5,
padding: 15,
width: 150,
},
// Arrow below the bubble
arrow: {
backgroundColor: "transparent",
borderColor: "transparent",
borderTopColor: "#fff",
borderWidth: 16,
alignSelf: "center",
marginTop: -32,
},
arrowBorder: {
backgroundColor: "transparent",
borderColor: "transparent",
borderTopColor: "#007a87",
borderWidth: 16,
alignSelf: "center",
marginTop: -0.5,
},
// Gig Title
name: {
fontSize: 16,
marginBottom: 5,
},
// Gig button
button: {
width: "40%",
height: 80,
},
});
Here is some of the Suggestions for you
use numberOfLines for title
use Dayjs instead of manually doing date.toString().slice(0,15) also it will be solve your all dates and time related problems

Related

Trying to create editable polygons with react-native-maps

Ive been trying to create a editable polygon with react-native-maps to basically create a user editable geofence. Using draggable markers to pinpoint the polygons corners. I thought this work, but upon dragging on of the markers, this error and I cannot understand why.
Any help is greatly appreciated!
import React, { useState } from 'react';
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import MapView, { Polyline, Marker, Polygon } from 'react-native-maps';
import { RFValue } from 'react-native-responsive-fontsize';
export default function App() {
const [region, setRegion] = useState({
latitude: 'null',
longitude: 'null',
});
const [Cords, setCords] = useState('null')
const [firstLat, setFirstLat] = useState()
const [firstLong, setFirstLong] = useState()
const [secondLat, setSecondLat] = useState()
const [secondLong, setSecondLong] = useState()
const [thirdLat, setThirdLat] = useState()
const [thirdLong, setThirdLong] = useState()
const [mapPressLat, setMapPressLat] = useState()
const [mapPressLong, setMapPressLong] = useState()
const polyList = [
{ latitude: firstLat, longitude: firstLong },
{ latitude: secondLat, longitude: secondLong },
{ latitude: thirdLat, longitude: thirdLong }
]
return (
<View style={styles.container}>
<StatusBar style="auto" />
<Text>{Cords}</Text>
<Text>{mapPressLat} | {mapPressLong}</Text>
<Text>{firstLat} | {firstLong}</Text>
<Text>{secondLat} | {secondLong}</Text>
<Text>{thirdLat} | {thirdLong}</Text>
<MapView style={{ height: '40%', width: '90%' }}
onRegionChangeComplete={(region) => setRegion(region)}
initialRegion={{
latitude: 50.75895213387573,
longitude: -1.2904538133239536,
latitudeDelta: 0.01,
longitudeDelta: 0.01,
}}
onPress={e => setMapPressLat([e.nativeEvent.coordinate.latitude]) + setMapPressLong([e.nativeEvent.coordinate.longitude])}
>
<View style={{ backgroundColor: 'black', height: RFValue(5), width: RFValue(5), borderRadius: 100, position: 'absolute', top: '49%', left: '48.7%' }} />
<Polyline
coordinates={polyList}
fillColor='#A3BE80'
strokeWidth={3}
tappable={true}
onPress={() => alert('yesy')}
/>
<Marker
key={'first'}
onDrag={a => setFirstLat([a.nativeEvent.coordinate.latitude]) + setFirstLong([a.nativeEvent.coordinate.longitude])}
coordinate={{
latitude: 50.75895213387573 + 0.001,
longitude: -1.2904538133239536 + 0.001
}}
draggable={true}
/>
<Marker
key={'sencond'}
onDrag={b => setSecondLat([b.nativeEvent.coordinate.latitude]) + setSecondLong([b.nativeEvent.coordinate.longitude])}
coordinate={{
latitude: 50.75895213387573 - 0.001,
longitude: -1.2904538133239536
}}
draggable={true}
/>
<Marker
key={'third'}
onDrag={c => setThirdLat([c.nativeEvent.coordinate.latitude]) + setThirdLong([c.nativeEvent.coordinate.longitude])}
coordinate={{
latitude: 50.75895213387573 + 0.001,
longitude: -1.2904538133239536 - 0.001
}}
draggable={true}
/>
</MapView>
<Text>Current latitude: {region.latitude}</Text>
<Text>Current longitude: {region.longitude}</Text>
<TouchableOpacity onPress={() => setCords([region.latitude] + ' ' + [region.longitude])} style={{ marginTop: 30, backgroundColor: 'darkcyan', borderRadius: 6 }}>
<Text style={{ color: 'white', padding: 15 }} >Cords</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ffffff',
alignItems: 'center',
justifyContent: 'center',
},
});
If anyone has the same issue as me.
I, for some stupid reason, put the marker's lat and long values in an array...
Old
onDrag={a => setFirstLat([a.nativeEvent.coordinate.latitude]) + setFirstLong([a.nativeEvent.coordinate.longitude])}
New
onDrag={a => setFirstLat(a.nativeEvent.coordinate.latitude) + setFirstLong(a.nativeEvent.coordinate.longitude)}
I hope this helps!

react native maps callout content is overflowed

i got a problem with react native maps callout , each marker update its position every 10 seconds, callout starts hidden but, when you press the marker it open the callout and keep it open each new position update, but sometimes the callout content is places out of bounds of the callout container.
image:
callout content not fit in it container
code:
`
import * as React from "react"
import { Text, View,StyleSheet } from 'react-native';
import { Marker,Callout } from 'react-native-maps';
import Svg, { Path, Circle } from "react-native-svg";
import moment from "moment";
import "moment/min/locales.min.js";
import { FontAwesome, FontAwesome5 } from '#expo/vector-icons';
import useStatusImei from "../../hooks/useStatusImei";
import { fecha,timediff } from "../../utils/App";
import {MapaContext} from "../../context/MapaContextProvider";
moment.locale("es");
const Icon = ({ignicion,velocidad,vel_max,grados,color}) =>{
return ignicion == 1 && velocidad > 1 ?
(
<Svg width={60} height={60} xmlns="http://www.w3.org/2000/svg" style={{ transform: [{ rotate: `${grados}deg` }] }}>
<Path
style={[styles.ign,{ stroke: velocidad >= vel_max ? '#ed6b75' : "#fff", fill: color }]}
d="m38.828 45.578 14.599 7.815-7.085-16.295a17.412 17.412 0 0 0 1.338-6.704c0-7.495-4.729-13.869-11.36-16.348L30.213 0l-6.107 14.046c-6.63 2.479-11.36 8.853-11.36 16.348 0 2.376.479 4.639 1.338 6.704L7 53.393l14.599-7.815a17.37 17.37 0 0 0 8.614 2.283c3.136 0 6.071-.837 8.615-2.283z"
/>
</Svg>
)
:
(
<Svg width={40} height={40} xmlns="http://www.w3.org/2000/svg">
<Circle style={[styles.off,{fill: color}]} cx={20} cy={20} r={18} />
</Svg>
)
}
const InfoWindow = ({numero,marca,info,color,time_color,fecha_hora_gps, ignicion,velocidad,vel_max,fecha_hora_ultimo_encendido,odometro, odometro_ultimo_encendido, fecha_hora_inicio_relenti,fecha_hora_ultimo_apagado,fecha_hora_fin_ultimo_viaje,fecha_hora_inicio_ultimo_viaje,odometro_fin_ultimo_viaje,odometro_inicio_ultimo_viaje}) =>{
let informacion, detalle,color_velocidad;
if( ignicion == 1){
if(Math.floor(velocidad)>1){//en movimiento
if( Math.floor(velocidad) < vel_max && Math.floor(velocidad) >=( vel_max - 5 )){
color_velocidad= '#F1C40F';
}else if(Math.floor(velocidad)>=vel_max){
color_velocidad= '#ed6b75';
detalle = (<Text style={{color:color_velocidad,fontWeight:'500'}}>¡Exceso de Velocidad!</Text>);
}else {
color_velocidad = '#26C281';
detalle = (
<View style={styles.info}>
<FontAwesome5 name="code-branch" size={15} color="#5867dd" />
<Text style={styles.text}> {timediff((moment().unix(fecha_hora_gps) - moment(fecha_hora_ultimo_encendido).unix()),0)} </Text>
<Text style={styles.text}> {( ( odometro - odometro_ultimo_encendido) / 1000 ).toFixed(1)}kms</Text>
</View>
);
}
informacion = (
<View>
<View><Text style={[styles.vel,{color:color_velocidad}]}>{ Math.round(velocidad)} kms/h</Text></View>
<View>
{detalle}
</View>
</View>
);
}else{//en relenti
informacion = (<View><Text style={{color,fontWeight:'500'}}>En relentí {timediff((moment().unix() - moment(fecha_hora_inicio_relenti).unix()),0)}</Text></View>);
}
}else{
informacion = (
<View>
<View><Text style={styles.text}>Apagado desde {moment(fecha_hora_ultimo_apagado).calendar()}</Text></View>
<View style={styles.info}>
<FontAwesome5 name="code-branch" size={15} color="#5867dd" />
<Text style={styles.text}> {timediff((moment(fecha_hora_fin_ultimo_viaje).unix() - moment(fecha_hora_inicio_ultimo_viaje).unix()),0)} </Text>
<Text style={styles.text}> {((odometro_fin_ultimo_viaje - odometro_inicio_ultimo_viaje) / 1000 ).toFixed(1)} kms </Text>
</View>
</View>
);
}
//
return (
<Callout>
<View style={styles.calloutContainer} >
<Text><Text style={styles.bold}>{numero}</Text> <Text style={styles.text}>{marca}</Text></Text>
{informacion}
<Text style={[styles.text,{fontSize:12}]} ><FontAwesome name="cloud-upload" size={14} color={time_color} /> {fecha(fecha_hora_gps,5)}</Text>
</View>
</Callout>);
}
const Unidad = ({ unidad,aforos = false }) => {
const {setUnidadFocus,unidad_focus} = React.useContext(MapaContext);
const item = useStatusImei({...unidad},aforos);
const markerRef = React.useRef(undefined);
const handleCallout = ()=>{
markerRef.current.showCallout();
setUnidadFocus({imei:item.imei,fecha_hora_gps:item.fecha_hora_gps,marker:markerRef});
}
React.useEffect(()=>{
if(unidad_focus && unidad_focus.imei == item.imei && !unidad_focus.marker){
handleCallout()
}
},[markerRef.current]);
let fz =12;
if (item && item.latitud && item.longitud) {
if(item.numero.length > 6)
fz = 9
if(item.numero.length > 5)
fz = 10
if(item.numero.length > 4)
fz = 11
return (
<Marker
ref = {(ref)=>{markerRef.current = ref}}
key={item.imei}
coordinate={{ latitude: item.latitud, longitude: item.longitud }}
anchor={{ x: 0.5, y: 0.5 }}
style={styles.marker}
tracksViewChanges={false}
flat={true}
onPress={()=>{handleCallout()}}
>
<Icon {...item} />
<Text style={[styles.markerLabel,{fontSize:fz}]}>{item.numero}</Text>
<InfoWindow {...item} />
</Marker>
);
}
return null;
};
const styles = StyleSheet.create({
marker:{ justifyContent: "center", alignItems: "center" },
calloutContainer: {
width:250,
height:100,
justifyContent:'center',
alignItems: 'center',
padding:5
},
bold:{
fontWeight:'600',
color:"#5867dd",
fontSize:16
},
text:{
color:'#57585a'
},
markerLabel: { color: '#FFFFFF', position: 'absolute', fontSize: 13, fontWeight: '400' },
info:{flexDirection:"row",alignItems:'center',justifyContent:'space-around'},
off:{ strokeWidth: 4, strokeOpacity: 0.5, stroke: "#fff", fillRule: "nonzero" },
ign:{strokeWidth: 6, strokeOpacity: 0.5, fillRule: "nonzero"},
vel: {fontWeight:'500',textAlign:'center'}
})
export default Unidad
`
I read along this forum, changed the components structure, set fixed width and height callout container and keep it with basic text but in each change the problem keep apearing only sometimes, in expo app and in production app.

How to update coordinates of "showsUserLocation" marker in react native maps?

The (blue dot) marker doesn't response to user movements. I can get the current location of the user, but I can't figure how to update the location of the blue marker. I can use component and update its location, but I need to use blue dot marker because I need to have geolocator button on the top right hand side.
import React, { useState, useEffect } from "react";
import * as Location from "expo-location";
import { Dimensions, StyleSheet, Text, View } from "react-native";
import MapView, { Callout, Circle, Marker } from "react-native-maps";
export default function App() {
const [location, setLocation] = useState(null);
const [errorMsg, setErrorMsg] = useState(null);
useEffect(() => {
(async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") {
setErrorMsg("Permission to access location was denied");
return;
}
// let location = await Location.getCurrentPositionAsync({});
let watchID = await Location.watchPositionAsync(
{
accuracy: Location.Accuracy.High,
timeInterval: 500,
distanceInterval: 0
},
position => {
setLocation(position);
}
);
})();
}, []);
let text = "Waiting..";
if (errorMsg) {
text = errorMsg;
} else if (location) {
text = JSON.stringify(location);
}
return (
<View style={{ marginTop: 50, flex: 1 }}>
{location && (
<>
<Text style={styles.paragraph}>
{"lat:" + location.coords.latitude}
</Text>
<Text style={styles.paragraph}>
{"long:" + location.coords.longitude}
</Text>
<Text style={styles.paragraph}>
{"acurracy:" + location.coords.accuracy}
</Text>
</>
)}
<MapView
style={styles.map}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421
}}
provider="google"
showsUserLocation={true}
followsUserLocation={true}
// scrollEnabled={false}
>
{location && (
<Marker
coordinate={{
latitude: location.coords.latitude,
longitude: location.coords.longitude
}}
></Marker>
)}
</MapView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center"
},
map: {
width: Dimensions.get("window").width,
height: Dimensions.get("window").height
}
});
Thanks!
Adding followsUserLocation={true} props fixed my problem.

How to expand card onPress - React Native

I am trying to make a ticket app that allows for people to create tickets based on work that needs done. Right now, I need help with the expandable view for each ticket card. What I'm wanting is when a user presses on a specific card, it will expand the view and provide more details for only that card. What it is currently doing is expanding the view for every ticket card in the list. I'm new to React Native and trying my best, but nothing has worked so far.
Here is my parent which is called Home:
import React, {useState, useEffect} from 'react';
import {styles, Colors} from '../components/styles';
import { SafeAreaView } from 'react-native';
import Ticket from '../components/Ticket';
const data = [
{
name: 'Josh Groban',
subject: 'U-Joint',
desc: 'The bolt that is meant to hold the u-joint in place has the head broken off from it. See attached picture.',
assignee: 'John Doe',
assigneeConfirmedComplete: 'NA',
dateReported: 'Tue Mar 8, 2022',
vehicle: 'Truck 1',
media: '',
key: '1',
isShowing: false
},
// code removed for brevity
];
const Home = ({navigation}) => {
const [ticketList, setTicketList] = useState(data);
const getTickets = () => {
setTicketList(data);
}
useEffect(() => {
getTickets();
}, []);
return (
<SafeAreaView style={styles.HomeContainer}>
<Ticket
ticketList={ticketList}
setTicketList={setTicketList}
/>
</SafeAreaView>
)
};
export default Home;
And here is the main component that has all of the ticket card configurations:
import React, {useState, useEffect} from 'react';
import {Text, FlatList, View, SafeAreaView, Button, Image, TouchableOpacity } from 'react-native';
import {styles, Colors} from './styles';
import {Ionicons} from '#expo/vector-icons';
const Ticket = ({ticketList, setTicketList}) => {
const defaultImage = 'https://airbnb-clone-prexel-images.s3.amazonaws.com/genericAvatar.png';
const [isComplete, setIsComplete] = useState(false);
const [show, setShow] = useState(false);
const showContent = (data) => {
const isShowing = {...data, isShowing}
if (isShowing)
setShow(!show);
}
const completeTask = () => {
setIsComplete(!isComplete);
}
return (
<SafeAreaView style={{flex: 1}}>
<FlatList showsVerticalScrollIndicator={false}
data={ticketList}
renderItem={(data) => {
return (
<>
<TouchableOpacity key={data.item.key} onPress={() => showContent(data.item.isShowing = true)}>
<View style={styles.TicketCard}>
<Image
style={styles.TicketCardImage}
source={{uri: defaultImage}}
/>
<View style={styles.TicketCardInner}>
<Text style={styles.TicketCardName}>{data.item.vehicle}</Text>
<Text style={styles.TicketCardSubject}>
{data.item.subject}
</Text>
</View>
<TouchableOpacity>
<Ionicons
name='ellipsis-horizontal-circle'
color={Colors.brand}
size={50}
style={styles.TicketCardImage}
/>
</TouchableOpacity>
<TouchableOpacity onPress={completeTask}>
<Ionicons
name={isComplete ? 'checkbox-outline' : 'square-outline'}
color={Colors.brand}
size={50}
style={styles.TicketCardButton}
/>
</TouchableOpacity>
</View>
<View style={styles.TicketCardExpand}>
<Text>
{show &&
(<View style={{padding: 10}}>
<Text style={styles.TicketCardDesc}>
{data.item.desc}
</Text>
<Text style={{padding: 5}}>
Reported by: {data.item.name}
</Text>
<Text style={{padding: 5}}>
Reported: {data.item.dateReported}
</Text>
{isComplete && (
<Text style={{padding: 5}}>
Confirmed Completion: {data.item.assigneeConfirmedComplete}
</Text>
)}
</View>
)}
</Text>
</View>
</TouchableOpacity>
</>
)}}
/>
</SafeAreaView>
)
};
export default Ticket;
Lastly, here are the styles that i'm using:
import {StyleSheet } from "react-native";
import { backgroundColor } from "react-native/Libraries/Components/View/ReactNativeStyleAttributes";
// colors
export const Colors = {
bg: '#eee',
primary: '#fff',
secondary: '#e5e7eb',
tertiary: '#1f2937',
darkLight: '#9ca3f9',
brand: '#1d48f9',
green: '#10b981',
red: '#ff2222',
black: '#000',
dark: '#222',
darkFont: '#bbb',
gray: '#888'
}
export const styles = StyleSheet.create({
HomeContainer: {
flex: 1,
paddingBottom: 0,
backgroundColor: Colors.bg,
},
TicketCard : {
padding: 10,
justifyContent: 'space-between',
borderColor: Colors.red,
backgroundColor: Colors.primary,
marginTop: 15,
flexDirection: 'row',
},
TicketCardExpand: {
justifyContent: 'space-between',
backgroundColor: Colors.primary,
},
TicketCardImage: {
width: 60,
height: 60,
borderRadius: 30
},
TicketCardName:{
fontSize: 17,
fontWeight: 'bold'
},
TicketCardSubject: {
fontSize: 16,
paddingBottom: 5
},
TicketCardDesc: {
fontSize: 14,
flexWrap: 'wrap',
},
TicketCardInner: {
flexDirection: "column",
width: 100
},
TicketCardButton: {
height: 50,
}
});
Any help is greatly appreciated!
Create a Ticket component with its own useState.
const Ticket = (data) => {
const [isOpen, setIsOpen] = useState(false);
const handlePress = () => {
setIsOpen(!isOpen);
}
return (
<TouchableOpacity
onPress={handlePress}
>
// data.item if you use a list, otherwise just data
<YourBasicInformation data={data.item} />
{isOpen && <YourDetailedInformation data={data.item} />}
</TouchableOpacity>
)
}
Render one Ticket for every dataset you have.
<List
style={styles.list}
data={yourDataArray}
renderItem={Ticket}
/>
If you don't want to use a List, map will do the job.
{yourDataArray.map((data) => <Ticket data={data} />)}
instead of setting show to true or false you can set it to something unique to each card like
setShow(card.key or card.id or smth)
and then you can conditionally render details based on that like
{show == card.key && <CardDetails>}
or you can make an array to keep track of open cards
setShow([...show,card.id])
{show.includes(card.id) && <CardDetails>}
//to remove
setShow(show.filter((id)=>id!=card.id))

How to dsplay coordinates of GPS in a Mapview?

I need your help to know how to display GPS coordinates in a MapView.
I want to track a person's location from gps coordinates (longitude and latitude).
I tried too much to recover the coordinates in a MapView but I did not arrive to do it, I am blocked.
So, I get the coordinates from a web service and I display them in a TextView.
This is my code:
import React, { Component } from 'react';
import { Constants, Location, Permissions } from 'expo';
import { Card } from 'react-native-paper';
import { Polyline } from 'react-native-maps';
import {
StyleSheet,
Platform,
View,
ActivityIndicator,
FlatList,
Text,
Image,
TouchableOpacity,
Alert,
YellowBox,
AppRegistry,
Button,
} from 'react-native';
export default class gps extends Component {
static navigationOptions = ({ navigation }) => {
return {
title: 'Suivi GPS',
headerStyle: {
backgroundColor: 'transparent',
},
headerTitleStyle: {
fontWeight: 'bold',
color: '#000',
zIndex: 1,
fontSize: 18,
lineHeight: 25,
fontFamily: 'monospace',
},
};
}
state = {
mapRegion: null,
dat: '',
};
GetItem() {}
componentDidMount() {
this.webCall();
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: 0.5,
width: '100%',
backgroundColor: '#000',
}}
/>
); //
};
webCall = () => {
return fetch('http://first-ontheweb.com/onLineSenior/pos.php')
.then(response => response.json())
.then(responseJson => {
this.setState({
isLoading: false,
dataSource: responseJson,
});
})
.catch(error => {
console.error(error);
});
};
render() {
if (this.state.isLoading) {
return (
<View
style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" />
</View>
);
}
return (
<View style={styles.map}>
<FlatList
data={this.state.dataSource}
ItemSeparatorComponent={this.FlatListItemSeparator}
renderItem={({ item }) => (
<View>
<Text style={styles.textView}>Longitude :</Text>
<Text style={styles.textView}>{item.longitude}</Text>
<Text style={styles.textView}>Latitude :</Text>
<Text style={styles.textView}>{item.latitude}</Text>
</View>
)}
keyExtractor={(index) => index.toString()}
/>
</View>
);
}
}
const styles = StyleSheet.create({
map: {
...StyleSheet.absoluteFillObject,
},
});
So, I want to display the GPS coordinates in a MapView.
Thanks.
You can do something like this:
first import the mapView:
import MapView from "react-native-maps";
Then:
state = {
focusedLocation: {
latitude: 37.7900352, //or your coordinates
longitude: -122.4013726, //or your coordinates
latitudeDelta: 0.0122,
longitudeDelta:
Dimensions.get("window").width /
Dimensions.get("window").height *
0.0122
}
};
render() {
let marker = null;
if (this.state.locationChosen) {
marker = <MapView.Marker coordinate={this.state.focusedLocation} />;
}
return (
let marker = <MapView.Marker coordinate={this.state.focusedLocation} />;
<View style={styles.container}>
<MapView
initialRegion={this.state.focusedLocation}
style={//map style here}
>
{marker}
</MapView>
</View>
);
}
you need to install react-native-maps package than
import MapView from 'react-native-maps';
Rendering a Map with an initial region
<MapView
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
/>
Using a MapView while controlling the region as state
getInitialState() {
return {
region: {
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
},
};
}
onRegionChange(region) {
this.setState({ region });
}
render() {
return (
<MapView
region={this.state.region}
onRegionChange={this.onRegionChange}
/>
);
}
Rendering a list of markers on a map
import { Marker } from 'react-native-maps';
<MapView
region={this.state.region}
onRegionChange={this.onRegionChange}
>
{this.state.markers.map(marker => (
<Marker
coordinate={marker.latlng}
title={marker.title}
description={marker.description}
/>
))}
</MapView>
you can find more in the documention here.
https://github.com/react-native-community/react-native-maps