Google Maps Android point in polygon - android

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();
}
}
});

Related

Check if route contains a specific coordinates or not

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.

ClusterManager OnClusterClickListener not called

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)

Unable to add parse image to custom Google Map info window

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.

Adding markers from url with Picasso

I'm adding markers to my map from a url using the Picasso library
As a marker isn't an ImageView I tried to use a Target instead
for(int x =0; x < mapIcon_url.length; x++){
Picasso.with(getActivity()).load(mapIcon_url[x]).resize(marker_size, marker_size+15).into(new Target() {
#Override
public void onSuccess(Bitmap b) {
bitmapMarker = BitmapDescriptorFactory.fromBitmap(b);
//create marker option
if(b != null)
markerOptions = new MarkerOptions().position(marker_position).icon(bitmapMarker));
else
markerOptions = new MarkerOptions().position(marker_position).icon(BitmapDescriptorFactory.fromResource(R.drawable.placeholder_pin)).snippet(String.valueOf(x));
marker = map.addMarker(markerOptions);
}
#Override
public void onError() {
//create marker option
markerOptions = new MarkerOptions().position(marker_position).icon(BitmapDescriptorFactory.fromResource(R.drawable.placeholder_pin)).snippet(String.valueOf(x));
marker = map.addMarker(markerOptions);
}
});
}
I'm doing this in a loop to add about 20 markers but I find that on first run of the code only 5 or 7 markers are added so I've switched to using the lib and an AsyncTask like this.
for(int x =0; x < mapIcon_url.length; x++){
new AddMarker().execute(mapIcon_url[x]);
}
public class AddMarker extends AsyncTask<String, Integer, BitmapDescriptor> {
BitmapDescriptor bitmapMarker1;
VenueDetails myVenue;
#Override
protected BitmapDescriptor doInBackground(String... url) {
myUrl = url[0];
try {
bitmapMarker1 = BitmapDescriptorFactory.fromBitmap(Picasso.with(getActivity()).load(myUrl).resize(marker_size, marker_size+15).get());
} catch (IOException e) {
e.printStackTrace();
}
return bitmapMarker1;
}
protected void onPostExecute(BitmapDescriptor icon) {
try {
map.addMarker(new MarkerOptions().position(marker_position).icon(icon)));
} catch (Exception e) {
e.printStackTrace();
}
}
}
However I'm a bit worried this method could give me some issues when I have alot of markers say about 100. My question would be is this the best way to do this and if not what other options can I try.
You have to keep a reference for each Target, otherwise the system
automatically releases them when the garbage collector is invoked.
So, the better solution is add each Target to a HashSet and then in
onBitmapLoaded() and onBitmapFailed methods from Target, remove the
Target itself from the set.
Thank you for the suggestion, now my code work perfectly. Below the pieces of code that implement your suggestion.
[...]//Global var
private Set<PoiTarget> poiTargets = new HashSet<PoiTarget>();
[...]
private void somewhere(){
PoiTarget pt;
for(Item item: data) {
m = map.addMarker(new MarkerOptions()
.position(new LatLng(item.latitude, item.longitude))
.title(item.title));
pt = new PoiTarget(m);
poiTargets.add(pt);
Picasso.with(context)
.load(mapImageURLString)
.into(pt);
}
}
[...]
//--------------------------------------------------------
// Inner class
//--------------------------------------------------------
class PoiTarget implements Target{
private Marker m;
public PoiTarget(Marker m) { this.m = m; }
#Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
m.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
poiTargets.remove(this);
Tools.msg(" #+ Set bitmap for "+m.getTitle()+" PT size: #"+poiTargets.size());
}
#Override public void onBitmapFailed(Drawable errorDrawable) {
Tools.msg(" #+ [ERROR] Don't set bitmap for "+m.getTitle());
poiTargets.remove(this);
}
#Override public void onPrepareLoad(Drawable placeHolderDrawable) {
}
}
You have to keep a reference for each Target, otherwise the system automatically releases them when the garbage collector is invoked.
So, the better solution is add each Target to a HashSet and then in onBitmapLoaded() and onBitmapFailed methods from Target, remove the Target itself from the set.

Google maps v2 marker using two snippet

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.

Categories

Resources