Show a panel on MapBox in Android - android

I use MapBox in Android and show some Points on it. Now I want to show a panel top-left of map and show some information in this panel. How can i do this? (An Example show in image in URL: https://docs.mapbox.com/help/img/directions/gljs-plugin.png , a panel like that panel show in image , the black panel on the left)
Thanks
private MapView mapView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this, YOUR_MAPBOX_ACCESS_TOKEN);
setContentView(R.layout.activity_main);
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(#NonNull MapboxMap mapboxMap) {
mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
// Map is set up and the style has loaded. Now you can add data or make other map adjustments
}
});
}
});

Related

Why does an image is distorted when I set it using GroundOverlay in my Google Map?

I am trying to set a screenshot of a map into another map using GroundOverlay provided by Google Maps.
First I save the bounds of the map when I take the screenshot. I get them using
borders = GoogleMap.getProjection().getVisibleRegion().latLngBounds;
After when I set the screenshot to the GroundOverlay image using that bounds, the image appears distorted. I did it like this
GroundOverlayOptions offlineMap = new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromBitmap(myBitmap))
.transparency(0)
.positionFromBounds(borders);
imageOverlay = map.addGroundOverlay(offlineMap);
Here is a screenshot of the problem:
Screenshot of the image overlay distorted
Why is happening this? How can I set the image correctly?
EDITED
I could set the image without distorsion passing the LatLng coordinates of the center of the image and the width of the image, but the thing is that the GroundOverlayOptions object needs the width in kilometers, and I calculated using the distance between the two bot points of the image in the moment that is captured.
My problem is, the image is set with correct proportions, but in the wrong place.
How can I save the attributes to set the image in the exactly same position on the map as when it was taken?
Try this code, which gets screenshot on mScreenshotButton press, than add it as overlay on mAddOverlayButton press:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mGoogleMap;
private MapFragment mMapFragment;
private Button mAddOverlayButton;
private Button mScreenshotButton;
private Bitmap mScreenshot;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mScreenshotButton = (Button) findViewById(R.id.get_screenshot_button);
mScreenshotButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getMapScreenshot();
}
});
mAddOverlayButton = (Button) findViewById(R.id.add_overlay_button);
mAddOverlayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LatLngBounds borders = mGoogleMap.getProjection().getVisibleRegion().latLngBounds;
GroundOverlayOptions overlay = new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromBitmap(mScreenshot))
.transparency(0f)
.positionFromBounds(borders);
mGoogleMap.addGroundOverlay(overlay);
}
});
mMapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map_fragment);
mMapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
}
public void getMapScreenshot()
{
GoogleMap.SnapshotReadyCallback callback = new GoogleMap.SnapshotReadyCallback() {
Bitmap bitmap;
#Override
public void onSnapshotReady(Bitmap snapshot) {
mScreenshot = snapshot;
}
};
mGoogleMap.snapshot(callback);
}
}
And there is no any distortion. Seems you didn't get borders properly.

MapView leaks activity (without location service)

