How to set method onItemClick to open a Google Maps? - android

I'm building an app, and I run on a problem with Google Maps. I wrote most of the code, but I don't how how to set that when user clicks on item(method onItemClick), in my case I have ListView on Firebase that is showing Tours of concerts, which you can see here:my tours listview to open a specific place and show it on map. For example, user clicks on Anaheim, CA concert and it shows where that place is. Thanks in advance.
public class MapActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final int REQUEST_LOCATION_PERMISSION = 10;
private GoogleMap.OnMapClickListener mCustomOnMapClickListener;
private GoogleMap mGoogleMap;
private MapFragment mMapFragment;
#BindView(R.id.lvTours) ListView lvTours;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
this.initialize();
}
public void initialize(){
this.mMapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.fGoogleMap);
this.mMapFragment.getMapAsync(this);
this.mCustomOnMapClickListener = new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
MarkerOptions newMarkerOptions = new MarkerOptions();
newMarkerOptions.icon(BitmapDescriptorFactory.fromResource(R.mipmap.tour));
newMarkerOptions.title("Tour");
newMarkerOptions.snippet("It' was here!");
newMarkerOptions.position(latLng);
mGoogleMap.addMarker(newMarkerOptions);
}
};
}
#Override
public void onMapReady(GoogleMap googleMap) {
this.mGoogleMap = googleMap;
UiSettings uiSettings = this.mGoogleMap.getUiSettings();
uiSettings.setZoomControlsEnabled(true);
uiSettings.setMyLocationButtonEnabled(true);
uiSettings.setZoomGesturesEnabled(true);
this.mGoogleMap.setOnMapClickListener(this.mCustomOnMapClickListener);
}
private boolean hasLocationPermission() {
String LocationPermission = android.Manifest.permission.ACCESS_FINE_LOCATION;
int status = ContextCompat.checkSelfPermission(this, LocationPermission);
if (status == PackageManager.PERMISSION_GRANTED) {
this.mGoogleMap.setMyLocationEnabled(true);
return true;
}
return false;
}
private void requestPermission() {
String[] permission = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
ActivityCompat.requestPermissions(MapActivity.this, permission, REQUEST_LOCATION_PERMISSION);
}
#OnItemClick(R.id.lvTours)
public void onClick()
{
}
}

Since you have your coordinates, you can build a LatLng(latitude, longitude) object
then you can move the camera of your map like this:
build a new camera position using CameraPosition.Builder() and then ask to your mGoogleMap to animate to that position:
CameraPosition position = CameraPosition.builder()
.target(location)
.zoom(16f)
.bearing(0.0f)
.tilt(0.0f)
.build();
mGoogleMap.animateCamera(CameraUpdateFactory.newCameraPosition(position), null)
using that position you can even put a marker on the map:
mGoogleMap.addMarker(new MarkerOptions().position(position)
.title("some title"));

Related

Android Google maps markerClickListener for clusterItems

