Clustering User-Input Markers (Google Maps x Android Studio) - android

I am trying to cluster markers that users input onMapLongClick but I can't seem to figure it out. All the tutorials/samples I've found show how to cluster for objects that are at a predetermined LatLng. This won't work for what I want to do because the point is not known until the user places a marker. For example, if users input twenty markers while using the app in a certain location at zoom level 7, then I want to be able to cluster them based on distance or a grid or however when they zoom to level 6. I am using Google Maps with Android Studio. Can anyone please help? I've been working for awhile on this...Here is the code I have so far. Thank you!
public class BasicMapDemoActivity extends AppCompatActivity implements
OnMapReadyCallback {
GoogleMap mMap;
private UiSettings mUiSettings;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.basic_demo);
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
if (item.getItemId() == R.id.menu_legal) {
startActivity(new Intent(this, LegalInfoActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onMapReady(GoogleMap map) {
mMap = map;
mUiSettings = mMap.getUiSettings();
mUiSettings.setZoomControlsEnabled(true);
mUiSettings.setScrollGesturesEnabled(true);
mUiSettings.setZoomGesturesEnabled(true);
mMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
#Override
public void onMapLongClick(LatLng point) {
mMap.addMarker(new MarkerOptions()
.position(point)
.snippet("this is a snippet"));
}
});
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
}
});
mMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition position) {
float maxZoom = 7.0f;
if (position.zoom > maxZoom) {
mMap.animateCamera(CameraUpdateFactory.zoomTo(maxZoom));
}
}
});
}
}

The easiest way is to attach a ClusterManager to your map. It will automatically animate the markers from cluster at their position (or cluster them, when you zoom out).
The clustering is part of another project, called android-map-utils which can be found here:
https://github.com/googlemaps/android-maps-utils
They have a great demo application in the repository, I believe you will find the functionality you need there.
Example for adding items to ClusterManager, after you map has been initialised.
set up the cluster manager
mClusterManager = new ClusterManager<>(BrowseLocationsActivity.this, googleMap);
mClusterManager.setClusterOnlyVisibleArea(true);
mClusterManager.setAlgorithm(new VisibleNonHierarchicalDistanceBasedAlgorithm<MapMarkerItem>(metrics.widthPixels, metrics.heightPixels));
when you need to add a new item to your cluster, just call
mClusterManager.addItem(new MapMarkerItem(latitude, longitude));
mClusterManager.cluster();
Note thatMapMarkerItem is a custom class, that implementes ClusterItem from the library.

Related

How to hide map pins by tapping an option in the menu?

