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.
Related
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 working on a small app and have implemented Google Maps and Places api. Currently i'm able to see all my markers on the map and clustering working fine. I'm able to zoom in the clusters open up and able to see the markers. I have a spinner that has different types and once selected that type is passed to the places search string.
This is my maps code that includes the clustering:
public class MapsActivity extends FragmentActivity implements LocationListener,ClusterManager.OnClusterItemInfoWindowClickListener<MyItem> {
GoogleMap mMap;
double myLatitude = 0;
double myLongitude = 0;
HashMap<String, String> mMarker = new HashMap<String, String>();
PlaceJSONParser placeJsonParser = new PlaceJSONParser();
private ClusterManager<MyItem> mClusterManager;
protected MyItem clickedClusterItem;
String[] placeType;
String[] placeTypeName;
Spinner spinPlaceType;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mMap = mapFragment.getMap();
onMapReady();
// Array of place types
placeType = getResources().getStringArray(R.array.placeType);
// Array of place type names
placeTypeName = getResources().getStringArray(R.array.placeTypeName);
// Creating an array adapter with an array of Place types
// to populate the spinner
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.spinner_item, R.id.textview, placeTypeName);
// Getting reference to the Spinner
spinPlaceType = (Spinner) findViewById(R.id.spinPlaceType);
// Setting adapter on Spinner to set place types
spinPlaceType.setAdapter(adapter);
spinPlaceType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
int selectedPosition = spinPlaceType.getSelectedItemPosition();
final String type = placeType[selectedPosition];
StringBuilder sb = new StringBuilder(
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
sb.append("location=" + myLatitude + "," + myLongitude);
sb.append("&type=" + type);
sb.append("&radius=4000");
sb.append("&key=PLACES_KEY");
// Creating a new non-ui thread task to download Google place json
// data
PlacesTask placesTask = new PlacesTask();
// Invokes the "doInBackground()" method of the class PlaceTask
placesTask.execute(sb.toString());
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
StringBuilder sb = new StringBuilder(
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
sb.append("location=" + myLatitude + "," + myLongitude);
sb.append("&type=restaurant");
sb.append("&radius=4000");
sb.append("&key=PLACES_KEY");
// Creating a new non-ui thread task to download Google place json
// data
PlacesTask placesTask = new PlacesTask();
// Invokes the "doInBackground()" method of the class PlaceTask
placesTask.execute(sb.toString());
}
});
// Will display next 20 places returned form the next_page_token
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab_more);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Finding you some more places.", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
StringBuilder sb = new StringBuilder(
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
sb.append("pagetoken=" + placeJsonParser.getNext_Page_token());
sb.append("&key=PLACES_KEY");
// Creating a new non-ui thread task to download Google place json
// data
if (placeJsonParser.getNext_Page_token() == null || placeJsonParser.getNext_Page_token() == ""){
Snackbar.make(view, "No more places left to find.", Snackbar.LENGTH_SHORT)
.setAction("Action", null).show();
}
PlacesTask placesTask = new PlacesTask();
// Invokes the "doInBackground()" method of the class PlaceTask
placesTask.execute(sb.toString());
}
});
mMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
Intent detailsIntent = new Intent(getBaseContext(), PlaceDetailsActivity.class);
String reference = mMarker.get(marker.getId());
marker.getPosition();
detailsIntent.putExtra("reference", reference);
detailsIntent.putExtra("markerLat", myLatitude);
detailsIntent.putExtra("markerLong", myLongitude);
startActivity(detailsIntent);
}
});
}
public void onMapReady(){
// Enabling MyLocation in Google Map
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setCompassEnabled(true);
mMap.getUiSettings().setZoomControlsEnabled(true);
// Getting LocationManager object from System Service
// LOCATION_SERVICE
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
// Creating a criteria object to retrieve provider
Criteria criteria = new Criteria();
// Getting the name of the best provider
String provider = locationManager.getBestProvider(criteria, true);
// Getting Current Location From GPS
Location location = locationManager.getLastKnownLocation(provider);
// onLocationChanged(location);
if (location != null) {
onLocationChanged(location);
}
}
/**
* A method to download json data from url
*/
private String downloadUrl(String strUrl) throws IOException {
String referer ="";
StringBuilder jsonResults = new StringBuilder();
HttpURLConnection conn = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
conn = (HttpURLConnection) url.openConnection();
if (referer != null) {
conn.setRequestProperty("Referer", referer);
}
InputStreamReader in = new InputStreamReader(conn.getInputStream());
// Load the results into a StringBuilder
int read;
char[] buff = new char[1024];
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
}
// Displays the list of places found in the terminal.
Log.i("Data", "Places Found: " + jsonResults);
} catch (MalformedURLException e) {
Log.i("Google Places Utility", "Error processing Places API URL");
return null;
} catch (IOException e) {
Log.i("Google Places Utility", "Error connecting to Places API");
return null;
} finally {
if (conn != null) {
conn.disconnect();
}
}
return jsonResults.toString();
}
/**
* A class, to download Google Places
*/
private class PlacesTask extends AsyncTask<String, Integer, String> {
String data = null;
// Invoked by execute() method of this object
#Override
protected String doInBackground(String... url) {
try {
data = downloadUrl(url[0]);
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
// Executed after the complete execution of doInBackground() method
#Override
protected void onPostExecute(String result) {
ParserTask parserTask = new ParserTask();
// Start parsing the Google places in JSON format
// Invokes the "doInBackground()" method of the class ParseTask
parserTask.execute(result);
}
}
/**
* A class to parse the Google Places in JSON format
*/
private class ParserTask extends
AsyncTask<String, Integer, List<HashMap<String, String>>> {
JSONObject jObject;
// Invoked by execute() method of this object
#Override
protected List<HashMap<String, String>> doInBackground(
String... jsonData) {
List<HashMap<String, String>> places = null;
try {
jObject = new JSONObject(jsonData[0]);
/** Getting the parsed data as a List construct */
places = placeJsonParser.parse(jObject);
} catch (Exception e) {
Log.d("Exception", e.toString());
}
return places;
}
// Executed after the complete execution of doInBackground() method
#Override
protected void onPostExecute(List<HashMap<String, String>> list) {
// Clears all the existing markers
mMap.clear();
setUpClusterer(list);
}
}
private void setUpClusterer(List<HashMap<String, String>> list) {
// Position the map.
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(myLatitude,myLongitude), 13));
// Initialize the manager with the context and the map.
// (Activity extends context, so we can pass 'this' in the constructor.)
mClusterManager = new ClusterManager<MyItem>(this, mMap);
// Point the map's listeners at the listeners implemented by the cluster
// manager.
mMap.setOnCameraChangeListener(mClusterManager);
mMap.setOnMarkerClickListener(mClusterManager);
mMap.setInfoWindowAdapter(mClusterManager.getMarkerManager());
mMap.setOnInfoWindowClickListener(mClusterManager);
mClusterManager.setOnClusterItemInfoWindowClickListener(this);
mClusterManager
.setOnClusterItemClickListener(new ClusterManager.OnClusterItemClickListener<MyItem>() {
#Override
public boolean onClusterItemClick(MyItem item) {
clickedClusterItem = item;
return false;
}
});
// Add cluster items (markers) to the cluster manager.
addItems(list);
mClusterManager.getMarkerCollection().setOnInfoWindowAdapter(
new MyCustomAdapterForItems());
}
public class MyCustomAdapterForItems implements GoogleMap.InfoWindowAdapter {
private final View myContentsView;
MyCustomAdapterForItems() {
myContentsView = getLayoutInflater().inflate(
R.layout.info_window, null);
}
#Override
public View getInfoWindow(Marker marker) {
TextView tvTitle = ((TextView) myContentsView
.findViewById(R.id.txtTitle));
TextView tvSnippet = ((TextView) myContentsView
.findViewById(R.id.txtSnippet));
tvTitle.setText(clickedClusterItem.getTitle());
tvSnippet.setText(clickedClusterItem.getSnippet());
return myContentsView;
}
#Override
public View getInfoContents(Marker marker) {
return null;
}
}
private void addItems(List<HashMap<String, String>> list) {
double latitude;
double longitude;
for (int i = 0; i < list.size(); i++) {
HashMap<String, String> hmPlace = list.get(i);
// Getting latitude of the place
latitude = Double.parseDouble(hmPlace.get("lat"));
// Getting longitude of the place
longitude = Double.parseDouble(hmPlace.get("lng"));
String name = hmPlace.get("place_name");
// Getting vicinity
String vicinity = hmPlace.get("vicinity");
MyItem offsetItem = new MyItem(latitude, longitude, hmPlace.get("reference"), name, vicinity);
mClusterManager.addItem(offsetItem);
}
}
public void onClusterItemInfoWindowClick(MyItem item) {
Intent placesIntent = new Intent(getBaseContext(), PlaceDetailsActivity.class);
String reference = item.getReference();
placesIntent.putExtra("name", item.getTitle());
placesIntent.putExtra("reference", reference);
placesIntent.putExtra("sourcelat", myLatitude);
placesIntent.putExtra("sourcelng", myLongitude);
startActivity(placesIntent);
}
#Override
public void onLocationChanged(Location location) {
myLatitude = location.getLatitude();
myLongitude = location.getLongitude();
LatLng myLocation = new LatLng(myLatitude, myLongitude);
mMap.moveCamera(CameraUpdateFactory.newLatLng(myLocation));
mMap.animateCamera(CameraUpdateFactory.zoomTo(13));
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
my myItem class to get info for the markers:
package com.example.tariq.outandabout;
import com.google.android.gms.maps.model.LatLng;
import com.google.maps.android.clustering.ClusterItem;
public class MyItem implements ClusterItem {
LatLng mPosition;
private String reference,placeTitle,snippet;
public MyItem(double lat, double lng,String val,String title, String snip) {
mPosition = new LatLng(lat, lng);
reference=val;
placeTitle=title;
snippet = snip;
}
#Override
public LatLng getPosition() {
// TODO Auto-generated method stub
return mPosition;
}
public String getReference() {
// TODO Auto-generated method stub
return reference;
}
public String getTitle() {
// TODO Auto-generated method stub
return placeTitle;
}
public String getSnippet() {
// TODO Auto-generated method stub
return snippet;
}
}
Currently only red markers are getting displayed but I was wondering if there is a way to have a different markers depending on the type selected from the spinner, For example if I select Hospital then the markers are shown as little hospital icons, if I select ATM, then a little ATM icon appears.
Any help will be appreciated.
Firstly you have to store all the info you need (at this situation just LatLng and marker icon) insite ClusterItem object.
public class MarkerItem implements ClusterItem {
private String title;
private String snippet;
private LatLng latLng;
private BitmapDescriptor icon;
public MarkerItem(MarkerOptions markerOptions) {
this.latLng = markerOptions.getPosition();
this.title = markerOptions.getTitle();
this.snippet = markerOptions.getSnippet();
this.icon = markerOptions.getIcon();
}
#Override
public LatLng getPosition() {
return latLng;
}
public String getTitle() {
return title;
}
public String getSnippet() {
return snippet;
}
public void setLatLng(LatLng latLng) {
this.latLng = latLng;
}
public BitmapDescriptor getIcon() {
return icon;
}
public void setIcon(BitmapDescriptor icon) {
this.icon = icon;
}
}
The next step would be to make cluster renderer show your icon instead of default maker icon. To achieve that, you need to extend DefaultClusterRenderer object:
public class ClusterRenderer extends DefaultClusterRenderer<MarkerItem> {
public ClusterRenderer(Context context, GoogleMap map, ClusterManager<MarkerItem> clusterManager) {
super(context, map, clusterManager);
clusterManager.setRenderer(this);
}
#Override
protected void onBeforeClusterItemRendered(MarkerItem markerItem, MarkerOptions markerOptions) {
if (markerItem.getIcon() != null) {
markerOptions.icon(markerItem.getIcon()); //Here you retrieve BitmapDescriptor from ClusterItem and set it as marker icon
}
markerOptions.visible(true);
}
}
Finally, you have to initialize the clusterRenderer and markerItems
ClusterManager clusterManager = new ClusterManager<>(context, googleMap);
ClusterRenderer clusterRenderer = new ClusterRenderer<>(activity, googleMap, clusterManager); // not needed to use clusterManager.setRenderer method since i made it in constructor
MarkerOptions markerOptions = new MarkerOptions()
.position(new LatLng(latitude, longitude))
.icon(BitmapDescriptorFactory.fromResource(R.drawable.your_resource_icon));
MarkerItem markerItem = new MarkerItem(markerOptions);
clusterManager.addItem(markerItem);
You can implement your own logic, which icon you want to pass to markerItem here.
EDIT
To pass different icons, you could create a separate method for that
Example:
public MarkerOptions getMarkerOptions(LatLng latLng, String title, String snippet, int iconRes) {
return new MarkerOptions()
.title(title)
.snippet(snippet)
.position(latLng)
.icon(BitmapDescriptorFactory.fromResource(iconRes));
}
EDIT 2
I updated MarkerItem class to suit your needs, replace your MyItem class with MarkerItem class. Add your items using this class and update it to suit your needs
I am developing an android application which displays a map. When it loads, it displays some addresses and sets markers for them.
When I click on any marker it should display a value in a custom view. But the custom text which is received from a json parser, gets a null value. When I click on the marker again, it sets correct value.
When I click on second marker it display 1st marker value. When I click on 2nd marker again it displays correct value. This process continues
Here's my code:
private class GeocoderTask extends AsyncTask<String, Void, List<Address>>{
private Context mainContxt;
Geocoder geocoder;
public GeocoderTask(Context con){
mainContxt=con;
}
#Override
protected List<Address> doInBackground(String... locationName) {
Geocoder geocoder = new Geocoder(mainContxt);
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocationName(locationName[0],1);
} catch (IOException e) {
e.printStackTrace();
}
return addresses;
}
#Override
protected void onPostExecute(List<Address> addresses) {
for(int i=0;i<addresses.size();i++){
Address address = (Address) addresses.get(i);
latLng = new LatLng(address.getLatitude(), address.getLongitude());
String addressText = String.format("%s, %s",
address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
address.getCountryName());
markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(addressText);
if(i==0) {
googleMap.animateCamera(CameraUpdateFactory.zoomBy(14),2000,null);
googleMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
}
googleMap.addMarker(markerOptions);
}
googleMap.setOnMarkerClickListener(new OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker_address) {
location=marker_address.getTitle();
Toast.makeText(getApplicationContext(),location, Toast.LENGTH_LONG).show();
new LoadSingleProperty().execute();
//new LoadImage().execute();
return false;
}
});
googleMap.setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
View myContentView = getLayoutInflater().inflate(
R.layout.custom_marker, null);
tempnew_price=getPrice(temptotal_price+"" +email);
TextView tvTitle = ((TextView) myContentView
.findViewById(R.id.title));
// tvTitle.setText(location);
tvSnippet = ((TextView) myContentView
.findViewById(R.id.snippet));
ivProperty = ((ImageView) myContentView
.findViewById(R.id.image_property));
tvTitle.setText(tempcovered_area+ " "+tempnew_price+System.getProperty("line.separator")+templocation);
tvSnippet.setText("A "+ tempbedroom + " "+tempproperty_type);
// new LoadImage().execute();
ivProperty.setImageBitmap(bmp);
return myContentView;
}
});
googleMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker arg0) {
Intent intent = new Intent(getBaseContext(),
search_property_activity.class);
intent.putExtra("Email", email);
startActivity(intent);
}
});
}
}
this is my loadsingle class coding.....
class LoadSingleProperty extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivityMap.this);
pDialog.setMessage("Loading Location. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected String doInBackground(String... args) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
if(location!=null && !location.equals("")){
params.add(new BasicNameValuePair("Location", location));
json= jsonParser.makeHttpRequest(url_loc_address, "GET", params);
}
Log.d("MyLocation: ", json.toString());
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
address = json.getJSONArray(TAG_ALL_ADDRESS);
//for (int i = 0; i < address.length(); i++) {
JSONObject c = address.getJSONObject(0);
templocation = c.getString(TAG_LOCATION);
tempcovered_area=c.getString(TAG_COVERED_AREA);
temptotal_price=c.getString(TAG_Total_Price);
tempbedroom=c.getString(TAG_BEDROOM);
tempproperty_type=c.getString(TAG_PROPERTY_TYPE);
tempemail=c.getString(TAG_EMAIL);
//}
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String file_url) {
pDialog.dismiss();
new GeocoderTask(MainActivityMap.this).execute(location);
}
}
Help me friends ...thx in advance
Create a constructor for LoadSingleProperty
class LoadSingleProperty extends AsyncTask<String, String, String> {
Marker mMarker;
public LoadSingleProperty(Marker marker){
mMarker = marker;
}
.
.
.
}
and pass your marker object to it.
new LoadSingleProperty(marker_address).execute();
Once parsing is done set your marker's title using setTitle() method for the marker
mMarker.setTitle(c.getString(TAG_PROPERTY_TYPE));
where you currently do this
tempproperty_type=c.getString(TAG_PROPERTY_TYPE);
Don't forget to refresh your info window once title is reset
How to force refresh contents of the markerInfoWindow
You may also want to show some sort of a loading icon till this time since you're performing a network request.
EDIT:
In case you're using a custom titleview, get a reference to InfoWindowAdapter object before setting as a adapter to googleMap
InfoWindowAdapter infoWindowAdapter = new InfoWindowAdapter() {...
Once parsing is complete, get info window view for mMarker object by calling
infoWindowAdapter.getInfoWindow(mMarker);
Find your textView from the view obtained above and set its text. Then refresh your info window by calling showInfoWindow() to update the info window.
Also please refer this link.
The info window that is drawn is not a live view. The view is rendered
as an image (using View.draw(Canvas)) at the time it is returned. This
means that any subsequent changes to the view will not be reflected by
the info window on the map. To update the info window later (for
example, after an image has loaded), call showInfoWindow()
private class GeocoderTask extends AsyncTask<String, Void, List<Address>> {
private Context mainContxt;
Geocoder geocoder;
public GeocoderTask(Context con) {
mainContxt = con;
}
#Override
protected List<Address> doInBackground(String... locationName) {
Geocoder geocoder = new Geocoder(mainContxt);
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocationName(locationName[0], 1);
} catch (IOException e) {
e.printStackTrace();
}
return addresses;
}
#Override
protected void onPostExecute(List<Address> addresses) {
for (int i = 0; i < addresses.size(); i++) {
Address address = (Address) addresses.get(i);
latLng = new LatLng(address.getLatitude(),
address.getLongitude());
String addressText = String.format(
"%s, %s",
address.getMaxAddressLineIndex() > 0 ? address
.getAddressLine(0) : "", address
.getCountryName());
markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(addressText);
if (i == 0) {
googleMap.animateCamera(CameraUpdateFactory.zoomBy(14),
2000, null);
googleMap.animateCamera(CameraUpdateFactory
.newLatLng(latLng));
}
googleMap.addMarker(markerOptions);
}
}
}
Then you write below code
googleMap.setOnMarkerClickListener(new OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker_address) {
location = marker_address.getTitle();
new LoadSingleProperty().execute();
return false;
}
});
Take another customeWindowAdapter or else use the present one only and set that in onPostExecute() method of 'LoadSingleProperty' AsyncTask..
This will solve that.
ping here you have any queries
I creating a android app that uses google maps android api.
This app need to to have a on click polygon function, but since it not available on google maps android api v2. I did some research and found a work around for this function.
What i ended up with is to check if a point is in a polygon method.
I'm using this library. And it work pretty well if you create the bounds manually.
If can create the bounds in a loop that would solve my problem.
I get the polygon points from my database.
Here is my MapFragment code:
public class MapBlocksMapView extends Fragment {
protected GoogleMap googleMap;
protected LatLng latLng;
protected Intent intent;
protected String color, crops, block_code, tmp_user;
public MapBlocksMapView() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ActionBar actionBar = getActivity().getActionBar();
actionBar.setTitle("Block View");
View rootView = inflater.inflate(R.layout.fragment_blocksmapview, container, false);
if (googleMap== null) {
googleMap= ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map)).getMap();
}
Bundle bundle = getArguments();
if (bundle != null) {
block_code = bundle.getString("block_code");
tmp_user = bundle.getString("user");
}
googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
checkpoint(latLng.latitude, latLng.longitude);
}
});
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState){
getdata(getActivity(), block_code);
super.onActivityCreated(savedInstanceState);
}
private void checkpoint(double latitude, double longitude) {
System.out.println(latitude +"," +longitude);
}
public void getdata(Context ctx, String block_code) {
SQLHelper dbhelper = new SQLHelper(ctx);
dbhelper.getReadableDatabase();
JSONArray jsonArray = dbhelper.getSingleBlocks(block_code);
try {
for (int a = 0; a < jsonArray.length(); a++) {
JSONObject jsonObject = new JSONObject(String.valueOf(jsonArray.getJSONObject(a)));
JSONArray jsonArray1 = jsonObject.getJSONArray("b_points");
if (jsonObject.getJSONArray("b_points").length() > 0) {
color = jsonObject.getString("b_color");
crops = jsonObject.getString("b_crop");
PolygonOptions rectOptions = new PolygonOptions();
for (int b = 0; b < jsonArray1.length(); b++) {
JSONArray jsonArray2 = jsonArray1.getJSONArray(b);
rectOptions.add(new LatLng(jsonArray2.getDouble(0), jsonArray2.getDouble(1)));
System.out.println(jsonArray2.get(0) + " / " + jsonArray2.get(1));
}
latLng = new LatLng(jsonArray1.getJSONArray(0).getDouble(0), jsonArray1.getJSONArray(0).getDouble(1));
rectOptions.strokeWidth(1).strokeColor(Color.parseColor(color)).fillColor(Color.parseColor(color));
googleMap.addPolygon(rectOptions);
CameraUpdate cameraPosition = CameraUpdateFactory.newLatLngZoom(latLng, 17);
googleMap.animateCamera(cameraPosition);
} else {
Toast.makeText(getActivity(), "Error with the selected block", Toast.LENGTH_LONG).show();
closeFragment();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onDestroyView() {
super.onDestroyView();
SupportMapFragment f = (SupportMapFragment) getFragmentManager()
.findFragmentById(R.id.map);
if (f != null)
getFragmentManager().beginTransaction().remove(f).commit();
}
private void closeFragment() {
getActivity().getFragmentManager().popBackStack();
}
}
Here is the example code from the library:
Polygon polygon = Polygon.Builder()
.addVertex(new Point(1, 3))
.addVertex(new Point(2, 8))
.addVertex(new Point(5, 4))
.addVertex(new Point(5, 9))
.addVertex(new Point(7, 5))
.addVertex(new Point(6, 1))
.addVertex(new Point(3, 1))
.build();
Point point = new Point(4.5f, 7);
boolean contains = polygon.contains(point);
If some have a other solution or suggestions would be helpful.
Thanks
I also had the same problem but i haven't found a "good" solution for this issue.
In the end i saved all polygons in a list and iterate through it with the click position. (but beware; maybe you have more than a single polygon at this position)
well this that library isnt going to be much help because you have geographical positions and the library expects screen positions so you are going to be doing most of the work yourself really.
you need to take each latlng and convert them into screen points by getting the maps projection
Point point = googleMap.getProjection().toScreenLocation(myLatLngPoint);
then you can put that point into your library like you need when looping. However I do not know what will be returned if the latlng you are using is not in the projection (ie. off the screen) so you will have to test that
I manage to solve this after some digging around and found this code on github.
I'm using this library now and it works like a charm.
My polygon points are stored like this in my database as string.
[[3.65E-4,-1.1E-5],[-5.0E-6,3.54E-4],[-3.0E-6,-1.1E-4]]
Here is a example code
protected double[] points;
public void getdata(){
SQLHelper dbhelper = new SQLHelper(ctx);
dbhelper.getReadableDatabase();
String[] ls =dbhelper.getSingleBlocksPointsArray(block_code)
.replaceAll("\\[", "")
.replaceAll("\\]","")
.split(",");
points = new double[ls.length];
for(int i=0;i<ls.length;i++)
{
points[i] = Double.parseDouble(ls[i]);
}
}
in onCreateView i use this:
googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
if(contains(new Coordinate(latLng.latitude,latLng.longitude), points)) {
Toast.makeText(getActivity(),"True",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(getActivity(),"False",Toast.LENGTH_SHORT).show();
}
}
});
Good afternoon. Is it possible to add a few snippets of one marker? For Android version 2 of Google Maps
Marker melbourne = mMap.addMarker(new MarkerOptions()
.position(MELBOURNE)
.title("Melbourne")
.snippet("Population: 4,137,400"));
Here's my infowindow
class MyInfoWindowAdapter implements InfoWindowAdapter{
private final View myContentsView;
MyInfoWindowAdapter(){
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams((w*2)/3, LayoutParams.WRAP_CONTENT);
myContentsView = getLayoutInflater().inflate(R.layout.custom_info_contents, null);
myContentsView.setLayoutParams(lp);
}
public View getInfoContents(Marker marker) {
tvTitle = ((TextView)myContentsView.findViewById(R.id.title));
tvTitle.setText(marker.getTitle());
tvSnippet = ((TextView)myContentsView.findViewById(R.id.snippet));
tvSnippet.setText(marker.getSnippet());
return myContentsView;
}
public View getInfoWindow(Marker marker) {
// TODO Auto-generated method stub
return null;
}
}
I want to show different markers of different snippets, when necessary. How do I do this? And is it possible at all?
UPDATE:
You probably have not understood or wrongly I explained.
public void ParseQueryMap() {
ParseQuery query = new ParseQuery("MyObject");
query.findInBackground(new FindCallback() {
public void done(List<ParseObject> myObject, ParseException e) {
if (e == null) {
for ( int i = 0; i < myObject.size(); i++) {
commGet = myObject.get(i).getString("Comment");
bugGet = myObject.get(i).getObjectId();
geo1Dub = myObject.get(i).getParseGeoPoint("location").getLatitude();
geo2Dub = myObject.get(i).getParseGeoPoint("location").getLongitude();
Location aLocation = new Location("first");
aLocation.setLatitude(geo1Dub);
aLocation.setLongitude(geo2Dub);
Location bLocation = new Location("second");
bLocation.setLatitude(location.getLatitude());
bLocation.setLongitude(location.getLongitude());
int distance = (int)aLocation.distanceTo(bLocation);
if (distance<rad) {
myMap.addMarker(new MarkerOptions().position(new LatLng(geo1Dub,geo2Dub)).title(commGet).snippet(snippet)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
} else {
}
}
} else {
Toast.makeText(MainActivity.this, "Error!", Toast.LENGTH_SHORT).show();
}
}
});
I want to get bugGet for each marker, the user bugGet not show, but when she clicks on infowindow I could learn bugGet specific marker. "bugGet" it "id" each marker in my database. The user does not need it, and I need you.
Here is example, you can check the coordinates of the marker and after that decide what infoWindow you want to show.
map.setInfoWindowAdapter(new InfoWindowAdapter() {
// Use default InfoWindow frame
#Override
public View getInfoWindow(Marker args) {
return null;
}
// Defines the contents of the InfoWindow
#Override
public View getInfoContents(Marker args) {
// Getting view from the layout file info_window_layout
View v = getLayoutInflater().inflate(R.layout.info_window_layout, null);
// Getting the position from the marker
clickMarkerLatLng = args.getPosition();
TextView title = (TextView) v.findViewById(R.id.tvTitle);
title.setText(args.getTitle());
map.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
public void onInfoWindowClick(Marker marker)
{
if (SGTasksListAppObj.getInstance().currentUserLocation!=null)
{
if (String.valueOf(SGTasksListAppObj.getInstance().currentUserLocation.getLatitude()).substring(0, 8).contains(String.valueOf(clickMarkerLatLng.latitude).substring(0, 8)) &&
String.valueOf(SGTasksListAppObj.getInstance().currentUserLocation.getLongitude()).substring(0, 8).contains(String.valueOf(clickMarkerLatLng.longitude).substring(0, 8)))
{
Toast.makeText(getApplicationContext(), "This your current location, navigation is not needed.", Toast.LENGTH_SHORT).show();
}
else
{
FlurryAgent.onEvent("Start navigation window was clicked from daily map");
tasksRepository = SGTasksListAppObj.getInstance().tasksRepository.getTasksRepository();
for (Task tmptask : tasksRepository)
{
String tempTaskLat = String.valueOf(tmptask.getLatitude());
String tempTaskLng = String.valueOf(tmptask.getLongtitude());
Log.d(TAG, String.valueOf(tmptask.getLatitude())+","+String.valueOf(clickMarkerLatLng.latitude).substring(0, 8));
if (tempTaskLat.contains(String.valueOf(clickMarkerLatLng.latitude).substring(0, 8)) && tempTaskLng.contains(String.valueOf(clickMarkerLatLng.longitude).substring(0, 8)))
{
task = tmptask;
break;
}
}
Intent intent = new Intent(getApplicationContext() ,RoadDirectionsActivity.class);
intent.putExtra(TasksListActivity.KEY_ID, task.getId());
startActivity(intent);
}
}
else
{
Toast.makeText(getApplicationContext(), "Your current location could not be found,\nNavigation is not possible.", Toast.LENGTH_SHORT).show();
}
}
});
// Returning the view containing InfoWindow contents
return v;
}
});
In one of my projects I created a new class MarkerSnippet and added all information to this class, e.g.:
public class MarkerSnippet {
private String foo;
private String bar;
public MarkerSnippet(String foo, String bar) {
this.foo = foo;
this.bar = bar;
}
// getter and setter for foo and bar
}
Then I create an instance of MarkerSnippet for each marker and add it as a JSON string (since the snippet only accepts Strings) using GSON:
Gson gson = new Gson(); // remark: only one Gson instane is needed
String fooContent = "myFoo";
String barContent = "myBar";
String snippetString = gson.toJson(new MarkerSnippet(fooContent, barContent));
map.addMarker(
new MarkerOptions().position(position)
.title(title)
.snippet(snippetString)
);
Then in your InfoWindowAdapter you need to convert your JSON string to the MarkerSnippet and add only this part of the snippet to your view that you want to show.