Lorsque j’ouvre mon SupportMapFragment (Android maps v2) une seconde fois (en appelant setContentView), j’obtiens l’erreur suivante:
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.(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
Le fichier XML:
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(); } }
Je n’ai aucune idée de ce que signifie cette erreur. Quelqu’un peut-il expliquer cela?
Au lieu de déclarer de SupportMapFragment dans la présentation, faites-le par programmation et assurez-vous d’utiliser getChildFragmentMananger au lieu du classique getFragmentManager () pour créer le fragment.
mMapFragment = SupportMapFragment.newInstance(); FragmentTransaction fragmentTransaction = mMapFragment.getChildFragmentManager().beginTransaction(); fragmentTransaction.add(R.id.map_root, mMapFragment); fragmentTransaction.commit();
Conservez ce SupportMapFragment mMapFragment car vous en aurez besoin pour récupérer l’object GoogleMap:
GoogleMap map = mMapFragment.getMap();
Mise à jour: En tant que solution alternative (ce que je pense être beaucoup mieux), vous pouvez utiliser un MapView décrit: ici
J’ai rencontré un problème similaire en travaillant avec une implémentation d’tabs. Avec Google Maps V2, vous êtes coincé avec le SupportMapFragment, donc l’utilisation de MapView n’est pas une option. Entre le message de juanmeanwhile et le commentaire n ° 1 trouvé ici ( https://code.google.com/p/gmaps-api-issues/issues/detail?id=5064#c1 ), j’ai réussi à comprendre ce que je faisais mal.
Donc, pour toute autre personne obtenant l’erreur d’ID en double, assurez-vous de déclarer le fragment par programme, pas en XML. Cela signifie probablement des dispositions de nidification.
Ensuite, vous devez créer votre fragment par programme, mais cela doit être fait avec soin en tenant compte du cycle de vie des fragments ( http://developer.android.com/reference/android/app/Fragment.html#getChildFragmentManager () ). Pour vous assurer que tout est créé au bon moment, votre code devrait ressembler à ceci (extrait du commentaire 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))); } } }
Espérons que cela économise du temps.
J’ai passé une demi-journée à résoudre ce problème et à trouver une solution de rechange. Remplacez votre méthode YourFragment
dans la classe YourFragment
:
public void onCreate(Bundle savedInstanceState) { setRetainInstance(true); super.onCreate(savedInstanceState); }
Et remplacez votre méthode 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 :-( } }
J’ai passé toute cette journée à chercher la solution à ce problème, en lisant tout le travail ici, et j’ai trouvé cette façon de résoudre les problèmes. Je posterai tout le code, car cette question manque de réponse complète, juste un petit extrait qui correspond à un scénario complet et qui aide n’importe qui.
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; } }
En déboguant ceci, vous remarquerez que peu importe le fonctionnement du fragment, vous n’avez pas besoin de botter pour la méthode onDestroyMetc, puisque la validation de null fonctionne uniquement avec l’instance courante de l’object.
Prendre plaisir! 😉
J’ai rencontré ce problème et trouvé dans mes journaux Android que mon accélération matérielle n’était pas activée. Après l’avoir activé dans mon AndroidManifest, je affichais plusieurs fois les cartes n’était plus un problème. J’utilisais un émulateur x86.
Après de nombreux essais et essais et que je parviens enfin à utiliser MapView Fragment parfaitement dans mon application et que le résultat se présente comme suit: –
, voici ma classe de fragments 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.toSsortingng(), 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(Ssortingng provider, int status, Bundle extras) { // TODO Auto-generated method stub } @Override public void onProviderEnabled(Ssortingng provider) { // TODO Auto-generated method stub } @Override public void onProviderDisabled(Ssortingng 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(); } } }
Mon fichier XML ressemble à ceci: –
La chose la plus importante à noter est que l’application Ne pas mélanger l’application.Fragment avec l’application v4.Fragments tombera en panne.
Comme vous pouvez le voir, j’ai utilisé app.Fragment pour joindre et supprimer mon fragment MapView
J’espère que ça aidera quelqu’un
J’ai essayé différentes solutions proposées ici, et le meilleur IMHO est le MapView. Quoi qu’il en soit, j’ai trouvé une autre solution qui pourrait convenir à vos besoins (ou peut-être pas).
J’ai eu mon SupportMapFragment
dans un ViewPager+FragmentPagerAdapter
avec 3 tabs. Je viens donc de configurer le ViewPager de manière à ce qu’il ne détruise jamais l’onglet où se trouve SupportMapFragment
.
viewPager.setOffScreenPageLimit(2); viewPager.setAdapter(...);
Avec cet appel, le ViewPager conservera toujours deux pages après et deux pages avant la page courante, donc aucun de mes trois tabs n’est jamais détruit / recréé.
Problème résolu 🙂
Notez que la consommation de mémoire augmentera
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; } } }
essayer ce code
@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); }
J’ai le même problème et résolu en créant dynamicment Google Map. Ce que vous devez faire, c’est créer une classe qui étend la classe SupportMapFragment .
Cette méthode fonctionne sur gingerbread to lollipop et sur les fragments nesteds, car elle créera la carte dynamicment, vous n’avez donc pas à vous soucier de supprimer le fragment ou quelque chose du genre.
Étape 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 DisplayMesortingcs displaymesortingcs = new DisplayMesortingcs(); getActivity().getWindowManager().getDefaultDisplay() .getMesortingcs(displaymesortingcs); int height = displaymesortingcs.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, AtsortingbuteSet 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(); } } }
Puis appelez la classe créée ci-dessus à partir d’Activité, fragment comme ceci:
Étape 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(); } }
Agencement XML pour fragment où vous devez append Framelayout au lieu d’un fragment pour map
Étape 3:
il suffit de mettre onCreateView
if (view != null) { ViewGroup parent = (ViewGroup) view.getParent(); if (parent != null) parent.removeView(view); } view = inflater.inflate(R.layout.map, container, false);