Cómo poner Google Maps V2 en un fragmento usando ViewPager

Estoy intentando hacer un diseño de pestaña igual en Play Store. Tengo que mostrar el diseño de las tabs usando fragmentos y viewpager de androidhive. Sin embargo, no puedo implementar google maps v2 en él. Busqué en Internet por horas pero no puedo encontrar un tutorial sobre cómo hacerlo. ¿Puede alguien por favor mostrarme cómo? ¡Gracias!

Al usar este código, podemos configurar MapView en cualquier lugar, dentro de cualquier ViewPager o Fragmento o Actividad.

En la última actualización de Google para Maps, solo MapView es compatible con fragmentos. MapFragment & SupportMapFragment no funciona. Puede que me equivoque, pero esto es lo que vi después de intentar implementar MapFragment & SupportMapFragment.

Configuración del diseño para mostrar el mapa. location_fragment.xml :

     

Ahora codificamos la clase java para mostrar el mapa. MapViewFragment :

 public class MapViewFragment extends Fragment { MapView mMapView; private GoogleMap googleMap; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.location_fragment, container, false); mMapView = (MapView) rootView.findViewById(R.id.mapView); mMapView.onCreate(savedInstanceState); mMapView.onResume(); // needed to get the map to display immediately try { MapsInitializer.initialize(getActivity().getApplicationContext()); } catch (Exception e) { e.printStackTrace(); } mMapView.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(GoogleMap mMap) { googleMap = mMap; // For showing a move to my location button googleMap.setMyLocationEnabled(true); // For dropping a marker at a point on the Map LatLng sydney = new LatLng(-34, 151); googleMap.addMarker(new MarkerOptions().position(sydney).title("Marker Title").snippet("Marker Description")); // For zooming automatically to the location of the marker CameraPosition cameraPosition = new CameraPosition.Builder().target(sydney).zoom(12).build(); googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); } }); return rootView; } @Override public void onResume() { super.onResume(); mMapView.onResume(); } @Override public void onPause() { super.onPause(); mMapView.onPause(); } @Override public void onDestroy() { super.onDestroy(); mMapView.onDestroy(); } @Override public void onLowMemory() { super.onLowMemory(); mMapView.onLowMemory(); } } 

Finalmente, debe obtener la clave API para su aplicación registrando su aplicación en Google Cloud Console . Registre su aplicación como aplicación nativa de Android.

El siguiente enfoque funciona para mí.

 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.MapView; import com.google.android.gms.maps.MapsInitializer; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; /** * A fragment that launches other parts of the demo application. */ public class MapFragment extends Fragment { MapView mMapView; private GoogleMap googleMap; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // inflat and return the layout View v = inflater.inflate(R.layout.fragment_location_info, container, false); mMapView = (MapView) v.findViewById(R.id.mapView); mMapView.onCreate(savedInstanceState); mMapView.onResume();// needed to get the map to display immediately try { MapsInitializer.initialize(getActivity().getApplicationContext()); } catch (Exception e) { e.printStackTrace(); } googleMap = mMapView.getMap(); // latitude and longitude double latitude = 17.385044; double longitude = 78.486671; // create marker MarkerOptions marker = new MarkerOptions().position( new LatLng(latitude, longitude)).title("Hello Maps"); // Changing marker icon marker.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_ROSE)); // adding marker googleMap.addMarker(marker); CameraPosition cameraPosition = new CameraPosition.Builder() .target(new LatLng(17.385044, 78.486671)).zoom(12).build(); googleMap.animateCamera(CameraUpdateFactory .newCameraPosition(cameraPosition)); // Perform any camera updates here return v; } @Override public void onResume() { super.onResume(); mMapView.onResume(); } @Override public void onPause() { super.onPause(); mMapView.onPause(); } @Override public void onDestroy() { super.onDestroy(); mMapView.onDestroy(); } @Override public void onLowMemory() { super.onLowMemory(); mMapView.onLowMemory(); } } 

fragment_location_info.xml

   

Puede usar esta línea si quiere usar GoogleMap en un fragmento:

  

 GoogleMap mGoogleMap = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map)).getMap(); 

Últimas cosas con getMapAsync lugar de la obsoleta.

1. verificar manifiesto para

  