I'm trying to implement clusters for my googlemaps markers. Currently I have some custom marker colors with an API call that fires when you click on them. When those results are loaded, there will open a bottomsheet with the specific information of that marker.
I want to keep the same functionalities (custom markers/clickListeners/radius around markers), but add clusters when zoomed out. I've looked at different sources for help:
Android cluster and marker clicks
Android marker-clustering
MarkerManager.java
But i'm not sure how to implement the custom marker and listener for the clusters items. I'am able to get clusters with standard markers without clicklisteners. Here are some images for illustration:
This is my current situation (I want to cluster these markers). As you can see, the bottom sheet pops up when I click on a marker
This is what I'm currently able to do, but I want to combine it with the previous picture
Here is the important part of my code of my map Fragment, (The Point class does implement the ClusterItem interface):
private Map<Marker, Point> retailerInfo = new HashMap<>();
private void markGeofencesOnMap() {
new GeofenceAreasRequest().getAllAreas(new GeofenceAreasCallback() {
#Override
public void onAreasLoaded(List<Point> points) {
for (final Point point : points) {
markerForGeofence(point);
drawRadius(point);
}
}
#Override
public void failedOnAreasLoaded(int message) {
Snackbar.make(coordinatorLayout, R.string.failed_loading_areas, Snackbar.LENGTH_LONG).show();
}
});
}
private void markerForGeofence(Point point) {
LatLng latLng = new LatLng(point.getLatitude(), point.getLongitude());
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.flat(true)
.title(point.getTitle())
.icon(BitmapDescriptorFactory.defaultMarker(195));
// markerManager.getCollection("markerCollection").addMarker(markerOptions);
// markerManager.getCollection("markerCollection").setOnMarkerClickListener(this);
// mClusterManager.addItem(point);
geoFenceMarker = googleMap.addMarker(markerOptions);
retailerInfo.put(geoFenceMarker, point);
}
private void drawRadius(Point point) {
CircleOptions circleOptions = new CircleOptions()
.center(geoFenceMarker.getPosition())
.strokeColor(Color.argb(50, 70, 70, 70))
.fillColor(Color.argb(100, 150, 150, 150))
.radius(point.getRadius());
googleMap.addCircle(circleOptions);
}
private void googleMapSettings() {
int permissionCheck = ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
googleMap.setMyLocationEnabled(true);
} else {
SystemRequirementsChecker.checkWithDefaultDialogs(getActivity());
}
googleMap.getUiSettings().setZoomControlsEnabled(true);
CameraPosition cameraPosition = new CameraPosition.Builder().target(getLastLocation()).zoom(12).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
googleMap.setOnMapClickListener(this);
// markerManager = new MarkerManager(googleMap);
// markerManager.newCollection("markerCollection");
// mClusterManager = new ClusterManager<Point>(getActivity(), googleMap );//, markerManager);
// googleMap.setOnMarkerClickListener(mClusterManager); //markerManager);
googleMap.setOnCameraIdleListener(mClusterManager);
googleMap.setOnMarkerClickListener(this);
}
#Override
public boolean onMarkerClick(Marker marker) {
if (retailerInfo != null) {
String retailerId = retailerInfo.get(marker).getRetailer();
new RetailersRequest().getRetailer(retailerId, new RetailersCallback() {
#Override
public void onRetailersLoad(List<Retailer> retailers) {
for (final Retailer retailer : retailers) {
mMapRetailerName.setText(retailer.getName());
mMapRetailerStreet.setText(retailer.getStreet());
mMapRetailerHouseNr.setText(retailer.getHousenumber());
mMapRetailerPostalCode.setText(retailer.getPostalCode());
mMapRetailerCity.setText(retailer.getCity());
}
bottomSheet.setVisibility(View.VISIBLE);
mBottomSheetBehavior.setPeekHeight(400);
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
#Override
public void failedOnRetailersLoaded(int code) {
Snackbar.make(coordinatorLayout, getString(R.string.failed_loading_retailers) + code, Snackbar.LENGTH_LONG).show();
}
});
CameraPosition cameraPosition = new CameraPosition.Builder().target(marker.getPosition()).zoom(14).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
return true;
}
#Override
public void onMapClick(LatLng latLng) {
bottomSheet.setVisibility(View.GONE);
}
#Override
public void onMapReady(GoogleMap googleMap) {
this.googleMap = googleMap;
googleMapSettings();
markGeofencesOnMap();
}
I hope someone can help me out in the right direction. Thx!
Okay, after some more trail and error, I think I've got it sorted out for the most part. All I had to do was to attach a custom DefaultClusterRenderer to my clusterManager. In the mapfragment I could use onClusterItemClick for handling the marker clicks. The one problem I still have is that the circles are not all properly rendered when zooming in and out.
private void markGeofencesOnMap() {
new GeofenceAreasRequest().getAllAreas(new GeofenceAreasCallback() {
#Override
public void onAreasLoaded(List<Point> points) {
for (final Point point : points) {
mClusterManager.addItem(point);
}
}
});
}
private void googleMapSettings() {
mClusterManager = new ClusterManager<Point>(getActivity(), googleMap );
// attach custom renderer behaviour
mClusterManager.setRenderer(new OwnPointRendered(getActivity().getApplicationContext(), googleMap, mClusterManager));
mClusterManager.setOnClusterItemClickListener(this);
googleMap.setOnMarkerClickListener(mClusterManager);
googleMap.setOnCameraIdleListener(mClusterManager);
}
#Override
public boolean onClusterItemClick(ClusterItem clusterItem) {
// cast ClusterItem to my Point class to handle marker clicks
Point retailer = (Point) clusterItem;
String retailerId = retailer.getRetailer();
return true;
}
OwnPointRendered.class
public class OwnPointRendered extends DefaultClusterRenderer<Point> {
private final GoogleMap map;
private List<Circle> circleList = new ArrayList<>();
public OwnPointRendered(Context context, GoogleMap map,
ClusterManager<Point> clusterManager) {
super(context, map, clusterManager);
this.map = map;
}
#Override
protected void onBeforeClusterItemRendered(Point item, MarkerOptions markerOptions) {
markerOptions.flat(true);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(195));
drawRadius(item);
super.onBeforeClusterItemRendered(item, markerOptions);
}
#Override
protected void onClusterRendered(Cluster<Point> cluster, Marker marker) {
super.onClusterRendered(cluster, marker);
for (Circle circle : circleList) {
circle.remove();
}
circleList.clear();
}
private void drawRadius(Point point) {
CircleOptions circleOptions = new CircleOptions()
.center(point.getPosition())
.strokeColor(Color.argb(50, 70, 70, 70))
.fillColor(Color.argb(100, 150, 150, 150))
.radius(point.getRadius());
Circle circle = map.addCircle(circleOptions);
circleList.add(circle);
}

Adding marker on current location

I'm a beginner in android programming and I'm currently working on google maps. What I want to do is to get the current location of the user and then put a marker on that location.
I'm practicing on this but I really can't get it to work. This only shows the current location of the user. But what I want to do is to display a marker on it as well. Any suggestions how to do it?
public class MapsActivity extends AppCompatActivity implements GoogleMap.OnMyLocationButtonClickListener,
OnMapReadyCallback,
ActivityCompat.OnRequestPermissionsResultCallback {
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
private boolean mPermissionDenied = false;
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setOnMyLocationButtonClickListener(this);
enableMyLocation();
}
private void enableMyLocation() {
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
PermissionUtils.requestPermission(this, LOCATION_PERMISSION_REQUEST_CODE,
android.Manifest.permission.ACCESS_FINE_LOCATION, true);
} else if (mMap != null) {
mMap.setMyLocationEnabled(true);
}
}
#Override
public boolean onMyLocationButtonClick() {
Toast.makeText(this, "Showing current location", Toast.LENGTH_SHORT).show();
return false;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) {
return;
}
if (PermissionUtils.isPermissionGranted(permissions, grantResults,
Manifest.permission.ACCESS_FINE_LOCATION)) {
enableMyLocation();
} else {
mPermissionDenied = true;
}
}
Get you last location-
LatLng location = getLatLngFromLastLocation();
Then use this code block to put marker on map:
MarkerOptions markerOptions = new MarkerOptions()
.position(location)
.icon(getMarkerIcon(mProfileTheme.getColorCodeLight()));
public BitmapDescriptor getMarkerIcon(int color) {
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
return BitmapDescriptorFactory.defaultMarker(hsv[0]);
}