I'm using the play services v9.8.0 (without location service permissions) and am still facing a leak when I use a MapView in a dialog fragment. I'm using it like in my code example and I use it to display a location only and I DON'T have setMyLocationEnabled (as I don't even have the permissions for this setting).
Does anyone see a problem in my code? I'm getting a leak like the one here: MapView v2 keeping Context around. I do following:
create a dialog
replace a view in my layout with a MapView (because I allow to use static maps as well, so my default view is a ImageView in my layout, that will be replaced with a MapView)
Then it happens that my fragments leaks MapView.mContext...
Code - Dialog Fragment
public class DialogMediaDetails extends DialogFragment
{
private GoogleMap mGoogleMap = null;
private MapView mMapView = null;
#Override
public final Dialog onCreateDialog(Bundle savedInstanceState)
{
Dialog dlg = ...; // create dialog
View view = ...; // get view from dialog
Location location = ...; // defined location
initGoogleMap();
return dlg;
}
private void initGoogleMap(Location location)
{
mMapView = new MapView(getActivity());
MapsInitializer.initialize(getActivity());
// Updates the location and zoom of the MapView
mMapView.onCreate(null);
mMapView.getMapAsync(new OnMapReadyCallback()
{
#Override
public void onMapReady(GoogleMap googleMap)
{
LatLng coordinates = new LatLng(location.getLatitude(), location.getLongitude());
googleMap.addMarker(new MarkerOptions().position(coordinates));
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(coordinates, 15));
mGoogleMap = googleMap;
mMapView.onResume();
}
});
mMapView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
mMapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// MapView is scrollable, so we disable dragging
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
#Override
public boolean canDrag(AppBarLayout appBarLayout) {
return false;
}
});
}
});
replaceHeader(mMapView);
}
private void replaceHeader(View view)
{
ViewGroup parent = (ViewGroup) pbHeader.getParent();
int index = parent.indexOfChild(pbHeader);
ViewGroup.LayoutParams lp = pbHeader.getLayoutParams();
parent.removeView(pbHeader);
parent.addView(view, index, lp);
}
// ----------------------------------------
// forward all lifecycle events to MapView
// ----------------------------------------
#Override
public void onResume() {
super.onResume();
if (mMapView != null)
mMapView.onResume();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mMapView != null)
mMapView.onSaveInstanceState(outState);
}
#Override
public void onPause() {
super.onPause();
if (mMapView != null)
mMapView.onPause();
}
#Override
public void onLowMemory() {
super.onLowMemory();
if (mMapView != null)
mMapView.onLowMemory();
}
#Override
public void onDestroy() {
super.onDestroy();
if (mMapView != null)
mMapView.onDestroy();
mMapView = null;
}
}
There are some issues reported about leaks with MapView. You may try calling googleMap.setMyLocationEnabled(false); in onDestroy to prevent the leak from happening. Failure to call either MapView.onDestroy or GoogleMap.setMyLocationEnabled(false) will cause a leak. Here's a related thread which might help.
I had the same issue, and realized in my heap reference tree that the bug is coming from the lite mode part of the library. Try not using lite mode and adding all the corresponding life cycles for mapview.

How to change map view on fragment?

I'm developing an app by using mapbox api. At the map when the user clicks map item on menu a fragment is opening.Later user may want to change mapview style such as satellite,dark,emerald or just a street view. User is able to choose map style on action bar. I implemented my action bar on main activity. When the user on map fragment choose map style and a variable comes to fragment which handled in main activity. This variable is the string of map style. Now I want to change map view style without recreating map fragment. What can you advise about this problem ?
public class GeoMapFragment extends Fragment implements OnMapReadyCallback {
public MapView mapView = null;
private MapboxMap mapboxMap;
public String mapViewSelectedItem ;
private static final int PERMISSIONS_LOCATION = 0;
public GeoMapFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_geomap, container, false);
mapView = (MapView)view.findViewById(R.id.mapview);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
// Inflate the layout for this fragment
return view;
}
#Override
public void onStart() {
super.onStart();
mapView.onStart();
}
#Override
public void onStop() {
super.onStop();
mapView.onStop();
}
#Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
#Override
public void onResume() {
super.onResume();
mapView.onResume();
}
/**
* Dispatch onPause() to fragments.
*/
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
public void onMapReady(MapboxMap map) {
mapboxMap = map;
mapboxMap.setStyle(Style.DARK);
mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(0, 0)));
// Show user location (purposely not in follow mode)
if ((ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) ||
(ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
} else {
mapboxMap.setMyLocationEnabled(true);
}
// TODO - mv.loadFromGeoJSONURL("https://gist.githubusercontent.com/tmcw/10307131/raw/21c0a20312a2833afeee3b46028c3ed0e9756d4c/map.geojson");
mapboxMap.addMarker(new MarkerOptions().title("Edinburgh").snippet("Scotland").position(new LatLng(55.94629, -3.20777)));
mapboxMap.addMarker(new MarkerOptions().title("Stockholm").snippet("Sweden").position(new LatLng(59.32995, 18.06461)));
mapboxMap.addMarker(new MarkerOptions().title("Prague").snippet("Czech Republic").position(new LatLng(50.08734, 14.42112)));
mapboxMap.addMarker(new MarkerOptions().title("Athens").snippet("Greece").position(new LatLng(37.97885, 23.71399)));
mapboxMap.addMarker(new MarkerOptions().title("Tokyo").snippet("Japan").position(new LatLng(35.70247, 139.71588)));
mapboxMap.addMarker(new MarkerOptions().title("Ayacucho").snippet("Peru").position(new LatLng(-13.16658, -74.21608)));
mapboxMap.addMarker(new MarkerOptions().title("Nairobi").snippet("Kenya").position(new LatLng(-1.26676, 36.83372)));
mapboxMap.addMarker(new MarkerOptions().title("Canberra").snippet("Australia").position(new LatLng(-35.30952, 149.12430)));
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case PERMISSIONS_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mapboxMap.setMyLocationEnabled(true);
}
}
}
}
Your map fragment should have a getMapAsync() call which you can change the style of. Heres a rough example of how you can accomplish this:
private MapboxMap map;
...
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(final MapboxMap mapboxMap) {
map = mapboxMap;
}
});
...
// Wherever you implemented receiving the style string from MainActivity you can include this:
map.setStyleUrl(<style url>);
If this doesn't work for you, please let me know how exactly you are creating the map fragment. Currently the SDK includes a fragment already which you can setup like so:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SupportMapFragment mapFragment;
if (savedInstanceState == null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
LatLng patagonia = new LatLng(-52.6885, -70.1395);
MapboxMapOptions options = new MapboxMapOptions();
options.accessToken("<your access token here>");
options.styleUrl(Style.SATELLITE);
options.camera(new CameraPosition.Builder()
.target(patagonia)
.zoom(9)
.build());
mapFragment = SupportMapFragment.newInstance(options);
transaction.add(R.id.container, mapFragment, "mapFragment");
transaction.commit();
} else {
mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentByTag("mapFragment");
}
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(final MapboxMap mapboxMap) {
map = mapboxMap;
}
});
}
If you did it this way you can easily change the style of the map like I said above.
Hope this helps out!