Puede obtener la clave de API para su aplicación registrando su aplicación en Google Cloud Console . Registre su aplicación como aplicación nativa de Android

2. en su diseño de fragmento .xml add FrameLayout (no fragmento):

   

o la altura que quieras

3. En onCreateView en tu fragmento

  private SupportMapFragment mSupportMapFragment; mSupportMapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.mapwhere); if (mSupportMapFragment == null) { FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); mSupportMapFragment = SupportMapFragment.newInstance(); fragmentTransaction.replace(R.id.mapwhere, mSupportMapFragment).commit(); } if (mSupportMapFragment != null) { mSupportMapFragment.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(GoogleMap googleMap) { if (googleMap != null) { googleMap.getUiSettings().setAllGesturesEnabled(true); -> marker_latlng // MAKE THIS WHATEVER YOU WANT CameraPosition cameraPosition = new CameraPosition.Builder().target(marker_latlng).zoom(15.0f).build(); CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition); googleMap.moveCamera(cameraUpdate); } } }); 

aquí lo que hice en detalle:

Desde aquí puede obtener la clave de la API de Google Map

forma alternativa y simple

primero inicie sesión en su cuenta de google y visite las bibliotecas de google y seleccione Google Maps Android API

dependencia encontrada en la actividad del mapa por defecto del estudio de Android:

 compile 'com.google.android.gms:play-services:10.0.1' 

pon tu clave en el archivo principal de Android en la aplicación como a continuación

en AndroidMainifest.xml hacer estos cambios:

  // required permission  // google map api key put under/inside  // android:value="YOUR API KEY"  

Código de fragmento:

 public class MainBranchFragment extends Fragment implements OnMapReadyCallback{ private GoogleMap mMap; public MainBranchFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view= inflater.inflate(R.layout.fragment_main_branch, container, false); SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.main_branch_map); mapFragment.getMapAsync(this); return view; } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; LatLng UCA = new LatLng(-34, 151); mMap.addMarker(new MarkerOptions().position(UCA).title("YOUR TITLE")).showInfoWindow(); mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(UCA,17)); } } 

en ti fragmento xml:

  

