HukeLau_DABA
HukeLau_DABA

Reputation: 2528

Google Map Fragment inside another Fragment

I have a navigation drawer that replaces a framelayout with a supportmapfragment. I am able to load the fragment fine the first time, but pressing that drawer item again gives the dreaded "duplicate binary" error.

I read from Binary XML file line #9: Error inflating class fragment with Google Map Fragment that the error is due to the fact that the map fragment cannot be removed from the navdrawer's fragment if the map fragment exists in the xml. He suggested a programmatic approach so I tried this:

NavDrawerFirstFragment:

@Override
public void onCreate(Bundle savedInstanceState) {
    Log.d("DEBUG", "In NavDrawerFirstFragment onCreate()");
    super.onCreate(savedInstanceState);
}


public NavDrawerFirstFragment() {
    // fragment needs a no arg ctor
}


public static NavDrawerFirstFragment newInstance(Location currentLoc) {
    NavDrawerFirstFragment firstFragment = new NavDrawerFirstFragment();
    // how to set arguments for this fragment when this method is static
    Bundle args = new Bundle();
    args.putParcelable("current_loc", currentLoc);
    firstFragment.setArguments(args);

    return firstFragment;
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    Log.d("DEBUG", "NavDrawerFirstFragment onCreateView()");
    super.onCreateView(inflater, container, savedInstanceState);
    View view = inflater.inflate(R.layout.fragment_nav_drawer_first, container, false);

    if (mMap == null) {
        mMapFragment = new SupportMapFragment();

        FragmentTransaction ft = getChildFragmentManager().beginTransaction();
        ft.replace(R.id.mapContainer, mMapFragment);
        mMap = mMapFragment.getMap();

    }
    /*if(mMap == null) {
        mMapFragment = (SupportMapFragment)getFragmentManager().findFragmentById(R.id.map);
    }*/

    return view;
}


@Override
public void onStart() {
    Log.d("DEBUG", "NavDrawerFirstFragment onStart()");
    super.onStart();

    mMap.getUiSettings().setRotateGesturesEnabled(false);
    // check for google play services here

    MarkerOptions mo = new MarkerOptions();
    Location initialLoc = getArguments().getParcelable("current_loc");
    LatLng latlong = new LatLng(initialLoc.getLatitude(), initialLoc.getLongitude());

    Marker startingMarker = mMap.addMarker(mo.position(latlong).position(latlong).icon(
            BitmapDescriptorFactory.defaultMarker(
                    BitmapDescriptorFactory.HUE_GREEN)));
    startingMarker.setDraggable(true);
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latlong, 12));
}


@Override
public void onActivityCreated(Bundle savedInstanceState) {
    Log.d("DEBUG", "NavDrawerFirstFragment onActivityCreated");
    super.onActivityCreated(savedInstanceState);
    if (mMap == null) {
        mMap = mMapFragment.getMap();
    }
}


@Override
public void onDetach() {
    Log.d("DEBUG", "NavDrawerFirstFragment onDetach()");
    super.onDetach();
}


@Override
public void onResume() {
    Log.d("DEBUG", "NavDrawerFirstFragment onResume()");
    super.onResume();

    FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
    fragmentTransaction.add(R.id.mapContainer, mMapFragment);
    fragmentTransaction.commit();

    if (mMapFragment != null)
        mMap = mMapFragment.getMap();
}

@Override
public void onPause() {
    Log.d("DEBUG", "NavDrawerFirstFragment onPause()");
    super.onPause();

    if (mMapFragment != null) {
        FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
        fragmentTransaction.remove(mMapFragment);
        fragmentTransaction.commit();
    }
}

fragment_nav_drawer_first.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
   android:orientation="vertical">

<LinearLayout
    android:id="@+id/navBar"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <EditText
        android:id="@+id/et_location"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="@string/hnt_et_location"
        android:layout_weight="1"
        android:inputType="text" />

    <Button
        android:id="@+id/btn_find"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="@string/str_btn_find" />
</LinearLayout>

<FrameLayout
    android:id="@+id/mapContainer"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"></FrameLayout>

</LinearLayout>

This is actually the solution proposed in another SO post: Error opening SupportMapFragment for second time

When I debug it I notice that however long I wait before stepping into onStart(), my GoogleMap mMap is still null. This is driving me bonkers and I would really appreciate the proper solution to consistently accessing a navdrawer fragment that isn't just a map but a searchbar and a map like I have.

Upvotes: 1

Views: 1931

Answers (1)

SweetWisher ツ
SweetWisher ツ

Reputation: 7306

This problem occurs because map already exits and you try to add it again with the same id .. So you need to remove the map framegnt in onPause and have to again add it in onResume :

@Override
public void onResume() {
    super.onResume();

    FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
    fragmentTransaction.add(R.id.mapContainer, mMapFragment);
    fragmentTransaction.commit();

    if (mMapFragment != null)
        mMap= mMapFragment.getMap();
}

@Override
public void onPause() {
    super.onPause();

    if (mMapFragment != null) {
        FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
        fragmentTransaction.remove(mMapFragment);
        fragmentTransaction.commit();
    }
}

Update :

Move your onStart code to onActivityCreated as shown here :

mMapFragment = new SupportMapFragment() {



    @Override
            public void onActivityCreated(Bundle savedInstanceState) {
                super.onActivityCreated(savedInstanceState);
                initMap();

            }
        };


    public void initMap()
    {
              if (mMap== null) {
                    mMap= mMapFragment.getMap();
            }
        mMap.getUiSettings().setRotateGesturesEnabled(false);
        // check for google play services here

        MarkerOptions mo = new MarkerOptions();
        Location initialLoc = getArguments().getParcelable("current_loc");
        LatLng latlong = new LatLng(initialLoc.getLatitude(), initialLoc.getLongitude());

        Marker startingMarker = mMap.addMarker(mo.position(latlong).position(latlong).icon(
                BitmapDescriptorFactory.defaultMarker(
                        BitmapDescriptorFactory.HUE_GREEN)));
        startingMarker.setDraggable(true);
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latlong, 12));
    }

Upvotes: 2

Related Questions