Creating a custom Fragment with full screen map

1.1k views Asked by At

I'd like to build a Fragment which consists of a full screen map overlaid with other views (A ViewPager, EditText, and the like). I've thought of two different options:

  1. Create a Fragment with a MapView near the root of the layout and set it to match_parent, then use other View's as normal.
  2. Subclass MapFragment.

I've subclassed MapFragment:

public class ListMapFragment extends MapFragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        return super.onCreateView(inflater, container, savedInstanceState);
    }
}

Displaying this fragment works as normal and the map takes up the entire fragment. However, I would like to display various views as described above over the map. If I try to inflate and return a view (as you would with a normal Fragment) by instead returning a view, a NPE occurs:

public class ListMapFragment extends MapFragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_list_map, container, false);
        return view; 
    }
}

Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'void maps.ad.y.v()' on a null object reference

If I try calling the supers method before returning a view, the layout is loaded, but the map is not:

public class ListMapFragment extends MapFragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_list_map, container, false);

        super.onCreateView(inflater, container, savedInstanceState);

        return view;
    } 

Out of the two options, is one preferred over the other? And if #2 is preferred, what is wrong with the above code?

2

There are 2 answers

0
ashkhn On

Unless you're actually modifying any of MapFragment's functionalities you should not be deriving from it. Just create a fragment with a FrameLayout and MapView as match_parent and add views to it.

And also that is what is wrong with the above code as well. When you derive from MapFragment and override its methods some of its initializations don't happen and as a result you get an NPE.

0
Fundhor On

If I try calling the supers method before returning a view, the layout is loaded, but the map is not:

This is the way to go. But you also need to load the map.

public class MyMapFragment extends SupportMapFragment implements OnMapReadyCallback {
    // extends SupportMapFragment, but MapFragment should work as well

    View rootView;
    private MapView mapView;

    public MyMapFragment() {}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        super.onCreateView(inflater, container, savedInstanceState);

        rootView = inflater.inflate(R.layout.fragment_map, container, false);

        mapView = (MapView) rootView.findViewById(R.id.map);
        mapView.onCreate(savedInstanceState);
        mapView.onResume();
        mapView.getMapAsync(this);//when you already implement OnMapReadyCallback in your fragment

        return rootView;
    }

    @Override
    public void onMapReady(GoogleMap map) {
        mainActivity.googleMap = map;
        // play with your map
    }
}

XML fragment_map.xml

<com.google.android.gms.maps.MapView
    android:id="@+id/map"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />