I made simple application where I get markers based on screen coordinates from the server. Problem is that markers doesn't appear on map immediately. User user must zoom in or zoom out only then marker is visible. Why is that? Is it possible to show marker as soon when marker data is downloaded from server? Or is it possible to somehow refresh map? I know that in previous version there was method map.invalidate() that is basically what I need to have now. Unfortunately this method is not available now.
I will add code snippet how my markers is added
#Override
protected void onPostExecute(ArrayList<MarkerItemData> markerItemData) {
super.onPostExecute(markerItemData);
if(markerItemData != null) {
mClusterManager.addItems(markerItemData);
}
}
It needs re-clustering again.
mClusterManager.addItems(markerItemData);
mClusterManager.cluster();
Because, when you add or remove an ClusterItem (MarkerItemData), it just performs the algorithm and calculates clusters. But does not render on map
Finally, ClusterManager listens onCameraIdle event(includes zoom events) and invokes cluster() method internally. This is the answer of user must zoom in or zoom out only then marker is visible.
From the javadoc here, you need to recluster your markers after adding them to your ClusterManager doing mClusterManager.cluster().
Related
I am working with Google Maps. Let's say I have around 1 million position markers stored in my database. What I want to do is load or display only those markers that should be on the part of map that is currently shown on screen. (For example, if my map is showing Asia, it should only show markers that are in Asia; if I move to any other place on the map, it should show markers in that region.) I'm doing this so I don't have to load the entire database at once, since that can cause delays in the app. I tried using Spatialite, but I didn't find a good tutorial, or information on how to use it. This is one of the links I followed, but I didn't get a good idea. Is there any other way to do this, or is Spatialite the best option?
You will have to figure out the best way to retrieve these positions from your database, but one way to add markers based on the map's camera's position is to add relevant markers in GoogleMap.OnCameraChangeListener.
// Check to see if your GoogleMap variable exists.
if (mGoogleMap != null) {
// Respond to camera movements.
mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
#Override
public void onCameraMove() {
// Get the current bounds of the map's visible region.
LatLngBounds bounds = mGoogleMap.getProjection().getVisibleRegion().latLngBounds;
// Loop through your list of positions.
for (LatLng latLng: yourLatLngList) {
// If a position is inside of the bounds,
if (bounds.contains(latLng)) {
// Add the marker.
mGoogleMap.addMarker(new MarkerOptions()
.position(latLng));
}
}
}
});
}
I wouldn't suggest looping through a million positions every time the map's camera's position is changed. I think the best way for you to do it is to get the current bounds of the map's visible region when the camera is moved, then send the bounds in a call to your backend on a different thread, and have your backend do the work of finding the positions that fit in those bounds and then return that list back to your app where you can add markers accordingly.
I have a simple app that show a lot of markers on a map (Google Map). At the moment I have over 3,000 markers and this number keeps growing as the database gets bigger.
I also have a few checkboxes that dictate which markers are to be shown, vice versa.
Originally I was adding each marker like this (inside a loop going through every location)
Marker marker;
marker = mMap.addMarker (markerOptions);
mMarkerArrayList.add(marker);
Then when the user interacted with the checkboxes, I simply made markers visible/invisible. This is faster removing, and re-adding the markers.
The code in the Checkbox Change Listener was something like this:
for (Marker marker : mMarkerArrayList) {
if (condition) {
marker.setVisible(false);
}
}
And then make the visible again on another change of the checkbox.
However, adding all these markers individually in the beginning was taking a long time (1-2 seconds) and as the markers can only be added in the UI thread, it was freezing the UI (including my progress bar) for that amount of time.
After a lot of research, and not getting anywhere, the only thing I could do was add the markers using the ClusterManager (android-maps-utils library). This loads twice as fast, and does not block my UI.
Adding code is something like this (here myLocation is the object of my MyLocation class which holds the lcoation and relevant data for each point).
for (MyLocation myLocation : mMyLocationArrayList) {
mClusterManager.addItem(myLocation)
}
Now the issue is linking the checkboxes to these ClusterItem objects. I cannot find any method, or field in the library to change the visibility of these markers (ClusterItem). In the previous method (changing the visibility) was almost instantaneous (fast enough that the user would not feel any lag). However, now, I need to add and remove these markers everytime, and there is a lag, and it is very obvious to the user.
Does anyone have any suggestions?
You should be able to use mClusterManager.getMarkerCollection().getMarkers() in order to get the Marker collection, and then hide certain Markers in the same way as you were before:
Collection<Marker> markerCollection = mClusterManager.getMarkerCollection().getMarkers();
for (Marker marker : markerCollection) {
if (condition) {
marker.setVisible(false);
}
}
#Khash I have had some success with the following code (i.e. hides both the Markers and Clusters), although I experience a similar issue when I zoom the map in or out the Markers and Clusters re-appear.
Hope this helps, happy coding!
if (hide) {
/* Hide all Markers and Clusters */
mMyClusterManager.getMarkerCollection().hideAll();
mMyClusterManager.getClusterMarkerCollection().hideAll();
} else {
/* Show all Markers and Clusters */
mMyClusterManager.getMarkerCollection().showAll();
mMyClusterManager.getClusterMarkerCollection().showAll();
}
I have a problem with using Google maps API on Android. I have a button which removes the selected marker off the maps interface, and information about it from the SQLite db that I have set up. Although my only problem is once multiple markers are on the map this feature stops and doesn't remove them:
Below shows the method which removes the marker from the maps and replaces them. As I said this works perfectly fine with a single marker and my testing has been a success, but with multiple it does not work.
I have an onclicklisterner for the markers which displays the information and a popup box for the marker, for the user to remove the marker they must click the marker which sets the global variable to that object then once the remove button is pressed the removeMarker() method is called. The getAllMarkers() method loops through a SQLite db and pulls information and adds to the maps.
End problem: Removing a marker when multiple markers are placed on the map doesn't work. Only works when a single marker is placed on the map.
Marker lastOpened = null;
To remove the information from the db the condition in the if statement returns a boolean value if it has been done:
if(this.mDbHelper.deleteLine(lastOpened.getTitle()))
Remove method
public void removeMarker(){
if(this.lastOpened != null){
if(this.mDbHelper.deleteLine(lastOpened.getTitle())){
lastOpened.remove();
getAllMarkers();
}
}
}
Thanks
You can either use googleMap.clear() or you can store your Markers in a collection of kind and remove them in a loop:
private ArrayList<Marker> mMarkers;
...
private void removeMarkers() {
for (Marker marker: mMarkers) {
marker.remove();
}
mMarkers.clear();
}
Here's a related ticket discuss how to remove marker: Remove a marker from a GoogleMap
I'm trying to implement app in which you can add your own marker which will be given a shutdown time. To do so I need to know how to manage my markers. Let's say I have array list of users with assigned unique ID.
private ArrayList<User> userList = new ArrayList<>();
Then I will create array list of markers which will contain information like Latitude, Longitude, Title, owner's ID and deadline.
private ArrayList<MyMarker> mMarkersArray = new ArrayList<MyMarker>();
Next whenever user will activate add marker method, new marker will be pushed to my list of markers. Ideologically everything seems nice and easy, furthermore creating new object looks like this:
Marker mMarker = mMap.addMarker(new MarkerOptions() (...) );
but when it comes to managing specific markers it seems like I'm missing something. There will be some trigger method which will check the deadline of all markers (or rather first one on the 'sorted by deadline' list) and then it should remove (not hide, because I think it would be inefficient from the memory point of view). How to achieve this? I can't add some custom variable like ID to markers (so I could then find the one I'm interested in) and I'm a bit lost.
There is a way to achieve this by clearing whole map and then rendering again all markers except the inactive, but as far as I'm concerned it's very inefficient and there has to be better solution.
If you want to remove a specific marker from the map, you can just call the remove(). method.
Sample code to remove a marker from MapView and HashMap:
for (Marker marker : hm.keySet()) {
if (hm.get(marker).equals(deadline)) {
marker.remove();
hm.remove(marker);
}
}
You dont need to clear the entire MapView, if you just call remove() method on specific marker.
Forgive me for being new to android app building.
My plan is to build an app that would take a city and open a new activity for it. The problem is I really don't know how to go about that. My plan would be very similar to how the app yik yak does it where you go put a marker in a certain area and it brings you to the activity for that location. I believe yik yak only shows the ones that are close to you but my plan was to take you to an activity for that location. Is that possible to do it that way or should I take yik yak's route on it and only show things that are within a certain radius of you?
Where can I get started on learning how to do that?
First, you need to choose a provider for your maps.
I would say google map is a good start as you suggested in the tag, but beware, it might not be available on some Chinese devices without play services.
You can follow the documentation here for a quick start
https://developers.google.com/maps/documentation/android/
Regarding the number of pins you want to put on your map, I see no problem to display a lot of them, you just have to group markers as the user zooms out, so you don't have 10 pins overlapping themselves.
So if in a quite zoomed state, the user clicks a group of markers, you can display a dialog to choose the city.
If the user zooms in a lot and clicks a particular pin, then you can start an activity.
Your main concern is listening for a zoom level change, like that:
mMap.setOnCameraChangeListener(new OnCameraChangeListener() {
private float currentZoom = -1;
#Override
public void onCameraChange(CameraPosition pos) {
if (pos.zoom != currentZoom){
currentZoom = pos.zoom;
// do you action here
}
}
});
Credits: https://stackoverflow.com/a/15046761/689710
Then, you can create a Map of Lists, the keys of the map will be the a custom lat / long object. Let's call it Pin. Pin provides it a custom isCloseTo method (taking a zoomlevel in params, and an other Pin object).
For each city you want to add on the map
For each key in the map
If the Pin object of your city isCloseTo the Pin key of the map
Add it to the list for that key
Else
Add a new Map entry with you city Pin as key and a list with your city as value
You Pin.isCloseTo method will be somehow similar to that:
https://stackoverflow.com/a/18170277/689710
Returning true or false according to "dist" return and your zoom level.
When you processed all your cities, you can browse the map and create a marker for each Pin key.
In a zoomed in state, you will have a Map with lists containing only one item, but i don't think it's much a problem.
You know yik yak is not starting a new activity when the place on the map is clicked. It rather updates the data underneath it when a new place is clicked. I think what you mean is you want to refresh/change the data displayed when a new city on google maps is clicked?