What is recommended way to use Google Map v2 inside fragment?
Asked Answered
H

2

17

I want to add map inside fragment with custom layout.

  1. I can do it using ChildFragmentManager that will add SupportMapFragment. This approach im currently using. However it has disadvantage because child fragment transaction is asynchronous and its hard to guarantee that getMap won't return null.
  2. Another way is to extend SupportMapFragment store mapView from super onCreateView

    mapView = super.onCreateView(inflater, container, savedInstanceState);

    and insert it to inflated layout. Primary problem is that then fragment try to restore from saved state Google Maps SDK crushes internally.

Is there any other way to solve this problem. It would be great if somebody from Google Map team will recommend right approach because you haven't included anything like this to samples.

Heel answered 5/3, 2013 at 14:16 Comment(0)
F
13

All FragmentTransactions are asynchronous. If you would like your transaction to happen immediately, you'll have to force them through like so:

getChildFragmentManager().beginTransaction.add(R.id.container, new MyMapFragment(), "MyMapFragment").commit();
getChildFragmentManager().executePendingTransactions();
/* getMap() should not return null here */

From the Android Developer Site:

After a FragmentTransaction is committed with FragmentTransaction.commit(), it is scheduled to be executed asynchronously on the process's main thread. If you want to immediately executing any such pending operations, you can call this function (only from the main thread) to do so. Note that all callbacks and other related behavior will be done from within this call, so be careful about where this is called from.

Returns
Returns true if there were any pending transactions to be executed.

Faddist answered 7/3, 2013 at 21:40 Comment(2)
Thanks, I have just tested your code. If i will make a getMap() call right after executePendingTransaction it will be still null.Heel
I found this which might be relevant to your question as well: #13722692Faddist
I
3

You can use MapView inside your Fragment (or Activity), this will allow you to use whatever layout you want.

I.e. your layout can look like this:

<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:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

You will also need to forward Fragment's lifecycle methods such as onCreate, onResume and so on to the MapView.

The only difference (seems to be a bug in Google Maps?) is that you also need to manually initialize Google Maps:

private void setUpMapIfNeeded() {
    if (mMap == null) {
        mMap = mMapView.getMap();
        if (mMap != null) {
            // Thought official docs says that it is not necessary to call
            // initialize() method if we got not-null GoogleMap instance from
            // getMap() method it seems to be wrong in case of MapView class.
            try {
                MapsInitializer.initialize(getActivity());
                setUpMap(mMap);
            } catch (GooglePlayServicesNotAvailableException impossible) {
                mMap = null;
            }
        }
    }
}
Inheritance answered 11/3, 2013 at 4:24 Comment(4)
I've got a problem with this approach. Map crushes from time to time when i try to forward onCreate. code.google.com/p/gmaps-api-issues/issues/…Heel
Hm, I'm using MapView (within fragment) in my latest project and didn't get this error. Can this issue be related to nested fragments? Try to call onCreate method with null as savedInstanceState param (though I understand this is not a good solution).Inheritance
MCeley, i should manually call mapView.onCreate if fragment is not used.Heel
Alexey - you can find solution to the BadParcelableException here:https://mcmap.net/q/520446/-restoring-mapview-39-s-state-on-rotate-and-on-backLoppy

© 2022 - 2024 — McMap. All rights reserved.