4

I'm trying to put the Google Maps fragment in my app but I keep getting this error when I try to inflate the view in the Locations class:

android.view.InflateException: Binary XML file line #37: Binary XML file line #37: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #37: Error inflating class fragment
Caused by: android.app.Fragment$InstantiationException: Trying to instantiate a class com.google.android.gms.maps.SupportMapFragment that is not a Fragment

I want to put the maps fragment in another fragment with is loaded in the main activity with the navigation drawer.

Here is my code loading the locations fragment the map should go into:

@Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

        Fragment fragment = new Race();
        toolbar.setTitle(R.string.nav_name_race);
        FragmentManager fragmentManager = getFragmentManager();

        if (id == R.id.nav_race) {
            toolbar.setTitle(R.string.nav_name_race);
            fragment = new Race();
        } else if (id == R.id.nav_pilot) {
            toolbar.setTitle(R.string.nav_name_pilot);
            fragment = new Pilot();
        } else if (id == R.id.nav_locations) {
            toolbar.setTitle(R.string.nav_name_locations);
            fragment = new Locations();
        } else if (id == R.id.nav_channelpicker) {
            toolbar.setTitle(R.string.nav_name_channelpicker);
            fragment = new Channelpicker();
        } else if (id == R.id.nav_band_overview) {
            toolbar.setTitle(R.string.nav_name_band_overview);
            fragment = new BandOverview();
        }

        fragmentManager.beginTransaction()
                .replace(R.id.mainframelayout, fragment)
                .commit();


        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

The Locations class:

public class Locations extends Fragment implements OnMapReadyCallback {

    private View view;
    private GoogleMap map;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        this.view = inflater.inflate(R.layout.content_locations, container, false);
        SupportMapFragment mapFragment = (SupportMapFragment) (((FragmentActivity) getActivity()).getSupportFragmentManager().findFragmentById(R.id.map));
        mapFragment.getMapAsync(this);


        //set fab onClickListener
        FloatingActionButton fabtop = (FloatingActionButton) view.findViewById(R.id.fabtop);
        assert fabtop != null;
        fabtop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(view.getContext(), "top", Toast.LENGTH_SHORT).show();
            }
        });

        FloatingActionButton fabbottom = (FloatingActionButton) view.findViewById(R.id.fabbottom);
        assert fabbottom != null;
        fabbottom.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(view.getContext(), "bottom", Toast.LENGTH_SHORT).show();
            }
        });

        return this.view;
    }

    @Override
    public void onMapReady(GoogleMap googleMap)
    {
        map = googleMap;

        // Add a marker in Sydney and move the camera
        LatLng sydney = new LatLng(-34, 151);
        map.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
        map.moveCamera(CameraUpdateFactory.newLatLng(sydney));
    }
}

And the layout file:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="?android:attr/actionBarSize"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity">

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabtop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right|bottom"
        android:src="@drawable/ic_menu_mylocation"
        app:backgroundTint="#FFFFFF"
        android:layout_above="@+id/fabbottom"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_marginRight="@dimen/fab_margin" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabbottom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right|bottom"
        android:src="@mipmap/ic_add_white_48dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_margin="@dimen/fab_margin" />
    
    <fragment 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"
        tools:context=".MapsActivity"
        android:name="com.google.android.gms.maps.SupportMapFragment" />

</RelativeLayout>

I think the problem is having a fragment inside a fragment, because if I make a new Activity for the map everything works fine. I'm still a beginner in working with fragments and don't know the proper way to insert the maps fragment in my app.

Every tip is appreciated.

hannele
  • 53
  • 4
lexlix
  • 43
  • 1
  • 7

1 Answers1

2

You do not need to call (SupportMapFragment) (((FragmentActivity) getActivity()).getSupportFragmentManager() in your fragment as you have getFragmentManager() in Fragment. But when using Nested Fragments, you should use getChildFragmentManager() instead of getFragmentManager() (See documentation).

Coming to your question, you can simply update your code to this:

SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
if (mapFragment != null) {
    mapFragment.getMapAsync(this);
}

And in case you face issues like Duplicate ID, tag null, or parent id with another fragment for com.google.android.gms.maps.MapFragment. You can try any of the solutions discussed here. Or try this one:

private View mContentView;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if (mContentView == null) {
        mContentView = inflater.inflate(R.layout.content_locations, container, false);
    }
    return mContentView;
}

It will not inflate layout every time so you will not face Duplicate ID, tag null, or parent id with another fragment for com.google.android.gms.maps.MapFragment issue. But make sure you pass false in attachToRoot (last argument of inflater.inflate) otherwise you may get exceptions like The specified child already has a parent.

Community
  • 1
  • 1
Rehan
  • 3,270
  • 5
  • 31
  • 30
  • I tried your solution but I can not compile because it wont let me cast the fragment returned by the getChildFragmentManager() to SupportMapFragment – lexlix May 23 '16 at 07:24
  • @Felix Can you tell whether your `Locations` class is extended from `android.support.v4.app.Fragment` or `android.app.Fragment`? – Rehan May 23 '16 at 07:29
  • it is extended from android.app.Fragment – lexlix May 23 '16 at 07:30
  • @Felix Then you'll have to extend it from `android.support.v4.app.Fragment` to use `SupportMapFragment` and make changes in Adapter in your Actiivity or if you prefer to use `android.app.Fragment` directly then you have to use `MapFragment` eveywhere in place of `SupportMapFragment` like in your xml change `com.google.android.gms.maps.SupportMapFragment` to `com.google.android.gms.maps.MapFragment` and accordingly in your `Fragment` as well. Did you get the point? – Rehan May 23 '16 at 07:36
  • I changed all my Fragments to android.support.v4.app.Fragment and now everything is working perfect. Thank you very much! – lexlix May 23 '16 at 07:41