studio mapview mapa google example activity android android-maps-v2 supportmapfragment

mapview - mapa en fragment android



Error al abrir SupportMapFragment por segunda vez (11)

Después de mucho Hit e intenta y finalmente logro usar MapView Fragment de manera perfecta en mi aplicación y el resultado es similar a este:

, aquí está mi clase de fragmento MapView: -

import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.OnMapClickListener; import com.google.android.gms.maps.MapFragment; 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; import com.serveroverload.yago.R; public class HomeFragment extends Fragment implements LocationListener { // Class to do operations on the Map GoogleMap googleMap; private LocationManager locationManager; public static Fragment newInstance() { return new HomeFragment(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.home_fragment, container, false); Bundle bdl = getArguments(); // setuping locatiomanager to perfrom location related operations locationManager = (LocationManager) getActivity().getSystemService( Context.LOCATION_SERVICE); // Requesting locationmanager for location updates locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 1, 1, this); // To get map from MapFragment from layout googleMap = ((MapFragment) getActivity().getFragmentManager() .findFragmentById(R.id.map)).getMap(); // To change the map type to Satellite // googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE); // To show our current location in the map with dot // googleMap.setMyLocationEnabled(true); // To listen action whenever we click on the map googleMap.setOnMapClickListener(new OnMapClickListener() { @Override public void onMapClick(LatLng latLng) { /* * LatLng:Class will give us selected position lattigude and * longitude values */ Toast.makeText(getActivity(), latLng.toString(), Toast.LENGTH_LONG).show(); } }); changeMapMode(3); // googleMap.setSatellite(true); googleMap.setTrafficEnabled(true); googleMap.setBuildingsEnabled(true); googleMap.setMyLocationEnabled(true); return v; } private void doZoom() { if (googleMap != null) { googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom( new LatLng(18.520430, 73.856744), 17)); } } private void changeMapMode(int mapMode) { if (googleMap != null) { switch (mapMode) { case 0: googleMap.setMapType(GoogleMap.MAP_TYPE_NONE); break; case 1: googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); break; case 2: googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE); break; case 3: googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN); break; case 4: googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); break; default: break; } } } private void createMarker(double latitude, double longitude) { // double latitude = 17.385044; // double longitude = 78.486671; // lets place some 10 random markers for (int i = 0; i < 10; i++) { // random latitude and logitude double[] randomLocation = createRandLocation(latitude, longitude); // Adding a marker MarkerOptions marker = new MarkerOptions().position( new LatLng(randomLocation[0], randomLocation[1])).title( "Hello Maps " + i); Log.e("Random", "> " + randomLocation[0] + ", " + randomLocation[1]); // changing marker color if (i == 0) marker.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_AZURE)); if (i == 1) marker.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_BLUE)); if (i == 2) marker.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_CYAN)); if (i == 3) marker.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_GREEN)); if (i == 4) marker.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)); if (i == 5) marker.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_ORANGE)); if (i == 6) marker.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_RED)); if (i == 7) marker.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_ROSE)); if (i == 8) marker.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_VIOLET)); if (i == 9) marker.icon(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_YELLOW)); googleMap.addMarker(marker); // Move the camera to last position with a zoom level if (i == 9) { CameraPosition cameraPosition = new CameraPosition.Builder() .target(new LatLng(randomLocation[0], randomLocation[1])) .zoom(15).build(); googleMap.animateCamera(CameraUpdateFactory .newCameraPosition(cameraPosition)); } } } /* * creating random postion around a location for testing purpose only */ private double[] createRandLocation(double latitude, double longitude) { return new double[] { latitude + ((Math.random() - 0.5) / 500), longitude + ((Math.random() - 0.5) / 500), 150 + ((Math.random() - 0.5) * 10) }; } @Override public void onLocationChanged(Location location) { if (null != googleMap) { // To get lattitude value from location object double latti = location.getLatitude(); // To get longitude value from location object double longi = location.getLongitude(); // To hold lattitude and longitude values LatLng position = new LatLng(latti, longi); createMarker(latti, longi); // Creating object to pass our current location to the map MarkerOptions markerOptions = new MarkerOptions(); // To store current location in the markeroptions object markerOptions.position(position); // Zooming to our current location with zoom level 17.0f googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(position, 17f)); // adding markeroptions class object to the map to show our current // location in the map with help of default marker googleMap.addMarker(markerOptions); } } @Override public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } @Override public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } @Override public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } @Override public void onDestroyView() { // TODO Auto-generated method stub super.onDestroyView(); locationManager.removeUpdates(this); android.app.Fragment fragment = getActivity().getFragmentManager() .findFragmentById(R.id.map); if (null != fragment) { android.app.FragmentTransaction ft = getActivity() .getFragmentManager().beginTransaction(); ft.remove(fragment); ft.commit(); } } }

Mi archivo Xml se ve así: -

<?xml version="1.0" encoding="utf-8"?> <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/map" android:name="com.google.android.gms.maps.MapFragment" android:layout_width="match_parent" android:layout_height="match_parent" />

Lo más importante a tener en cuenta es que la aplicación DO No Mix. El fragmento con la aplicación v4.Fragments else se bloqueará gravemente.

Como puede ver, he usado la aplicación. Fragmento para adjuntar y eliminar mi fragmento MapView

Espero que ayude a alguien

Al abrir mi SupportMapFragment (Android maps v2) por segunda vez (llamando a setContentView) aparece el siguiente error:

01-28 16:27:21.374: E/AndroidRuntime(32743): FATAL EXCEPTION: main 01-28 16:27:21.374: E/AndroidRuntime(32743): android.view.InflateException: Binary XML file line #6: Error inflating class fragment 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.inflate(LayoutInflater.java:352) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.View.inflate(View.java:16119) 01-28 16:27:21.374: E/AndroidRuntime(32743): at mypackage.MyView.<init>(HitsView.java:26) 01-28 16:27:21.374: E/AndroidRuntime(32743): at mypackage.MenuListFragment.onItemClick(MenuListFragment.java:133) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.widget.AdapterView.performItemClick(AdapterView.java:298) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.widget.AbsListView.performItemClick(AbsListView.java:1086) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.widget.AbsListView$PerformClick.run(AbsListView.java:2855) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.widget.AbsListView$1.run(AbsListView.java:3529) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.os.Handler.handleCallback(Handler.java:615) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.os.Handler.dispatchMessage(Handler.java:92) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.os.Looper.loop(Looper.java:137) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.app.ActivityThread.main(ActivityThread.java:4745) 01-28 16:27:21.374: E/AndroidRuntime(32743): at java.lang.reflect.Method.invokeNative(Native Method) 01-28 16:27:21.374: E/AndroidRuntime(32743): at java.lang.reflect.Method.invoke(Method.java:511) 01-28 16:27:21.374: E/AndroidRuntime(32743): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 01-28 16:27:21.374: E/AndroidRuntime(32743): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 01-28 16:27:21.374: E/AndroidRuntime(32743): at dalvik.system.NativeStart.main(Native Method) 01-28 16:27:21.374: E/AndroidRuntime(32743): Caused by: java.lang.IllegalArgumentException: Binary XML file line #6: Duplicate id 0x7f04003b, tag null, or parent id 0x0 with another fragment for com.google.android.gms.maps.SupportMapFragment 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:285) 01-28 16:27:21.374: E/AndroidRuntime(32743): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676) 01-28 16:27:21.374: E/AndroidRuntime(32743): ... 20 more

El archivo XML:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:map="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <fragment android:id="@+id/hits_map" android:layout_width="match_parent" android:layout_height="wrap_content" class="com.google.android.gms.maps.SupportMapFragment" map:mapType="normal" map:uiZoomControls="false" map:uiZoomGestures="true" map:cameraZoom="13" map:uiRotateGestures="true" map:uiTiltGestures="true"/> </RelativeLayout>

MyView.class:

public class MyView extends RelativeLayout { private GoogleMap map; public MyView(Context context, FragmentActivity activity) { super(context); inflate(activity, R.layout.activity_hits, this); this.map = ((SupportMapFragment) activity.getSupportFragmentManager() .findFragmentById(R.id.hits_map)).getMap(); } }

No tengo idea de lo que significa este error. ¿Alguien puede explicar esto?


En lugar de declarar de SupportMapFragment en el diseño, hágalo programáticamente y asegúrese de usar getChildFragmentMananger en lugar del clásico getFragmentManager () para crear el fragmento.

mMapFragment = SupportMapFragment.newInstance(); FragmentTransaction fragmentTransaction = mMapFragment.getChildFragmentManager().beginTransaction(); fragmentTransaction.add(R.id.map_root, mMapFragment); fragmentTransaction.commit();

Mantenga este SupportMapFragment mMapFragment ya que lo necesitará para recuperar el objeto GoogleMap:

GoogleMap map = mMapFragment.getMap();


Intenté varias soluciones propuestas aquí, y el mejor en mi humilde opinión es el MapView. De todos modos, encontré otra solución que podría satisfacer sus necesidades (o tal vez no).

Tenía mi SupportMapFragment dentro de ViewPager+FragmentPagerAdapter con 3 pestañas. Así que simplemente configuré el ViewPager de una manera que nunca destruye la pestaña donde está el SupportMapFragment .

viewPager.setOffScreenPageLimit(2); viewPager.setAdapter(...);

Con esta llamada, ViewPager siempre mantendrá dos páginas después y dos páginas antes de la actual, de modo que ninguna de mis tres pestañas nunca se destruirá / recreará.

Problema resuelto :)

