Inicializar MapFragment mediante programación con Google Maps API v2

Estoy intentando agregar un MapFragment a mi Fragmento actual. El uso de fragmentos anidados está restringido a FragmentTransactions, no puede utilizar la etiqueta xml en su diseño. Además, quiero que se agregue al Fragmento principal cuando el usuario presiona un botón. Por lo tanto, estoy creando el MapFragment programaticamente con getInstance() cuando el usuario presiona ese botón y agregarlo al lugar adecuado. Se muestra correctamente, hasta ahora tan bueno.

El problema es que después de adjuntar el MapFragment necesito obtener una referencia a GoogleMap para colocar un Marcador , pero el método getMap() devuelve null (como onCreateView() del fragmento no se ha llamado aún).

Miré el código de ejemplo de demostración y he encontrado que la solución que utilizan es inicializar el MapFragment en onCreate() y obtener la referencia a GoogleMap en onResume() , después de onCreateView() ha sido llamado.

Necesito obtener la referencia a GoogleMap inmediatamente después de la inicialización de MapFragment, porque quiero que los usuarios puedan mostrar u ocultar el mapa con un botón. Sé que una posible solución sería crear el mapa al principio como se ha dicho anteriormente y acaba de establecer su visibilidad se fue, pero quiero que el mapa esté desactivado por defecto por lo que no toma el ancho de banda del usuario si no se le preguntó explícitamente para ello.

He intentado con el MapsInitializer , pero tampoco funciona. Estoy un poco atascado. ¿Algunas ideas? Aquí está mi código de prueba hasta ahora:

 public class ParadaInfoFragment extends BaseDBFragment { // BaseDBFragment is just a SherlockFragment with custom utility methods. private static final String MAP_FRAGMENT_TAG = "map"; private GoogleMap mMap; private SupportMapFragment mMapFragment; private TextView mToggleMapa; private boolean isMapVisible = false; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_parada_info, container, false); mToggleMapa = (TextView) v.findViewById(R.id.parada_info_map_button); return v; } @Override public void onStart() { super.onStart(); mToggleMapa.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!isMapVisible) { openMap(); } else { closeMap(); } isMapVisible = !isMapVisible; } }); } private void openMap() { // Creates initial configuration for the map GoogleMapOptions options = new GoogleMapOptions().camera(CameraPosition.fromLatLngZoom(new LatLng(37.4005502611301, -5.98233461380005), 16)) .compassEnabled(false).mapType(GoogleMap.MAP_TYPE_NORMAL).rotateGesturesEnabled(false).scrollGesturesEnabled(false).tiltGesturesEnabled(false) .zoomControlsEnabled(false).zoomGesturesEnabled(false); // Modified from the sample code: // It isn't possible to set a fragment's id programmatically so we set a // tag instead and search for it using that. mMapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG); // We only create a fragment if it doesn't already exist. if (mMapFragment == null) { // To programmatically add the map, we first create a // SupportMapFragment. mMapFragment = SupportMapFragment.newInstance(options); // Then we add it using a FragmentTransaction. FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction(); fragmentTransaction.add(R.id.parada_info_map_container, mMapFragment, MAP_FRAGMENT_TAG); fragmentTransaction.commit(); } // We can't be guaranteed that the map is available because Google Play // services might not be available. setUpMapIfNeeded(); //XXX Here, getMap() returns null so the Marker can't be added // The map is shown with the previous options. } private void closeMap() { FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction(); fragmentTransaction.remove(mMapFragment); fragmentTransaction.commit(); } private void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the // map. if (mMap == null) { // Try to obtain the map from the SupportMapFragment. mMap = mMapFragment.getMap(); // Check if we were successful in obtaining the map. if (mMap != null) { mMap.addMarker(new MarkerOptions().position(new LatLng(37.4005502611301, -5.98233461380005)).title("Marker")); } } } } 

Gracias

El buen AnderWebs me dio una respuesta en Google+, pero él es demasiado laz …. emm ocupado para escribir aquí de nuevo, así que aquí está la versión corta: Extender la clase MapFragment y anular el método onCreateView() . Después de este método se hace podemos obtener una referencia no nula a ese objeto GoogleMap .

Esta es mi solución particular:

 public class MiniMapFragment extends SupportMapFragment { private LatLng mPosFija; public MiniMapFragment() { super(); } public static MiniMapFragment newInstance(LatLng posicion){ MiniMapFragment frag = new MiniMapFragment(); frag.mPosFija = posicion; return frag; } @Override public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) { View v = super.onCreateView(arg0, arg1, arg2); initMap(); return v; } private void initMap(){ UiSettings settings = getMap().getUiSettings(); settings.setAllGesturesEnabled(false); settings.setMyLocationButtonEnabled(false); getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(mPosFija,16)); getMap().addMarker(new MarkerOptions().position(mPosFija).icon(BitmapDescriptorFactory.fromResource(R.drawable.marker))); } } 