Para el problema de obtener una NullPointerException cuando cambiamos las tabs en un FragmentTabHost , solo necesitas agregar este código a tu clase que tiene el TabHost . Me refiero a la clase donde inicializas las tabs. Este es el código:

 /**** Fix for error : Activity has been destroyed, when using Nested tabs * We are actually detaching this tab fragment from the `ChildFragmentManager` * so that when this inner tab is viewed back then the fragment is attached again****/ import java.lang.reflect.Field; @Override public void onDetach() { super.onDetach(); try { Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager"); childFragmentManager.setAccessible(true); childFragmentManager.set(this, null); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } 
 public class DemoFragment extends Fragment { MapView mapView; GoogleMap map; LatLng CENTER = null; public LocationManager locationManager; double longitudeDouble; double latitudeDouble; String snippet; String title; Location location; String myAddress; String LocationId; String CityName; String imageURL; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub View view = inflater .inflate(R.layout.fragment_layout, container, false); mapView = (MapView) view.findViewById(R.id.mapView); mapView.onCreate(savedInstanceState); setMapView(); } private void setMapView() { try { MapsInitializer.initialize(getActivity()); switch (GooglePlayServicesUtil .isGooglePlayServicesAvailable(getActivity())) { case ConnectionResult.SUCCESS: // Toast.makeText(getActivity(), "SUCCESS", Toast.LENGTH_SHORT) // .show(); // Gets to GoogleMap from the MapView and does initialization // stuff if (mapView != null) { locationManager = ((LocationManager) getActivity() .getSystemService(Context.LOCATION_SERVICE)); Boolean localBoolean = Boolean.valueOf(locationManager .isProviderEnabled("network")); if (localBoolean.booleanValue()) { CENTER = new LatLng(latitude, longitude); } else { } map = mapView.getMap(); if (map == null) { Log.d("", "Map Fragment Not Found or no Map in it!!"); } map.clear(); try { map.addMarker(new MarkerOptions().position(CENTER) .title(CityName).snippet("")); } catch (Exception e) { e.printStackTrace(); } map.setIndoorEnabled(true); map.setMyLocationEnabled(true); map.moveCamera(CameraUpdateFactory.zoomTo(5)); if (CENTER != null) { map.animateCamera( CameraUpdateFactory.newLatLng(CENTER), 1750, null); } // add circle CircleOptions circle = new CircleOptions(); circle.center(CENTER).fillColor(Color.BLUE).radius(10); map.addCircle(circle); map.setMapType(GoogleMap.MAP_TYPE_NORMAL); } break; case ConnectionResult.SERVICE_MISSING: break; case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED: break; default: } } catch (Exception e) { } } 

en fragment_layout

  

Cuando agrega el uso de su mapa:

 getChildFragmentManager().beginTransaction() .replace(R.id.menu_map_container, mapFragment, "f" + shabbatIndex).commit(); 

en lugar de .add y en lugar de getFragmentManager .

simplemente creé MapActivity y lo inflaré para fragmentarlo. MapActivity.java:

 package com.example.ahmedsamra.mansouratourguideapp; import android.support.v4.app.FragmentActivity; import android.os.Bundle; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; public class MapsActivity extends FragmentActivity implements OnMapReadyCallback { private GoogleMap mMap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_categories);//layout for container getSupportFragmentManager().beginTransaction() .replace(R.id.container, new MapFragment()) .commit(); // Obtain the SupportMapFragment and get notified when the map is ready to be used. SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } /** * Manipulates the map once available. * This callback is triggered when the map is ready to be used. * This is where we can add markers or lines, add listeners or move the camera. In this case, * we just add a marker near Sydney, Australia. * If Google Play services is not installed on the device, the user will be prompted to install * it inside the SupportMapFragment. This method will only be triggered once the user has * installed Google Play services and returned to the app. */ @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; // Add a marker in Sydney and move the camera LatLng mansoura = new LatLng(31.037933, 31.381523); mMap.addMarker(new MarkerOptions().position(mansoura).title("Marker in mansoura")); mMap.moveCamera(CameraUpdateFactory.newLatLng(mansoura)); } } 

activity_map.xml:

  

MapFragment.java:-

 package com.example.ahmedsamra.mansouratourguideapp; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /** * A simple {@link Fragment} subclass. */ public class MapFragment extends Fragment { public MapFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.activity_maps,container,false); return rootView; } } 

Tengo una solución alternativa para NullPointerException cuando DestoryView el fragmento en DestoryView . Simplemente ponga su código en onStop() no onDestoryView . ¡Funciona bien!

 @Override public void onStop() { super.onStop(); if (mMap != null) { MainActivity.fragmentManager.beginTransaction() .remove(MainActivity.fragmentManager.findFragmentById(R.id.location_map)).commit(); mMap = null; } } 

De acuerdo con https://developer.android.com/about/versions/android-4.2.html#NestedFragments , puede usar fragmentos nesteds para lograr esto llamando a getChildFragmentManager () si aún desea usar el fragmento de Google Maps en lugar del ver dentro de tu propio fragmento:

 SupportMapFragment mapFragment = new SupportMapFragment(); FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); transaction.add(R.id.content, mapFragment).commit(); 

donde “contenido” es el diseño de la raíz en su fragmento (preferiblemente un FrameLayout). La ventaja de usar un fragmento de mapa es que el sistema administra automáticamente el ciclo de vida del mapa.

Aunque la documentación dice “No se puede inflar un diseño en un fragmento cuando ese diseño incluye un . Los fragmentos nesteds solo se admiten cuando se agregan dinámicamente a un fragmento.”, De alguna manera lo he hecho con éxito y funcionó bien. Aquí está mi código:
En el método onCreateView () del fragmento:

 View view = inflater.inflate(R.layout.layout_maps, container, false); SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(...); 

En el diseño:

  

¡Espero eso ayude!

Adición dinámica de fragmento de mapa para ver el Buscapersonas:

Si tiene como objective una aplicación anterior al nivel 12 de API, cree una instancia de SupportedMapFragment y agréguela a su adaptador de página de visualización.

 SupportMapFragment supportMapFragment=SupportMapFragment.newInstance(); supportMapFragment.getMapAsync(this); 

API de nivel 12 o superior admite objetos MapFragment

 MapFragment mMapFragment=MapFragment.newInstance(); mMapFragment.getMapAsync(this);