I am creating an app which displays several pins which have different categories according to colour, similar to displaying hotels, restaurants etc. I have a menu which when I select the option I want to hide that particular category but I am having trouble hiding the pins, I'm just not sure what code to use for this.
I've tried to use setVisibility(invisible) but I don't know where this should go.
This is within my main activity - the menu.
public class AR_MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
//trying to get the menu options to do something
switch(item.getItemId()){
case R.id.poi1:
Toast.makeText(this, "Enemy Selected", Toast.LENGTH_SHORT).show();
return true;
case R.id.poi2:
Toast.makeText(this, "IED Selected", Toast.LENGTH_SHORT).show();
return true;
case R.id.poi3:
Toast.makeText(this, "Obstruction Selected", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
This is where the map pins are created, also within main activity.
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMyLocationEnabled(true);
LocationManager and listener
locationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
// Add a marker in Sydney and move the camera
LatLng userLocation = new LatLng(location.getLatitude(), location.getLongitude());
mMap.clear();
mMap.addMarker(new MarkerOptions().position(userLocation).title("AR Projects HQ")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 16));
LatLng obstruction = new LatLng(50.878640, -2.108940);
mMap.addMarker(new MarkerOptions().position(obstruction).title("Obstruction").snippet("Fallen Power Lines. Eng notified.")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE)));
The program runs no problem and displays a toast to display which option has been selected.
set varible to mMap.addMarker
Marker mark = mMap.addMarker(new MarkerOptions() ....
mark.setVisible(false);
this Marker can add to array if you want
List<Marker> markList = new ArrayList<>();
////
Marker mark = mMap.addMarker(new MarkerOptions() ....
markList.add(mark);
//// and then you can hide with loop
for (Marker miaw : markList) {
miaw.setVisible(false);
}

Android: error with map fragment on navigation drawer and permission check

I started working on an old application i have that uses a map fragment on a navigation drawer. It used to work OK but now, with the new permisson thing, I get some errors. I have searched on SO and on the internet generally but I dont know what I am missing. My map Fragment is below
public class Fragment_maps extends android.support.v4.app.Fragment implements OnMapLongClickListener, OnMapClickListener, OnMapReadyCallback {
MapView mMapView;
GoogleMap googleMap;
#Override
public void onMapReady(GoogleMap googleMap) {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// inflate and return the layout
View v = inflater.inflate(R.layout.fragment_maps, container, false);
mMapView = (MapView) v.findViewById(R.id.map);
mMapView.onCreate(savedInstanceState);
//activate menu button
setHasOptionsMenu(true);
mMapView.onResume();// needed to get the map to display immediately
try {
MapsInitializer.initialize(getActivity().getApplicationContext());
} catch (Exception e) {
e.printStackTrace();
}
//get the map
mMapView.getMapAsync(this);
// Detect location
googleMap.setMyLocationEnabled(true);
googleMap.getUiSettings().setMyLocationButtonEnabled(false);
//googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
// Turns traffic layer on
googleMap.setTrafficEnabled(true);
// Enables indoor maps
googleMap.setIndoorEnabled(true);
// Enables indoor maps
googleMap.setIndoorEnabled(true);
// Turns on 3D buildings
googleMap.setBuildingsEnabled(true);
// Show Zoom buttons
googleMap.getUiSettings().setZoomControlsEnabled(true);
// latitude and longitude
double latitude = 40.639350;
double longitude = 22.944607;
googleMap.setOnMapLongClickListener(this);
googleMap.setOnMapClickListener(this);
// create marker
MarkerOptions thessaloniki = new MarkerOptions().position(new LatLng(latitude, longitude)).title("Thessaloniki");
// Changing marker icon
thessaloniki.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
// adding marker
googleMap.addMarker(thessaloniki);
CameraPosition cameraPositionThess = new CameraPosition.Builder() .target(new LatLng(40.639350, 22.944607)).zoom(12).build();
googleMap.animateCamera(CameraUpdateFactory .newCameraPosition(cameraPositionThess));
// Perform any camera updates here
return v;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_maps, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d("onOptionsItemSelected","yes");
switch (item.getItemId()) {
case R.id.HYBRID:
googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
return true;
case R.id.SATELLITE:
googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
return true;
case R.id.TERRAIN:
googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
return true;
case R.id.NORMAL:
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onMapClick(LatLng point) {
Toast.makeText(getActivity(),point.toString(),Toast.LENGTH_SHORT).show();
googleMap.animateCamera(CameraUpdateFactory.newLatLng(point));
}
#Override
public void onMapLongClick(LatLng point) {
if (SelectUserActivity.flagOwner){
googleMap.addMarker(new MarkerOptions()
.position(point)
.title(MainActivity.onomaxarth)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
Toast.makeText(getActivity(),"Hotel pinned at: "+point.toString(),Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getActivity(),point.toString(),Toast.LENGTH_SHORT).show();
}
}
#Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
#Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
I used googleMap = mMapView.getMap(); to get the map but i have change it with mMapView.getMapAsync(this); by implementing OnMapReadyCallback and it forced me to create the onMapReady method, which I dont know how it is different from the onCreateView method so i leave it empty.
Now i get an error on googleMap.setMyLocationEnabled(true); for permission and when i debug my app the googleMap object is null.
When I run it, on selecting the map fragment the app crashes and terminates the activity that holds the Fragments.
On the Manifest i have
android:minSdkVersion="17"
android:targetSdkVersion="23"
and my gradle dependencies are
compile 'com.android.support:support-v4:24.2.1'
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.google.android.gms:play-services:+'
What am i missing here? How can i use the permission in the fragment and why googleMap is empty?
Move this code from your onCreateView to your onMapReady:
// Detect location
googleMap.setMyLocationEnabled(true);
googleMap.getUiSettings().setMyLocationButtonEnabled(false);
//googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
// Turns traffic layer on
googleMap.setTrafficEnabled(true);
// Enables indoor maps
googleMap.setIndoorEnabled(true);
// Enables indoor maps
googleMap.setIndoorEnabled(true);
// Turns on 3D buildings
googleMap.setBuildingsEnabled(true);
// Show Zoom buttons
googleMap.getUiSettings().setZoomControlsEnabled(true);
// latitude and longitude
double latitude = 40.639350;
double longitude = 22.944607;
googleMap.setOnMapLongClickListener(this);
googleMap.setOnMapClickListener(this);
// create marker
MarkerOptions thessaloniki = new MarkerOptions().position(new LatLng(latitude, longitude)).title("Thessaloniki");
// Changing marker icon
thessaloniki.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
// adding marker
googleMap.addMarker(thessaloniki);
CameraPosition cameraPositionThess = new CameraPosition.Builder() .target(new LatLng(40.639350, 22.944607)).zoom(12).build();
googleMap.animateCamera(CameraUpdateFactory .newCameraPosition(cameraPositionThess));
The line mMapView.getMapAsync(this); prepares the map and onMapReady gets called when the map is ready to be used.
Also, if you have defined private GoogleMap googleMap;, you will want to add this to the beginning of your onMapReady method:
this.googleMap = googleMap;

reposition a marker when I press button android API V2

I have the following code and, when I press a menu button I would like to reposition the same marker and the camera but I do not have idea how to do it, I've read oficial documentation but I haven't found info. I'm using repositionMarker() method to do it, but Im not sure what to do. Thanks
public class Init extends AppCompatActivity implements OnMapReadyCallback
{
private MapFragment map;
static final LatLng PERTH = new LatLng(19.0436, -98.1981);
private CameraUpdate camaraloc, camaraloczoom;
private Marker markerloc;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inicio);
map = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
if (map != null)
{
map.getMapAsync(this);
}
}
#Override
public void onMapReady(GoogleMap map)
{
map.setMyLocationEnabled(true);
camaraloc = CameraUpdateFactory.newLatLng(PERTH);
camaraloczoom = CameraUpdateFactory.zoomTo(8);
map.moveCamera(camaraloc);
map.animateCamera(camaraloczoom);
markerloc = map.addMarker(new MarkerOptions().position(PERTH)
.title("city").snippet("esp").icon(BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.menu_inicio, menu);
return true;
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.home:
drawerLayout.openDrawer(GravityCompat.START);
return true;
case R.id.action_settings:
Toast.makeText(this, "name marker: "+markerloc.getTitle(), Toast.LENGTH_SHORT).show();
reposicionMarker();
return true;
}
return super.onOptionsItemSelected(item);
}
public void repositionMarker()
{
camaraloc = CameraUpdateFactory.newLatLng(new LatLng(16.65, -91.8658));
camaraloczoom = CameraUpdateFactory.zoomTo(15);
if ( markerloc != null )
markerloc.remove();
markerloc.setPosition(new LatLng(16.65, -91.8658));
// here is where I dont know what to do
}
}
Calling setLocation on the Marker should work, for changing its location. What seems to be your problem is that you are actually removing the marker right before you set the new location.

marker.showInfoWindow() has no effect using google map API V2 Lite Mode

Google doc is very clear about using showInfoWindow with Markers in Lite Mode:
if you set the title() of a marker, the default info window will
appear when the user taps the marker. You can show the info window
programmatically by calling showInfoWindow() on the marker. You can
also create custom info windows via the InfoWindowAdapter interface.
https://developers.google.com/maps/documentation/android/lite
Here is a part of my code:
#Override
public void onMapReady(GoogleMap googleMap) {
googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
}
});
googleMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
#Override
public void onMapLongClick(LatLng latLng) {
}
});
googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
marker.showInfoWindow();
return true;
}
});
BitmapDescriptor skierIcon = BitmapDescriptorFactory.fromResource(R.drawable.skiericon);
markers.add(googleMap.addMarker(new MarkerOptions()
.position(new LatLng(mountain_latitude+0.01, mountain_longitude+0.01))
.title("Bob")
.visible(true)
.icon(skierIcon)));
markers.add(googleMap.addMarker(new MarkerOptions()
.position(new LatLng(mountain_latitude-0.01, mountain_longitude-0.01))
.title("Alice")
.icon(skierIcon)));
for(Marker marker: this.markers){
marker.showInfoWindow();
boolean ret = marker.isInfoWindowShown();
}
}
My problem is that marker.isInfoWindowShown() always returns false.
Here is how I call it
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.map, mapFragment);
fragmentTransaction.commit();
mapFragment.getMapAsync(this);
Remember the rendering of the map is an asynchronous process, you create your Markers inside onMapReady() and after the execution of this method, then you can check if your markers are being shown.