Ahora en la clase Fragmento anterior que hago

 mMapFragment = MiniMapFragment.newInstance(new LatLng(37.4005502611301, -5.98233461380005)); 

Tal vez todavía no es perfecto, porque la pantalla parpadea al mostrar el mapa. Pero no estoy seguro si el problema es debido a esto o algo más.

Gracias, encontré esto muy útil. Estoy publicando mi solución ligeramente modificada, ya que era más limpio para mí decirle al Fragmento padre cuando el mapa estaba listo. Este método también funciona con un ciclo saveInstanceState / restoreInstanceState.

 public class CustomMapFragment extends SupportMapFragment { private static final String LOG_TAG = "CustomMapFragment"; public CustomMapFragment() { super(); } public static CustomMapFragment newInstance() { CustomMapFragment fragment = new CustomMapFragment(); return fragment; } @Override public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) { View v = super.onCreateView(arg0, arg1, arg2); Fragment fragment = getParentFragment(); if (fragment != null && fragment instanceof OnMapReadyListener) { ((OnMapReadyListener) fragment).onMapReady(); } return v; } /** * Listener interface to tell when the map is ready */ public static interface OnMapReadyListener { void onMapReady(); } } 

Para utilizarlo como un fragmento anidado: –

 public class ParentFragment extends Fragment implements OnMapReadyListener { ... mMapFragment = CustomMapFragment.newInstance(); getChildFragmentManager().beginTransaction().replace(R.id.mapContainer, mMapFragment).commit(); @Override public void onMapReady() { mMap = mMapFragment.getMap(); } ... } 

Espero que ayude a alguien.

Aquí está mi solución a esto, tomé la inspiración del código fijado previamente y lo limpié para arriba. También agregué los métodos estáticos con y sin los parámetros de GoogleMapOptions.

 public class GoogleMapFragment extends SupportMapFragment { private static final String SUPPORT_MAP_BUNDLE_KEY = "MapOptions"; public static interface OnGoogleMapFragmentListener { void onMapReady(GoogleMap map); } public static GoogleMapFragment newInstance() { return new GoogleMapFragment(); } public static GoogleMapFragment newInstance(GoogleMapOptions options) { Bundle arguments = new Bundle(); arguments.putParcelable(SUPPORT_MAP_BUNDLE_KEY, options); GoogleMapFragment fragment = new GoogleMapFragment(); fragment.setArguments(arguments); return fragment; } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mCallback = (OnGoogleMapFragmentListener) getActivity(); } catch (ClassCastException e) { throw new ClassCastException(getActivity().getClass().getName() + " must implement OnGoogleMapFragmentListener"); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); if (mCallback != null) { mCallback.onMapReady(getMap()); } return view; } private OnGoogleMapFragmentListener mCallback; } 

El patrón de uso es el siguiente:

 public class MyMapActivity implements OnGoogleMapFragmentListener { ... @Override public void onMapReady(GoogleMap map) { mUIGoogleMap = map; ... } ... private GoogleMap mUIGoogleMap; } 

No hay necesidad de cutomize SupportMapFragment que puede hacer esto directamente mediante el siguiente pedazo de código,

 FragmentManager fm = getSupportFragmentManager(); // getChildFragmentManager inside fragments. CameraPosition cp = new CameraPosition.Builder() .target(initialLatLng) // your initial co-ordinates here. like, LatLng initialLatLng .zoom(zoom_level) .build(); SupportMapFragment mapFragment = SupportMapFragment.newInstance(new GoogleMapOptions().camera(cp)); fm.beginTransaction().replace(R.id.rl_map, mapFragment).commit(); 

Añadir este pedazo de código para el layout

 <RelativeLayout android:id="@+id/rl_map" android:layout_width="fill_parent" android:layout_height="fill_parent" /> 

Esto cargará GoogleMap en la Location particular directamente es decir, initialLatLng.

  • ¿Cómo puedo analizar puntos y trazar una ruta en un mapa de Google en Android?
  • Geocode no funciona - Genymotion
  • Cómo ocultar mapview (google maps v2) cuando el fragmento cambió
  • Eventos cercanos en una ciudad para aplicaciones Android
  • ¿Cómo mostrar múltiples marcadores con diferentes iconos en Google Maps Android API v2?
  • Android Google Maps: deshabilita el arrastrar en MapFragment
  • Error en la autorización de Google Maps para Android API v2
  • Mapas android carga asincrónica de elementos de superposición
  • Hacer que el marcador se pueda arrastrar tras un solo clic en Android
  • Azulejos personalizados borrosos en Android Maps V2
  • Cómo adjuntar un marcador flexible en el mapa algo así como Uber y Lyft?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.