android: google map loading issue

I'm using google map in my app , the code runs on device perfectly but the map does not load ! I just see a white screen ! what's the problem ?
here is the code , please help !
public class MyMap extends MapActivity {
private MapView map;
private MapController controller;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initMapView();
initMyLocation();
}
/** Find and initialize the map view. */
private void initMapView() {
map = (MapView) findViewById(R.id.map);
controller = map.getController();
map.setSatellite(true);
map.setBuiltInZoomControls(true);
}
/** Start tracking the position on the map. */
private void initMyLocation() {
final MyLocationOverlay overlay = new MyLocationOverlay(this, map);
overlay.enableMyLocation();
//overlay.enableCompass(); // does not work in emulator
overlay.runOnFirstFix(new Runnable() {
public void run() {
// Zoom in to current location
controller.setZoom(8);
controller.animateTo(overlay.getMyLocation());
}
});
map.getOverlays().add(overlay);
}
#Override
protected boolean isRouteDisplayed() {
// Required by MapActivity
return false;
}
}
put your map api key in xml here is tutorial to get map api key
Create your google map api key and pest in maplayout.xml
android:apiKey=" your api key"
which is freely avaliable

Android MapView

I'm trying to add an overlay for myLocation in Android. The map displays, but the overlay does not. I did get the overlay to appear using a separate class that extends ItemizedOverlay. I'm wondering of there is a way to display this individual point without creating a separate class?
Attached is the source code for the activity class.
public class WalkAbout extends MapActivity {
//for Hello_mapview
List<Overlay> mapOverlays;
Drawable drawable;
private MapView m_vwMap;
private MapController m_mapController;
private PathOverlay m_pathOverlay;
private MyLocationOverlay m_locationOverlay;
private ArrayList<GeoPoint> m_arrPathPoints;
private ArrayList<OverlayItem> m_arrPicturePoints;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initLocationData();
initLayout();
}
#Override
protected boolean isRouteDisplayed() {
return false;
}
private void initLocationData() {
// TODO
}
private void initLayout() {
//instantiate XML File into corresponding view objects.
//Then inflate new view from XML resource.
setContentView(R.layout.map_layout);
MapView m_vwMap = (MapView)findViewById(R.id.mapview);
m_vwMap.setBuiltInZoomControls(true);
m_vwMap.setSatellite(true);
//retrieve list of overlay objects
mapOverlays=m_vwMap.getOverlays();
//set market for overlays
drawable=this.getResources().getDrawable(R.drawable.item);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight());
//create OverlayItem with my location
m_locationOverlay= new MyLocationOverlay(this, m_vwMap);
//enable market to set location and direction
m_locationOverlay.enableCompass();
m_locationOverlay.enableMyLocation();
mapOverlays.add(m_locationOverlay);
}
}
You need to call invalidate() on your m_vwMap so it will redraw itself.

Categories

Resources