How to get lat n lng center point of map in android?

I am building an android application where user is getting latLng by long touching in Google map.
Here is the code:
public class MainActivitytut extends FragmentActivity{
GoogleMap googleMap;
MarkerOptions markerOptions;
LatLng latLng;
private TextView myAddress;
String lat;
TextView txtmapinfo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maintut);
//onBackPressed();
SupportMapFragment supportMapFragment = (SupportMapFragment)
getSupportFragmentManager().findFragmentById(R.id.map);
// Getting a reference to the map
googleMap = supportMapFragment.getMap();
// Setting a click event handler for the map
googleMap.setOnMapClickListener(new OnMapClickListener() {
#Override
public void onMapClick(LatLng arg0) {
// Getting the Latitude and Longitude of the touched location
latLng = arg0;
lat = latLng.toString();
// Toast.makeText(getApplicationContext(), lat,
// Toast.LENGTH_LONG).show();
// getMyLocationAddress();
// Clears the previously touched position
googleMap.clear();
// Animating to the touched position
googleMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
// Creating a marker
markerOptions = new MarkerOptions();
// Setting the position for the marker
markerOptions.position(latLng);
// Placing a marker on the touched position
googleMap.addMarker(markerOptions);
// Adding Marker on the touched location with address
new ReverseGeocodingTask(getBaseContext()).execute(latLng);
}
});
}
protected void putExtra(String string, CharSequence text) {
// TODO Auto-generated method stub
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is
// present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
I had used lat = map.getCameraPosition().target; and when I toast the value of lat, it is toasting 0.0
What I need is that when on swiping the map the latlng change and toast.
Wait until the map has loaded and then call getCameraPosition:
mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
#Override
public void onMapLoaded() {
LatLng pos = mMap.getCameraPosition().target;
Log.e("", "Pos: " + pos.toString());
mMap.addMarker(new MarkerOptions().position(pos));
}
});

Categories

Resources