Tenga en cuenta que el consumo de memoria aumentará


Me encontré con este problema y encontré en mis registros de Android que mi aceleración de hardware no estaba activada. Después de encenderlo en mi AndroidManifest, estaba visualizando los mapas varias veces y ya no era un problema. Estaba usando un emulador x86.


Me he pasado medio día resolviendo este problema y solo encontré una solución alternativa. Reemplace su método YourFragment en YourFragment clase YourFragment :

public void onCreate(Bundle savedInstanceState) { setRetainInstance(true); super.onCreate(savedInstanceState); }

Y anule su método onDestroy :

@Override public void onDestroyView() { super.onDestroyView(); try { SupportMapFragment fragment = (SupportMapFragment) getActivity() .getSupportFragmentManager().findFragmentById( R.id.multi_inns_on_map); if (fragment != null) getFragmentManager().beginTransaction().remove(fragment).commit(); } catch (IllegalStateException e) { //handle this situation because you are necessary will get //an exception here :-( } }


Pasé todo este día buscando la solución a este problema, leyendo toda la solución aquí, y encontré esta manera de resolver los problemas. Publicaré todo el código, porque a esta pregunta le falta una respuesta completa, solo un pequeño fragmento que coincide con un escenario completo y ayuda a cualquiera.

public class LocationFragment extends Fragment implements View.OnClickListener { private GoogleMap googleMap; private static View rootView; private SupportMapFragment supportMapFragment; public LocationFragment() { } @Override public void onDestroyView() { super.onDestroyView(); } @Override public void onCreate(Bundle savedInstanceState) { setRetainInstance(true); super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if(savedInstanceState == null) { if (rootView != null) { ViewGroup parent = (ViewGroup) rootView.getParent(); if (parent != null) parent.removeView(rootView); } try{ if(rootView == null) { rootView = inflater.inflate(R.layout.fragment_location, container, false); } supportMapFragment = (SupportMapFragment) getFragmentManager().findFragmentById(R.id.map); LocationUtility locationUtility = LocationUtility.getInstance(context); GoogleMap googleMap = locationUtility.initilizeMap(supportMapFragment); //More code } catch (Exception e) { e.printStackTrace(); } } return rootView; } }

Al depurar esto, notará que no importa cómo funciona el fragmento, no necesita botter para onDestroyMethod, etc., ya que la validación de nulo solo funciona con la instancia actual del objeto.

¡Disfrutar! ;)


Tengo el mismo problema y lo solucioné al crear Google Map dinámicamente. Lo que tienes que hacer es crear una clase que extienda la clase SupportMapFragment .

Este método funciona en gingerbread a lollipop y en fragmentos anidados porque creará el mapa de forma dinámica, por lo que no tendrá que preocuparse por eliminar el fragmento ni nada de eso.

Paso 1:

public class DynamicMapFragment extends SupportMapFragment { public GoogleMap googleMap; public View mOriginalContentView; public static int statusGooglePlayService; @Override public void onCreate(Bundle arg0) { super.onCreate(arg0); } @Override public View onCreateView(LayoutInflater mInflater, ViewGroup parent, Bundle arg2) { mOriginalContentView = super.onCreateView(mInflater, parent, arg2); //this is for getting height of the phone screen DisplayMetrics displaymetrics = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay() .getMetrics(displaymetrics); int height = displaymetrics.heightPixels; //Here you can define the height of the map as you desire FrameLayout.LayoutParams parentLayout = new FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, height / 3); mOriginalContentView.setLayoutParams(parentLayout); return mOriginalContentView; } @Override public View getView() { return mOriginalContentView; } @Override public void onInflate(Activity arg0, AttributeSet arg1, Bundle arg2) { super.onInflate(arg0, arg1, arg2); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); googleMap = getMap(); statusGooglePlayService = GooglePlayServicesUtil .isGooglePlayServicesAvailable(getActivity()); if (statusGooglePlayService == ConnectionResult.SUCCESS) { if (googleMap != null) { // do whatever you want to do with map } } else { Dialog dialog = GooglePlayServicesUtil.getErrorDialog( statusGooglePlayService, getActivity(), -1); dialog.show(); } } }

Luego llama a la clase creada anteriormente desde Activity, Fragment como esta:

Paso 2:

//Calling the method from a fragment private void createMap(View rootView) { FrameLayout mapLayout = (FrameLayout)rootView.findViewById(R.id.location_map); FragmentTransaction mTransaction = getActivity() .getSupportFragmentManager().beginTransaction(); SupportMapFragment mFRaFragment = new DynamicMapFragment(); mTransaction.add(mapLayout.getId(), mFRaFragment); mTransaction.commit(); try { MapsInitializer.initialize(activity); } catch (Exception e) { e.printStackTrace(); } }

Diseño XML para fragmento en el que tiene que agregar Framelayout en lugar de un fragmento para el mapa

Paso 3:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <FrameLayout android:id="@+id/location_map" android:layout_width="match_parent" android:layout_height="250dp" android:layout_weight="0" /> <!-- You can add any other view also whatever you want to add <Button android:layout_width="match_parent" android:layout_height=""wrap_content"" android:layout_weight="0" /> --> </LinearLayout>


prueba este código

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { finder = new LocationFinder(getActivity()); view = inflater.inflate(R.layout.fragment_secondfragement, container, false); initMap(); // getLocation(); return view; } public void initMap(){ if (map == null) { mapFragment = (SupportMapFragment) getChildFragmentManager() .findFragmentById(R.id.map); } map = mapFragment.getMap(); map.setMyLocationEnabled(true); map.getUiSettings().setMyLocationButtonEnabled(true); }


solo ponte onCreateView

if (view != null) { ViewGroup parent = (ViewGroup) view.getParent(); if (parent != null) parent.removeView(view); } view = inflater.inflate(R.layout.map, container, false);


Actualización: como una solución alternativa (que creo que es mucho mejor) puede utilizar un MapView que se describe: here

Me encontré con un problema similar al trabajar con una implementación de pestañas. Con Google Maps V2, está atrapado con el SupportMapFragment, por lo que usar MapView no es una opción. Entre la publicación de juanmeanwhile y el comentario n. ° 1 que se encuentran aquí ( https://code.google.com/p/gmaps-api-issues/issues/detail?id=5064#c1 ), logré descubrir qué estaba haciendo mal.

Entonces, para cualquier otra persona que obtenga el error de Id. Duplicado, asegúrese de declarar el fragmento programáticamente, no en XML. Esto probablemente significa diseños de anidamiento.

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:map="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- Lots of fancy layout --> <RelativeLayout android:id="@+id/map" android:layout_width="match_parent" android:layout_height="wrap_content"> </RelativeLayout> </RelativeLayout>

Luego debe crear su fragmento programáticamente, pero debe hacerse cuidadosamente teniendo en cuenta el ciclo de vida de Fragments ( http://developer.android.com/reference/android/app/Fragment.html#getChildFragmentManager() ). Para asegurarse de que todo se crea en el momento correcto, su código debe verse así (tomado del comentario n. ° 1).

public class MyFragment extends Fragment { private SupportMapFragment fragment; private GoogleMap map; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.layout_with_map, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); FragmentManager fm = getChildFragmentManager(); fragment = (SupportMapFragment) fm.findFragmentById(R.id.map); if (fragment == null) { fragment = SupportMapFragment.newInstance(); fm.beginTransaction().replace(R.id.map, fragment).commit(); } } @Override public void onResume() { super.onResume(); if (map == null) { map = fragment.getMap(); map.addMarker(new MarkerOptions().position(new LatLng(0, 0))); } } }

Espero que esto ahorre algo de tiempo.


private MainActivity mainActObj; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mainActObj = getMainActivity(); } @SuppressWarnings("unchecked") @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (mainActObj.mapView == null) { return mainActObj.mapView = inflater.inflate(R.layout.fragment_map, null); } else { ViewGroup parent = (ViewGroup) mainActObj.mapView.getParent(); if (parent != null) { parent.removeView(mainActObj.mapView); } try { return mainActObj.mapView = inflater.inflate( R.layout.fragment_map, container, false); } catch (InflateException except) { return mainActObj.mapView; } } }