i am working with google maps on android studio, in which i draw polygon on map. till this everything going great but now i wanted to store this polygon to sqlite database and then retrieve this data to listView. now i don't understand how to implement this in my code. if anyone have any idea about this then please save me.
here is my code where i draw polygon:
#Override
public void onMapReady(final GoogleMap googleMap) {
final List<LatLng> latLngList = new ArrayList<>(); // list of polygons
final List<Marker> markerList = new ArrayList<>();
mMap = googleMap;
LatLng center = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
final MarkerOptions markerOptions = new MarkerOptions().position(center).title(center.latitude + ":" + center.longitude);
mMap.clear();
googleMap.animateCamera(CameraUpdateFactory.newLatLng(center));
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(center, 18));
googleMap.addMarker(markerOptions);
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(final LatLng latLng) {
int height = 50;
int width = 30;
BitmapDrawable bitmapdraw = (BitmapDrawable)getResources().getDrawable(R.mipmap.marker);
Bitmap b = bitmapdraw.getBitmap();
Bitmap smallMarker = Bitmap.createScaledBitmap(b, width, height, false);
/*Marker marker = googleMap.addMarker(markerOptions);*/
Marker marker = mMap.addMarker(new MarkerOptions().position(latLng).draggable(true).icon(BitmapDescriptorFactory.fromBitmap(smallMarker)));
markerList.add(marker);
latLngList.add(latLng);
drawPolygon(latLngList);
polygon.setClickable(true);
}
});
mMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
#Override
public void onMapLongClick(LatLng latLng) {
polygon.remove();
/*marker.remove();
markerList.remove(marker);*/
}
});
}
private void drawPolygon(List<LatLng> latLngList) {
if (polygon != null) {
polygon.remove();
}
PolygonOptions polygonOptions = new PolygonOptions();
polygonOptions.fillColor(0x7F228B22);
polygonOptions.strokeColor(Color.GREEN);
polygonOptions.strokeWidth(5);
polygonOptions.addAll(latLngList);
polygon = mMap.addPolygon(polygonOptions);
}
my listview will look like [![this][1]][1]
You could save principal attributes you want. For example... in my case I needed to save coordinates LatLng and camera zoom. Then you can make a custom class like this.
class CustomLatLng : Serializable{
var latitudeList : MutableList<String> = mutableListOf()
var longitudeList : MutableList<String> = mutableListOf()
var cameraPositionLat : Double = 0.0
var cameraPositionLng : Double = 0.0
var zoomCamera : Float = 12f
fun add(latitude : Double, longitude : Double ){
latitudeList.add(latitude.toString())
longitudeList.add(longitude.toString())
}
fun clearLatLng(){
latitudeList.clear()
longitudeList.clear()
}
fun isNotEmpty(): Boolean{
return !(latitudeList.isEmpty() || longitudeList.isEmpty())
}
}
// in other place of your code put this...
const val PARA_NAME_POLYGONS = "polygons"
fun savePolygon(poligons:CustomLatLng ) {
val editor = sharedPreferences.edit()
editor.putString(PARA_NAME_POLYGONS, serializePolygon(poligons))
editor.apply()
//editor.commit()
}
fun cleanPolygon() {
val editor = sharedPreferences.edit()
editor.remove(PARA_NAME_POLYGONS)
editor.apply()
}
private fun serializePolygon(polygon: CustomLatLng): String {
val gson = Gson()
return gson.toJson(polygon)
}
fun getPolygon():CustomLatLng {
val gson = Gson()
val json = sharedPreferences.getString(PARA_NAME_POLYGONS,"").toString()
if (json.isEmpty())
return CustomLatLng()
return gson.fromJson(json,CustomLatLng::class.java)
}
wherever you have a polygon , save only data that you will need to recreate a Polygon
val customLatLng = CustomLatLng()
polygon?.points?.forEach {
customLatLng.add(it.latitude, it.longitude)
}
customLatLng.zoomCamera = 10f
savePolygon(customLatLng)
note I'm saving only data I need, You must create as many variables as you need, I hope it helps
Related
I am currently developing an application in which i want to know if a route contains a certain set of lat long coordinates. Here is my code:
public class PathActivity extends FragmentActivity implements OnMapReadyCallback, RoutingListener {
private GoogleMap mMap;
FetchLocation fetchLocation;
LatLng start;
LatLng end;
ProgressDialog pd;
List<Polyline> polylines;
private static final int[] COLORS = new int[]{R.color.gradient_dark_pink};
FirebaseFirestore firestore;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_path);
//Receiving Object From Intent
Intent rcv = getIntent();
fetchLocation = (FetchLocation) rcv.getSerializableExtra("keyFetchLocationObject2");
pd = new ProgressDialog(this);
pd.setMessage("Please Wait...");
firestore = FirebaseFirestore.getInstance();
fetchAllTrafficLights();
polylines = new ArrayList<>();
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
pd.show();
//Making a Path
start = new LatLng(fetchLocation.latitude, fetchLocation.longitude);
end = new LatLng(fetchLocation.destinationLatitude, fetchLocation.destinationLongitude);
Routing routing = new Routing.Builder()
.travelMode(Routing.TravelMode.DRIVING)
.withListener(this)
.alternativeRoutes(false)
.waypoints(start, end)
.build();
routing.execute();
}
#Override
public void onRoutingFailure(RouteException e)
{
Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
pd.dismiss();
}
#Override
public void onRoutingStart() {
}
#Override
public void onRoutingSuccess(ArrayList<Route> route, int shortestRouteIndex)
{
pd.dismiss();
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(start, 16));
if(polylines.size()>0) {
for (Polyline poly : polylines) {
poly.remove();
}
}
polylines = new ArrayList<>();
//add route(s) to the map.
for (int i = 0; i <route.size(); i++)
{
//In case of more than 5 alternative routes
int colorIndex = i % COLORS.length;
PolylineOptions polyOptions = new PolylineOptions();
polyOptions.color(getResources().getColor(COLORS[colorIndex]));
polyOptions.width(10 + i * 3);
polyOptions.addAll(route.get(i).getPoints());
Polyline polyline = mMap.addPolyline(polyOptions);
polylines.add(polyline);
Toast.makeText(getApplicationContext(),"Route "+ (i+1) +": distance - "+ route.get(i).getDistanceValue()+": duration - "+ route.get(i).getDurationValue(),Toast.LENGTH_SHORT).show();
// Start marker
MarkerOptions options = new MarkerOptions();
options.position(start);
options.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_start_blue));
mMap.addMarker(options);
// End marker
options = new MarkerOptions();
options.position(end);
options.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_end_green));
mMap.addMarker(options);
}
}
#Override
public void onRoutingCancelled() {
}
public void fetchAllTrafficLights()
{
pd.show();
firestore.collection("Controller").get().addOnCompleteListener(this, new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(Task<QuerySnapshot> task)
{
if(task.isSuccessful())
{
for(QueryDocumentSnapshot documentSnapshot : task.getResult())
{
Log.i("Hello", documentSnapshot.get("controllerLatitude").toString() + " " + documentSnapshot.get("controllerLongitude").toString());
pd.dismiss();
}
}
}
})
.addOnFailureListener(this, new OnFailureListener()
{
#Override
public void onFailure(Exception e)
{
Toast.makeText(PathActivity.this, "Error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
pd.dismiss();
}
});
}
}
I am using github library: https://github.com/jd-alexander/Google-Directions-Android to draw the route between two points.
The coordinated are already saved in the firestore database and are successfully fetched as shown in Log. Now I want to check if the lat long points fetched from database are in the path or not. Eg. If we move from point A to D, I want to check points B,C are present on the route or not. I also want to know does the google places api always give same route coordinates between two locations. Here is my object:
public class FetchLocation implements Serializable
{
public double latitude;
public double longitude;
public double destinationLatitude;
public double destinationLongitude;
public FetchLocation()
{
}
public FetchLocation(double latitude, double longitude, double destinationLatitude, double destinationLongitude) {
this.latitude = latitude;
this.longitude = longitude;
this.destinationLatitude = destinationLatitude;
this.destinationLongitude = destinationLongitude;
}
#Override
public String toString() {
return "FetchLocation{" +
"latitude=" + latitude +
", longitude=" + longitude +
", destinationLatitude=" + destinationLatitude +
", destinationLongitude=" + destinationLongitude +
'}';
}
}
The users source lat long are fetched in the previous activity using google place autocomplete- https://developers.google.com/places/android-sdk/autocomplete and are set in the object which is passed to this activity.
Anyone please help!!
Take a look at PolyUtil.isLocationOnPath(LatLng point, java.util.List<LatLng> polyline, boolean geodesic, double tolerance) method of Google Maps Android API Utility Library. You need to get polyline path from A to D and check each point from list (B and C) with isLocationOnPath() if it laying on A-D path. Something like that:
for (LatLng point : pointsBandCList) {
if (PolyUtil.isLocationOnPath(point, polylineFromAtoD.getPoints(), true, 100)) {
// "point" laying on A to D path
...
}
}
where 100 - is tolerance (in meters). You can adjust it for your task.
Good afternoon every one, I manage my google maps v2 with cluster manager(I'm using this library android-maps-utils) and I want to get the diffrence when a marker clicked and when a cluster manager clicked, But methodes doesn't called, So what going wrong in my code, I spent 10 days in this small problem, So Please Help.
HERE IT IS MY WHOLE CODE:
public class BigClusteringDemoActivity extends BaseDemoActivity implements ClusterManager.OnClusterClickListener,ClusterManager.OnClusterItemClickListener {
private ClusterManager<MyItem> mClusterManager;
#Override
protected void startDemo() {
getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10));
mClusterManager = new ClusterManager<MyItem>(this, getMap());
getMap().setOnCameraChangeListener(mClusterManager);
try {
readItems();
} catch (JSONException e) {
Toast.makeText(this, "Problem reading list of markers.", Toast.LENGTH_LONG).show();
}
getMap().setOnMarkerClickListener(mClusterManager);
}
private void readItems() throws JSONException {
InputStream inputStream = getResources().openRawResource(R.raw.radar_search);
List<MyItem> items = new MyItemReader().read(inputStream);
for (int i = 0; i < 10; i++) {
double offset = i / 60d;
for (MyItem item : items) {
LatLng position = item.getPosition();
double lat = position.latitude + offset;
double lng = position.longitude + offset;
MyItem offsetItem = new MyItem(lat, lng);
mClusterManager.addItem(offsetItem);
}
}
}
#Override
public boolean onClusterClick(Cluster cluster) {
Log.d("cluster","clicked" + cluster.getItems());
return false;
}
#Override
public boolean onClusterItemClick(ClusterItem item) {
Log.d("cluster","clicked" + item.getPosition());
return false;
}
}
You have not connected your ClusterManager to the map with onClick
You have this one getMap().setOnCameraIdleListener(mClusterManager);
try adding these aswell
getMap().setOnMarkerClickListener(mClusterManager);
mClusterManager.setOnClusterClickListener(this);
mClusterManager.setOnClusterItemClickListener(this);`
This will use the implements for listeners you added.
I have managed to find sequence of ClusterManager initialization for click listeners finally work:
1) init maps
mMap = googleMap
2) init ClusterManager
mClusterManager = ClusterManager(requireContext(), mMap)
3) set Map OnMarkerClickListener
mMap.setOnMarkerClickListener(mClusterManager)
4) init ClusterManager
mClusterManager = ClusterManager(requireContext(), mMap)
5) set cluster click listeners
mClusterManager.setOnClusterItemClickListener {
println("CLUST ITEM CLICK")
return#setOnClusterItemClickListener false
}
mClusterManager.setOnClusterClickListener {
println("CLUST CLICK")
return#setOnClusterClickListener false
}
6) when you use your custom render init it now:
mClusterManager.renderer = CustomIconRenderer(requireContext(), mMap, mClusterManager)
I'm trying to find out if it's possible to get latitude and longitude from address. I read that I can use Geocoder to convert address to Lat and Long.
However, I'm not sure how to implement this as I'm manually storing the address, lat and long of the location and retrieving it from firebase. I'm adding the markers on the map through the coords. But what I want is getting the coordinates from the address instead of the manually putting in the coords. Do I add the Geocoder function under the part where I retrieve the address? How do I do that?
This is the example I read :
How can I find the latitude and longitude from address?
LocationRemitActivity.java
public class LocationRemitActivity extends FragmentActivity implements OnMapReadyCallback {
public static final String EXTRA_NAME = "";
private static final String TAG = "tag";
private ClusterManager<StoreLatLng> mClusterManager;
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_remit_location);
ButterKnife.bind(this);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Marker Cluster
setUpClusterer();
mMap.getUiSettings().setIndoorLevelPickerEnabled(false);
}
private void setUpClusterer() {
// Position the map.
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(1.304414, 103.834006), 17));
// Initialize the manager with the context and the map.
// (Activity extends context, so we can pass 'this' in the constructor.)
mClusterManager = new ClusterManager<>(this, mMap);
// Point the map's listeners at the listeners implemented by the cluster
// manager.
mMap.setOnCameraIdleListener(mClusterManager);
mMap.setOnMarkerClickListener(mClusterManager);
mMap.setOnInfoWindowClickListener(mClusterManager); //added
mMap.setInfoWindowAdapter(mClusterManager.getMarkerManager());
// Listener for Info-Window Click , Parse data to next activity.
mClusterManager.setOnClusterItemInfoWindowClickListener(new ClusterManager.OnClusterItemInfoWindowClickListener<StoreLatLng>() {
#Override
public void onClusterItemInfoWindowClick(StoreLatLng myItem) {
Intent intent = new Intent(LocationRemitActivity.this, SelectedStoreDetail.class);
intent.putExtra(EXTRA_NAME, myItem.getTitle());
intent.putExtra("snippet", myItem.getSnippet());
Bundle args = new Bundle();
args.putParcelable("latlng", myItem.getPosition());
intent.putExtra("bundle", args);
startActivity(intent);
}
});
// Setting Cluster On Click ~> Zoom in 1 level .
mClusterManager.setOnClusterClickListener(new ClusterManager.OnClusterClickListener<StoreLatLng>() {
#Override
public boolean onClusterClick(final Cluster<StoreLatLng> cluster) {
// mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(cluster.getPosition(), (float) Math.floor(mMap.getCameraPosition().zoom + 1)), 300, null);
BottomSheetDialogFragment bottomSheetDialog = BottomSheetDialogFragment.getInstance();
bottomSheetDialog.show(getSupportFragmentManager(), "Custom Bottom Sheet");
return true;
}
});
// Add cluster items (markers) to the cluster manager.
addItems();
}
//
private void addItems() {
// Firebase Setup to Retrieve Data
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference();
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
if (postSnapshot.hasChild("Info")) {
// Get Data from Firebase (Name , Address , Lat , Lng)
String locationName = String.valueOf(postSnapshot.child("Info").child("Name").getValue());
String locationAddress = String.valueOf(postSnapshot.child("Info").child("Address").getValue());
double locationlat = (double) postSnapshot.child("Info").child("lat").getValue();
double locationlng = (double) postSnapshot.child("Info").child("lng").getValue();
if (locationName != null && locationAddress != null) {
// Create Marker inside MyItem + add markers to mClusterManager
StoreLatLng item = new StoreLatLng(locationlat, locationlng, locationName, locationAddress);
mClusterManager.addItem(item);
}
}
}
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});
I am trying to add an image I have in parse to a google map info window, I can add the image from resource but I am unable to load my existing parse image to the image view inside my infowindow. I have loaded the image from parse in other areas of my app, but it seems that the info window is out of scope. Is there a way to load this parse image inside my infowindow? I do not want to use a resource file because the images are different in parse. The 2 sections of my code are below:
class NearbyEventTask extends AsyncTask<String, Void, ArrayList<Item>>
{
Random r;
Context context;
public NearbyEventTask(Context context){
r = new Random();
this.context = context;
}
public LatLng getRandomLocation(Location center, double radius) {
// Convert radius from meters to degrees
double radiusInDegrees = radius / 111000;
double u = r.nextDouble();
double v = r.nextDouble();
double w = radiusInDegrees * Math.sqrt(u);
double t = 2 * Math.PI * v;
double lat = w * Math.cos(t);
double lon = w * Math.sin(t);
double new_lat = lat / Math.cos(center.getLongitude());
return new LatLng(new_lat + center.getLatitude(), lon + center.getLongitude());
}
#Override
protected ArrayList<Item> doInBackground(String... params) {
ArrayList<Item> list = new ArrayList<Item>();
ParseQuery<ParseObject> query = ParseQuery.getQuery("Places");
if(searchType!=null && searchType.length()>0) {
ArrayList<String> types = new ArrayList<String>();
for(String type: searchType.split("\\|")) types.add(type);
query.whereContainedIn("category", types);
}
if(lastKnownLocation!=null) {
query.whereNear("location", new ParseGeoPoint(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()));
}
try {
List<ParseObject> objects = query.find();
for(ParseObject obj : objects){
ParseGeoPoint point = obj.getParseGeoPoint("location");
Item item = new Item(obj.getString("name"), obj.getString("category"), obj.getString("description"), point.getLatitude(), point.getLongitude());
item.vicinity = obj.getString("description") + " | "+obj.getDate("event_date");
list.add(item);
if(obj.getParseFile("icon")!=null) {
item.setIcon(obj.getParseFile("icon").getUrl());
item.downloadIcon(context);
}
}
} catch (ParseException e) {
}
return list;
}
#Override
protected void onPostExecute(final ArrayList<Item> arrayList) {
if(isCancelled()) return;
if(googleMap!=null) {
googleMap.clear();
mMarker2Item.clear();
LatLngBounds.Builder boundBuilder = new LatLngBounds.Builder();
for (Item item : arrayList) {
MarkerOptions opts = new MarkerOptions()
.position(item.location())
.title(item.name);
if(item.iconBitmap!=null){
opts = opts.icon(BitmapDescriptorFactory.fromBitmap(item.iconBitmap));
}
Marker newMarker = googleMap.addMarker(opts);
newMarker.setSnippet(item.vicinity);
mMarker2Item.put(newMarker, item);
boundBuilder.include(item.location());
}
try {
if (firstTime) {
firstTime = false;
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(boundBuilder.build(), 200);
googleMap.moveCamera(cameraUpdate);
googleMap.animateCamera(cameraUpdate, 1000, null);
}
} catch (Exception ex) {
}
} else mHandler.postDelayed(new Runnable() {
#Override
public void run() {
onPostExecute(arrayList);
}
}, 500);
}
}
#Override
public void onMapReady(final GoogleMap googleMap) {
googleMap.setMyLocationEnabled(true);
this.googleMap = googleMap;
googleMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
// Use default InfoWindow frame
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
// Defines the contents of the InfoWindow
#Override
public View getInfoContents(Marker marker) {
View v = getActivity().getLayoutInflater().inflate(R.layout.maps_infowindow, null);
v.setLayoutParams(new LinearLayout.LayoutParams((int) (mapFragment.getView().getMeasuredWidth() * .9), LinearLayout.LayoutParams.WRAP_CONTENT));
((TextView) v.findViewById(R.id.title)).setText(marker.getTitle());
((TextView) v.findViewById(R.id.desc)).setText(marker.getSnippet());
ImageView icon = (ImageView) v.findViewById(R.id.imageView5);
icon.getLayoutParams().height = 800; // OR
icon.getLayoutParams().width = 800;
ArrayList<Item> list = new ArrayList<Item>();
ParseQuery<ParseObject> query = ParseQuery.getQuery("Places");
if(searchType!=null && searchType.length()>0) {
ArrayList<String> types = new ArrayList<String>();
for(String type: searchType.split("\\|")) types.add(type);
query.whereContainedIn("icon", types);
}
try {
List<ParseObject> objects = query.find();
for(ParseObject obj : objects){
if(obj.getParseFile("icon")!=null) {
Picasso.with(getActivity()).load(obj.getParseFile("icon").getUrl()).into(icon, new MarkerCallback(marker));
}
}
} catch (ParseException e) {
}
return v;
}
}
);
CODE UPDATED: If you look at my NearbyEventTast class at the top, you can see how the code was implemented to get the data back from parse. I am trying to do the same thing by creating a new NearbyEventTast but I fail to load the correct image. It always shows the same image (I think its the first one in parse) and displays it for all objects instead of the corresponden image. Any idiea whats going on? Thank you!
As I am not much aware of Parse. But I have also face this issue to show a image from URL into info window.
First of all, the reason infowindow is not showing the downloaded image because MapFragment renders the view into a Canvas and then draws that. What you're seeing in the info window aren't the views you created, but a "picture" or "screenshot" of them. You basically need to call showInfoWindow() again on the Marker object, and that will re-render the Canvas and your image will now be visible.
Or you can use the Picasso Library to load the image. I am using the Picasso callback option in my app.
First you need to create a Class that will implements a Picasso Callback Interface and in the Constructor recieve a marker to call a show info window when image loads.
public static class MarkerCallback implements Callback {
private Marker marker;
public MarkerCallback(Marker marker) {
this.marker = marker;
}
#Override
public void onSuccess() {
if (marker != null && marker.isInfoWindowShown()) {
marker.hideInfoWindow();
marker.showInfoWindow();
}
}
#Override
public void onError() {
}
}
How to use it.
public View getInfoContents(Marker marker) {
View v = getActivity().getLayoutInflater().inflate(R.layout.maps_infowindow, null);
v.setLayoutParams(new LinearLayout.LayoutParams((int) (mapFragment.getView().getMeasuredWidth() * .9), LinearLayout.LayoutParams.WRAP_CONTENT));
((TextView) v.findViewById(R.id.title)).setText(marker.getTitle());
((TextView) v.findViewById(R.id.desc)).setText(marker.getSnippet());
ImageView markerIcon = (ImageView) v.findViewById(R.id.imageView5);
Picasso.with(MainActivity.this).load(imgUrl).into(markerIcon, new MarkerCallback(marker));
}
Hope this will help you.
so what I'm trying to do is when a user tap on a Google Map Marker, an activity will show that will display all the information inside that marker. But the problem is, all markers shows the same result(which is the item in the first row of my parse.com database). I am currently using Xamarin for development. I will appreciate any answer. Thank you guys in advanced.
public async void getGeoPoint(){
string getPlaceName, getPlacePrice, getPlaceAddress, getOwnerContact, getRentalType, getOwnerName;
string xx = autoCompleteTextView.Text;
ParseQuery<ParseObject> query = ParseObject.GetQuery ("Rentals")
.WhereEqualTo ("rentalCity", xx);
IEnumerable<ParseObject> results = await query.FindAsync ();
foreach(var temp in results){
getLatitude = temp.Get<double> ("rentalLatitude");
getLongitude = temp.Get<double> ("rentalLongitude");
getPlaceName = temp.Get<string> ("rentalName");
getPlacePrice = temp.Get<string> ("rentalPrice");
getPlaceAddress = temp.Get<string> ("rentalFullAddress");
getOwnerContact = temp.Get<string> ("ownerContactNo");
getRentalType = temp.Get<string> ("rentalType");
getOwnerName = temp.Get<string> ("ownerName");
myMarker = map.AddMarker(new MarkerOptions()
.SetPosition(new LatLng(getLatitude, getLongitude))
.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.edimeow))
);
}
map.MarkerClick += (object sender, GoogleMap.MarkerClickEventArgs e) => {
string selected = getPlaceName;
var passToRentalProfile = new Intent (this, typeof(HostRentalProfileList));
passToRentalProfile.PutExtra ("selected", selected);
StartActivity (passToRentalProfile);
this.Finish();
};
btnList.Click += (object sender, EventArgs e) => {
var passToUserList = new Intent (this, typeof(UserListMode));
passToUserList.PutExtra("arrData", xx);
StartActivity(passToUserList);
this.Finish();
};
}//getGeoPoint
In your foreach loop your enumerating all the results returned, and whilst you are adding a new map marker at different geo-positions, you are not storing any of the other details within the marker that is added.
Subsequently, when you enumerate the next result, your resetting your local variables to the new information.
Your map.MarkerClick is a generic handler that occurs for any map marker click.
Your attempting to reference getPlaceName which is set earlier, and will be equal to the last item in your results always.
You need to store these results in some collection and the add some id to a map marker that is created, so you can refer back to your original result to use, when they click on the map marker.
I have something similar, where i need to display a custom message when a marker is clicked, I store it in a Dictionary and over the GoogleMap.IOnMarkerClickListener which will pass you the Marker that has been clicked.
public class MarkerManager : Java.Lang.Object, GoogleMap.IOnMarkerClickListener
{
private readonly GoogleMap _map;
private Dictionary<Marker, int> _markerDictionary;
public MarkerManager(GoogleMap map, BaseActivity activity)
{
_activity = activity;
_map = map;
_markerDictionary = new Dictionary<Marker, int>();
}
public void AddMarkerCallback(LatLng position, string title, string bodyText, int? icon, Action<int, Marker> callback,
bool draggable = false, int id = 0)
{
var markerOptions = new MarkerOptions();
markerOptions.SetPosition(position);
markerOptions.SetTitle(title);
markerOptions.SetSnippet(bodyText);
markerOptions.Draggable(draggable);
CallBack = callback;
if (icon.HasValue)
{
markerOptions.InvokeIcon(BitmapDescriptorFactory.FromResource(icon.Value));
}
var marker = _map.AddMarker(markerOptions);
_markerDictionary.Add(marker, id);
_map.SetOnMarkerClickListener(this);
}
public void ClearMap()
{
if(_map != null)
_map.Clear();
_markerDictionary = new Dictionary<Marker, int>();
}
public bool OnMarkerClick(Marker p0)
{
p0.ShowInfoWindow();
Console.WriteLine("maker click");
HideMarkerAfterTime(p0);
foreach (var i in _markerDictionary)
{
if (!i.Key.Equals(p0)) continue;
if (CallBack == null) return true;
SeletedMarkerId = i.Value;
CallBack(i.Value, p0);
return true;
}
if (CallBackLocation != null)
CallBackLocation(p0.Position);
return false;
}
/// <summary>
/// The timer
/// </summary>
private System.Timers.Timer _timer;
/// <summary>
/// Hides the marker after time.
/// </summary>
/// <param name="p0">The p0.</param>
/// <param name="miliSeconds">The mili seconds.</param>
private void HideMarkerAfterTime(Marker p0, double miliSeconds = 3000)
{
//need to clean down timer object. if i click on another
//icon wierd things happen
if (_timer != null) _timer.Dispose();
_timer = new System.Timers.Timer { Interval = miliSeconds };
_timer.Start();
_timer.Elapsed += (sender, args) => _activity.RunOnUiThread(() =>
{
p0.HideInfoWindow();
_timer.Stop();
});
}
}