How to addMarker directly on GoogleMap after click button setMyLocationEnabled?

I made a code.
In this code, when i click a map, there will be a marker on clicked point.
This is my Code
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(final GoogleMap googleMap) {
mMap = googleMap;
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
} else {
Toast.makeText(getApplicationContext(), "oh, no", Toast.LENGTH_LONG).show();
}
googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
String lat = String.valueOf(point.latitude);
String lng = String.valueOf(point.longitude);
MarkerOptions marker = new MarkerOptions().position(
new LatLng(point.latitude, point.longitude)).title("ok");
mMap.addMarker(marker);
}
});
}
}
Question :
What i want is that when i click SetMylocationEnable button, there also added a new marker. And because i want marker is only one in whole map, another marker that has been in the map before is to be removed. How can i do it? Would you teach me?
You can see what button i saying is, in picture. (picture is from : Enable my location icon Googlemap v2)
mMap.setOnMyLocationButtonClickListener(new OnMyLocationButtonClickListener() {
#Override
public boolean onMyLocationButtonClick() {
Location location = getLocation();
MarkerOptions marker = new MarkerOptions().position(
new LatLng(location.getLatitude(), location.getLongitude())).title("ok");
mMap.addMarker(marker);
return true;
}
});
private Location getLocation() {
LocationManager locationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
return locationManager.getLastKnownLocation(locationManager
.getBestProvider(criteria, false));
}
keep a reference to the marker, if the reference is null then create the marker as you have done, if it is not, then edit the marker and change its location

