I have two maps in one view fragment (see screenshot below), and although the maps run correctly and I can access one map via getMapAsync(), I am unable to understand how to run another getMapAsync() and distinguish it from the first.
Two maps together working well:
A fairly simple View Layout (called "fragment_map.xml"):
<com.google.android.gms.maps.MapView
android:id="#+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<android.support.v7.widget.CardView
android:id="#+id/map_card"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp">
<com.google.android.gms.maps.MapView
android:layout_width="100dp"
android:layout_height="100dp"
android:id="#+id/miniMap"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp" />
</android.support.v7.widget.CardView>
In the Activity (or Fragment in my case):
private MapView mv, miniMap;
private GoogleMap gm;
private View myLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
myLayout = inflater.inflate(R.layout.fragment_map, container, false);
mv = (MapView) myLayout.findViewById(R.id.mapview);
mv.onCreate(savedInstanceState);
miniMap = (MapView) myLayout.findViewById(R.id.miniMap);
miniMap.onCreate(savedInstanceState);
mv.getMapAsync(this);
miniMap.getMapAsync(this);
return myLayout;
}
#Override
public void onMapReady(GoogleMap map) {
gm = map;
gm.setMyLocationEnabled(true);
gm.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition position) {
gm.animateCamera(CameraUpdateFactory.newLatLng(position.target));
}
});
}
The maps inflate correctly and everything works smoothly, but as you can guess, whatever I do to "GoogleMap gm" happens to both maps due to
mv.getMapAsync(this);
miniMap.getMapAsync(this);
both pointing to a single
#Override
public void onMapReady(GoogleMap map) {
Any ideas as to how I can attach a separate GoogleMap to each MapView?
EDIT:
Thanks to Zeeshan Shabbir I used a boolean to first target the main map, then initialize the mini-map:
private GoogleMap gm;
private View myLayout;
private boolean miniMapReady = false;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
myLayout = inflater.inflate(R.layout.fragment_map, container, false);
mv = (MapView) myLayout.findViewById(R.id.mapview);
mv.onCreate(savedInstanceState);
miniMap = (MapView) myLayout.findViewById(R.id.miniMap);
miniMap.onCreate(savedInstanceState);
mv.getMapAsync(this);
return myLayout;
}
#Override
public void onMapReady(GoogleMap map) {
if (!miniMapReady) {
gm = map;
gm.setMyLocationEnabled(true);
miniMap.getMapAsync(this);
miniMapReady = true;
} else {
miniGm = map;
}
gm.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition position) {
miniGm.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition(position.target, position.zoom - 5.0f, position.tilt, position.bearing)));
}
});
}
The ChangeCamera Listener here allows the mini-map to follow the user's interaction on the main map while remaining at a lower zoom level.
Try to use boolean when minimap is ready set it to false. And in onMapReady check that boolean if it is true then do what you want for mv otherwise if boolean is false write logic for minimap
Related
I have a Fragment that contains a map, this map is loaded up on the callback and OnMapReady which pulls in a map at my location successfully.
However I am trying to add in a feature whereby the user selects a location from a Spinner and the selection then draws the relevant Polygon on my map, however I keep getting an error 'Attempting to invoke virtual method Polygon'
I am by no means a talented Android developer, trying to learn and play about somewhat.
public class FindCarpark extends Fragment {
private SupportMapFragment mapFragment;
private UserLocation.OnFragmentInteractionListener mListener;
Spinner spinCar;
String selectedItem;
GoogleMap mMap;
private static final ArrayList<LatLng> cpB = new ArrayList<>();
public FindCarpark() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_find_carpark, container, false);
Context context = getActivity().getApplicationContext();
spinCar = rootView.findViewById(R.id.car_spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this.getActivity(),R.array.car_parks, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
spinCar.setAdapter(adapter);
spinCar.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
if (i > 0) {
selectedItem = spinCar.getSelectedItem().toString().trim();
addCoords(selectedItem.toString());
}
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
if (mapFragment == null) {
mapFragment = SupportMapFragment.newInstance();
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap mMap) {
new googleMap().makeMap(mMap);
}
});
}
getChildFragmentManager().beginTransaction().replace(R.id.map, mapFragment).commit();
return rootView;
}
public void addCoords(String coords){
Log.i("coords", coords);
switch (coords){
case "B":
cpB.add(new LatLng(53.797731, -1.546351));
cpB.add(new LatLng(53.797551, -1.545983));
cpB.add(new LatLng(53.797447, -1.545267));
cpB.add(new LatLng(53.797731, -1.546351));
makePolygon(cpB);
Log.i("coords", cpB.toString());
break;
default:
break;
}
}
public void makePolygon(ArrayList<LatLng> coords){
mMap.addPolygon(new PolygonOptions()
.addAll(coords)
.strokeColor(Color.RED)
.fillColor(Color.BLUE));
}
XML:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FindCarpark">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Spinner
android:id="#+id/car_spinner"
android:prompt="#string/app_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
</Spinner>
<com.google.android.gms.maps.MapView
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</FrameLayout>
Error:
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.model.Polygon com.google.android.gms.maps.GoogleMap.addPolygon(com.google.android.gms.maps.model.PolygonOptions)' on a null object reference
Your mMap variable is never filled. This then later causes a null pointer exception. The problem is:
if (mapFragment == null) {
mapFragment = SupportMapFragment.newInstance();
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap mMap) {
new googleMap().makeMap(mMap);
}
});
}
here mMap is a local variable, while the mMap you later try to access is a property of the object, thus:
if (mapFragment == null) {
mapFragment = SupportMapFragment.newInstance();
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap mMap) {
FindCarpark.this.mMap = mMap
new googleMap().makeMap(mMap);
}
});
}
i Have a Fragment that should show a Specific place on Google Map
public class ContactFragment extends Fragment implements OnMapReadyCallback {
public ContactFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
FragmentManager fragment = getActivity().getSupportFragmentManager();
final SupportMapFragment myMAPF = (SupportMapFragment) fragment.findFragmentById(R.id.map);
return inflater.inflate(R.layout.fragment_contact, container, false);
}
#Override
public void onMapReady(GoogleMap googleMap) {
LatLng marker = new LatLng(34.877737,-1.326545);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(marker,13));
googleMap.addMarker(new MarkerOptions().position(marker));
}
}
and in the XML file of the Fragment i have this :
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/map"
android:layout_below="#+id/contact_domiciliation"
class="com.google.android.gms.maps.MapFragment"
></fragment>
Yet when i launch click on the button that opens this fragment i get a map of the entire globe .
Add this line of code to the fragment:
myMAPF.getMapAsync(this);
I have simple Fragment class, specialized for displaying Google Map:
public class MapFragment extends Fragment implements Map, OnMapReadyCallback {
private static final String TAG = MapFragment.class.getSimpleName();
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_map, container, false);
MapView googleMapView = (MapView) view.findViewById(R.id.mapFragment_mapView);
googleMapView.onCreate(savedInstanceState);
googleMapView.getMapAsync(this);
return view;
}
#Override
public void onMapReady(GoogleMap googleMap) {
Log.d(TAG, "onMapReady have called");
MapsInitializer.initialize(this.getActivity());
}
}
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<com.google.android.gms.maps.MapView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/mapFragment_mapView" />
</FrameLayout>
When i run my app, i can see the log message, which means i've got a valid object GoogleMap. But on the screen i see this picture:
Object GoogleMap is really valis - for example i can turn on My Location button and i will see it on screen. So whymap tiles not loading???
You can make it work like this. This is having an additional benefit that the fragment can have other elements too displayed if needed.
public class DashBoardFragment extends Fragment{
private MapView mMapView;
private GoogleMap mGoogleMap;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.fragment_dash_board, container, false);
mMapView = (MapView) view.findViewById(R.id.map_dashBoard);
mMapView.onCreate(savedInstanceState);
mMapView.onResume();
try {
MapsInitializer.initialize(getActivity().getApplicationContext());
} catch (Exception e) {
e.printStackTrace();
}
mGoogleMap = mMapView.getMap();
return view;
}
}
xml for the fragment goes like this
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.screens.DashBoardFragment">
<com.google.android.gms.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map_dashBoard"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
Google play services should be available in device. You can check by using this.
public static boolean isGooglePlayServiceAvailable(Activity context){
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
if(status==ConnectionResult.SUCCESS){
return true;
}else{
GooglePlayServicesUtil.getErrorDialog(status, context, 10).show();
return false;
}
}
And last but very much important , our map key should be present in Manifest
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="your google map key" />
You have to call the 'getMapAsync()' function to display the map.In your onCreateView use getMapAsync() to set the callback on the fragment.
Here's a sample code for getMapAsync:
MapFragment mapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map); mapFragment.getMapAsync(this);
You may also try to read the Official Google Documentation for MapFragment:
https://developers.google.com/android/reference/com/google/android/gms/maps/MapFragment#getMapAsync(com.google.android.gms.maps.OnMapReadyCallback)
#EFragment(R.layout.main_map)
public class MapActivity extends Fragment {
private GoogleMap map;
static final LatLng DURG = new LatLng(21.1900,81.2800);
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.main_map, container, false);
map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
return view;
}
}
Null pointer exception error occure at map.setMapType(GoogleMap.MAP_TYPE_SATELLITE).
R.layout.main_map:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<fragment
android:id="#+id/map_fragment_id"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
You need to add MapFragment Dynamically when you want to inflate a MapFragment inside a Fragment.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.main_map, container, false);
SupportMapFragmentmf = SupportMapFragment.newInstance();
FragmentManager fm = getChildFragmentManager();
fm.beginTransaction().replace(R.id.mapView, mf, "normal_map").commit();
mf.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap arg0) {
map = arg0;
map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
}
});
return view;
}
where your main_map should be like below
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
I hope that helps. Please let me know if you have any doubts.
you should use
getMapAsync(OnMapReadyCallback callback)
then in the callback you can set the map to satellite view
Good night,
I have an application with a map in a swipe tab, but I want that map select a point and start at that point.
Thank you in advance.
Enclose JAVA:
public class Mapa extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View android = inflater.inflate(R.layout.mapa_3, container, false);
return android;
}
#Override
public void onDestroyView() {
super.onDestroyView();
Fragment f = getFragmentManager().findFragmentById(R.id.mapFragment);
if (f != null)
getFragmentManager().beginTransaction().remove(f).commit();
}
}
the layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/map_container"
tools:context=".Mapa" >
<fragment
android:id="#+id/mapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
</RelativeLayout>
I guess you want to add a marker to a map and set camera to look at it. Here is how you can achieve it(more info here and here):
GoogleMap map;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View android = inflater.inflate(R.layout.mapa_3, container, false);
final LatLng position = new LatLng(MARKER_LATITUDE, MARKER_LONGITUDE);
// marker
map = ((MapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment)).getMap();
map.addMarker(new MarkerOptions()
.position(position)
.title("Hello world"));
// camera position
map.setOnCameraChangeListener(new OnCameraChangeListener()
{
#Override
public void onCameraChange(CameraPosition arg0)
{
CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(position, 14);
map.animateCamera(cu);
map.setOnCameraChangeListener(null);
}
});
return android;
}