Loading Android Google Map fragment managed by ViewPager
Asked Answered
N

5

9

I can load a google map into an Android fragment that's within an activity. That has been working fine.

But now I want to use ViewPager to navigate between views (class android.support.v4.app.Fragment). It doesn't seem possible to load a com.google.android.gms.maps.MapFragment into such a fragment.

For example, in:

SoleMap.java

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;

public class SoleMap extends Fragment implements OnMapReadyCallback {

    MapFragment gMapFragment;
    GoogleMap gMap = null;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.sole_map, container, false);

        gMapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.soleViewMap);
        gMapFragment.getMapAsync(this);

        return view;
    }

    @Override
    public void onMapReady(GoogleMap map) {
        gMap = map;
        gMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new
                LatLng(49.39,-124.83), 20));
    }

}

The statement

getFragmentManager().findFragmentById(R.id.holeViewMap);

causes a compiler error (incompatible types).

I have tried to use SupportMapFragment instead, which eliminates the compiler errors, but then when I run the app, it quits immediately with the message "I/O Error: Connection refused." The Google docs seem to indicate that you need a special "For Work" account to use the Support library. Is that correct? If so, I guess I'm out of luck.

The only other way I can see to do it is to use activities instead of fragments to host my views, i.e., get rid of the ViewPager.

Any suggestions?

Noddy answered 30/4, 2015 at 20:9 Comment(3)
try this: #19353755Tonkin
Connection refused: do you have Google Maps API key in the manifest?Rollins
I think my "connection refused" problem was unrelated -- probably having to do with an update to the SDK that needed a shutdown/restart. To answer your question, yes, I had my manifest (with key) that had been working previously.Noddy
F
14

In your sole_map.xml you must add a MapView, let's say something like this:

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.maps.MapView
    android:id="@+id/soleViewMap"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

Then get it from your SoleMap fragment with the id view.findViewById(R.id.soleViewMap); This will return you a MapView, then you can do what you're doing now. It should look something like this:

public class SoleMap extends Fragment implements OnMapReadyCallback {

  MapView gMapView;
  GoogleMap gMap = null;

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.sole_map, container, false);

    gMapView = (MapView) view.findViewById(R.id.soleViewMap);
    gMapView.getMapAsync(this);

    return view;
  }

  @Override
  public void onMapReady(GoogleMap map) {
    gMap = map;
    gMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
    gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new
            LatLng(49.39,-124.83), 20));
  }
}

Don't forget to associate your mapview with the fragment lifecycle calling the events onCreate, onLowMemory, onPause, onResume and onDestroy (hope not missing any of them), and call to MapsInitializer.initialize(getContext()); as well

Falsify answered 30/4, 2015 at 20:36 Comment(6)
I'm still working on implementing this but in case anyone else is using the above, I believe it requires one correction. Instead of findFragmentById(), one must use findViewByID(). I am then able to compile. I'll come back ASAP to indicate whether I could get it to work this way.Noddy
You're right, my bad, I'll make the correction in a moment. Thanks!Falsify
I am now able to get a map on one of my fragments. The above was very helpful regarding the overall fix. For help with implementation details, see gist.github.com/joshdholtz/4522551. Also the Android docs for the MapView class.Noddy
Why MapView and not SupportMapFragment?Hesler
Thanks a ton ! this post should have +100, everyone just remember to call mMapView.onCreate() in createView and mMapView.onResume() in the callbackAgni
It worked for me. I missed gMapView.getMapAsync(this); in my project.Petrography
S
9

Accepted answer is good start point but if we will try to use it it will fail, it not describe full solution. Full working fragment with map which can be used in ViewPager and Tabs ( notice using map in fragmeny lifecycle ):

public class AttractionMapTabFragment extends AttractionTab implements OnMapReadyCallback {

private ScrollMapView gMapView;
private GoogleMap gMap;


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

    View view = inflater.inflate(R.layout.fragment_map, null);

    gMapView = (ScrollMapView) view.findViewById(R.id.map);
    gMapView.getMapAsync(this);

    //most important use onCreate;
    gMapView.onCreate(getArguments());
    return view;

}

@Override
public void onMapReady(GoogleMap googleMap) {
    gMap = googleMap;
    gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new
            LatLng(51.3623329,21.7719342), 8));
}

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

    if (gMapView != null)
        gMapView.onResume();
}


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

    if (gMapView != null)
        gMapView.onDestroy();
}

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

    if (gMapView != null)
        gMapView.onStart();
}

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

    if (gMapView != null)
        gMapView.onStop();

}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    if (gMapView != null)
        gMapView.onSaveInstanceState(outState);
}
}

Custom MapView class - it is needed if we use ScrollView as parent, it give possibility to move map.If You are not using ScrollView in this screen then standard MapView can be used.

public class ScrollMapView extends MapView {

public ScrollMapView(Context context, AttributeSet attributeSet) {
    super(context, attributeSet);
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    /**
     * Request all parents to relinquish the touch events
     */
    getParent().requestDisallowInterceptTouchEvent(true);
    return super.dispatchTouchEvent(ev);
}
}

Last thing is layout - R.layout.fragment_map:

<?xml version="1.0" encoding="utf-8"?>
<your.app.ScrollMapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android" />
Shelba answered 9/1, 2017 at 22:45 Comment(0)
S
2
public class MapViewFragment extends Fragment implements OnMapReadyCallback{

private GoogleMap mMap;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.activity_maps, container, false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    //FragmentManager fragment = getActivity().getSupportFragmentManager();
   // Fragment fragment=(Fragment) getChildFragmentManager().findFragmentById(R.id.mapView);
    final SupportMapFragment myMAPF = (SupportMapFragment)getChildFragmentManager().findFragmentById(R.id.map);
    myMAPF.getMapAsync(this);

}

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

    // Add a marker in Sydney and move the camera
    LatLng sydney = new LatLng(25.412383, 55.508085);
    mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
    mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
Sap answered 24/10, 2016 at 8:2 Comment(2)
You didn't explain nothing, what is your solution? This is just the autogenerated code when you create a MapActivity from Android templatesMonocot
Finally I found what you want to solve with this code, it makes my map work inside a view pager. But it was hard to figure out what is the propose of your code/solution.Monocot
S
0

Write this code in your activity_maps.xml

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />
Sap answered 24/10, 2016 at 8:7 Comment(0)
C
0

I was stuck with this problem for days. Finally I made it work like this:

sole_map.xml

<fragment xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".SoleMap"
    android:id="@+id/soleViewMap"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    map:mapType="terrain" />

SoleMap.java

Instead of doing things in "onCreateView" I do it in "onViewCreated" and also instead of using MapFragment I use SupportMapFragment and use getChildFragmentManager instead of getFragmentManager, like this:

public class MapaFragment extends Fragment implements OnMapReadyCallback {

GoogleMap mapa_sole;

public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.sole_map, container, false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    final SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.soleViewMap);
    mapFragment.getMapAsync(this);

}

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


    // TODO....

   }
}

Hope this help!

Chargeable answered 30/11, 2019 at 18:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.