How to add 2 listeners to map?

i'm developing my first app and i created the following map viewer activity:
public class MapViewer extends Activity implements OnInfoWindowClickListener, ClusterManager.OnClusterClickListener<MyItem> {
private GoogleMap map;
private LatLng defaultLatLng = new LatLng(X, Y);
private int zoomLevel = 5;
private Database db = new Database(this);
private ClusterManager<MyItem> mClusterManager;
private LatLngBounds allowedBounds;
private final LatLng northeast = new LatLng(A, B);
private final LatLng southwest = new LatLng(C, D);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapviewer);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(northeast);
builder.include(southwest);
allowedBounds = builder.build();
try {
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
if (map != null) {
map.setMyLocationEnabled(true);
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
map.getUiSettings().setRotateGesturesEnabled(false);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(defaultLatLng, zoomLevel));
mClusterManager = new ClusterManager<MyItem>(this, map);
mClusterManager.setRenderer(new MyClusterRenderer(this, map, mClusterManager));
mClusterManager.setOnClusterClickListener(this);
map.setOnCameraChangeListener(mClusterManager);
map.setOnMarkerClickListener(mClusterManager);
map.setInfoWindowAdapter(new ClusterInfoWindow(getLayoutInflater()));
map.setOnInfoWindowClickListener(this);
addItems();
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
As you can see i set a listener to map object
map.setOnCameraChangeListener(mClusterManager);
that adds or removes clusters on markers groups, according to zoom level.
Now i would add a listener that checks if user moves on map within some bounds:
map.setOnCameraChangeListener(new OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition cameraPosition) {
checkBounds();
}
});
But it doesn't work. It works only if i remove the previous listener (mClusterManager).
So, how to make both listener working on the same map object?
Thank you in advance for your replies and sorry for my english.
As there's only a set method and no add method, you can only set one listener at a time. But you could delegate from the one listener to the other like this:
map.setOnCameraChangeListener(new OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition cameraPosition) {
checkBounds();
mClusterManager.onCameraChange(cameraPosition);
}
});
Of course mClusterManager does not need to implement the CameraChangeListener interface any more but just needs a method public void onCameraChange(CameraPosition cameraPosition).

android GoogleMap is null, displays fine but can't add markers/polylines

I have a GoogleMap which displays fine (within a SupportMapFragment) and uses the GoogleMapOptions for the target camera location. However, I am unable to add markers/polylines to the GoogleMap. Here is the method for creating the map:
private void createMap(List<LatLng> latLngs) {
if(map == null) {
GoogleMapOptions options = new GoogleMapOptions();
mapFragment = SupportMapFragment.newInstance(options);
map = mapFragment.getMap();
float zoom = 13;
CameraPosition cameraP = new CameraPosition(latLngs.get(0), zoom, 0, 0);
options.camera(cameraP);
//TODO MAP IS NULL - SORT OUT!
// check it has been instantiated
if (map != null) {
Log.d(TAG, "map is not null");
map.clear();
//Calculate target zoom, based on trip size
map.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraP));
// Add LatLngs to polyline
PolylineOptions poly = new PolylineOptions().color(Color.RED);
MarkerOptions startMarker = new MarkerOptions()
.position(latLngs.get(0)).title("Start");
MarkerOptions endMarker = null;
if(latLngs.size() > 1) {
endMarker = new MarkerOptions().position(
latLngs.get(latLngs.size() - 1)).title("End");
}
for (LatLng latLng : latLngs) {
poly.add(latLng);
}
map.addPolyline(poly);
map.addMarker(startMarker);
map.addMarker(endMarker);
}
ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.trip_summary_map_container, mapFragment);
ft.commit();
}
}
As you can see from the inline comments, the map is still null (although it is displaying and using the options). Just can't add things to it. I assume I am not instantiating it properly?
The Activity extends FragmentActivity, and I have set up all the necessary stuff for using the Maps API.
Thank you for any help.
EDIT: I have posted a new answer with the solution I prefer to use now.
I had the same problem some days ago and I solved it extending SupportMapFragment class so that it executes a callback method once the map is finally ready.
public class ExtendedSupportMapFragment extends SupportMapFragment {
public static interface MapReadyListener {
public void mapIsReady(GoogleMap map);
}
#Deprecated
public static SupportMapFragment newInstance() {
return null;
}
#Deprecated
public static SupportMapFragment newInstance(GoogleMapOptions options) {
return null;
}
public static ExtendedSupportMapFragment newInstance(MapReadyListener mapReadyListener) {
ExtendedSupportMapFragment fragment = new ExtendedSupportMapFragment();
fragment.mapReadyListener = mapReadyListener;
return fragment;
}
private MapReadyListener mapReadyListener;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (mapReadyListener != null)
mapReadyListener.mapIsReady(getMap());
}
}
Then you just need to do something like this:
public class RutaMapaFragment extends SherlockFragment implements ExtendedSupportMapFragment.MapReadyListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fragmentMapa = ExtendedSupportMapFragment.newInstance(RutaMapaFragment.this);
}
...
#Override
public void mapIsReady(GoogleMap map) {
//Do whatever you want with your map.
}
}
So, time has passed and all. The fact is that I don't use the solution in my previous answer anymore, but prefer to use a ViewTreeObserver instead. The following code shows a rather simple fragment with a SupportMapFragment being added to it.
The method createMap() adds the SupportMapFragment and then executes setupMap(), but only via a OnGlobalLayoutListener that will basically be executed once the map is actually ready. Of course, this listener is removed immediately—there's no need to keep it there any longer.
public class MyMapFragment extends Fragment {
private View mMapContainer;
private SupportMapFragment mMapFragment;
private GoogleMap mMap;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(/* ... */);
// ...
mMapContainer = view.findViewById(R.id.map_fragment_container);
createMap();
return view;
}
private void createMap() {
mMapFragment = new SupportMapFragment();
getFragmentManager().beginTransaction()
.replace(R.id.map_fragment_container, mMapFragment)
.commit();
mMapContainer.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
mMapContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
mMapContainer.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
mMap = mMapFragment.getMap();
setupMap();
}
});
}
private void setupMap() {
mMap.setMyLocationEnabled(true);
// ...
}
}
Try to add the Marker & PolyLines in the map using below code:
GoogleMap mMap;
static final CameraPosition BONDI =
new CameraPosition.Builder().target(new LatLng(-33.891614, 151.276417))
.zoom(15.5f)
.bearing(300)
.tilt(50)
.build();
changeCamera(CameraUpdateFactory.newCameraPosition(BONDI));
mMap.addMarker(new MarkerOptions().position(new LatLng(-33.891614, 151.276417)).title("Bondi"));
private void changeCamera(CameraUpdate update) {
changeCamera(update, null);
}
/**
* Change the camera position by moving or animating the camera depending on the state of the
* animate toggle button.
*/
private void changeCamera(CameraUpdate update, CancelableCallback callback) {
boolean animated = ((CompoundButton) findViewById(R.id.animate)).isChecked();
if (animated) {
mMap.animateCamera(update, callback);
} else {
mMap.moveCamera(update);
}
}
Add the PolyLines as below:
// A simple polyline with the default options from Melbourne-Adelaide-Perth.
mMap.addPolyline((new PolylineOptions())
.add(BONDI));

Categories

Resources