Je développe une application à l’aide d’une variable NavigationDrawer
, c’est-à-dire DrawerLayout
, et je navigue vers différents Fragments
. Lorsque j'appelle un Map_Fragment_Page
, l'application se bloque, mais pas la première fois. Pour la première fois, il affiche correctement la variable Map
, mais après cela, lorsque je navigue dans différents fragments et que je reviens à Map_Fragment_Page
, il se bloque et génère une erreur Android.view.InflateException: Binary XML file line #8: Error inflating class fragment
.
J'ai essayé tellement de solutions différentes et j'ai également effectué une recherche sur Google
mais je n'ai toujours pas obtenu la solution requise. Le problème n'est pas encore résolu.
howtoreach.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<fragment
Android:id="@+id/howtoreach_map"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
class="com.google.Android.gms.maps.SupportMapFragment"/>
</RelativeLayout>
HowToReach.Java
package com.demo.map.howtoreach;
import com.google.Android.gms.maps.CameraUpdateFactory;
import com.google.Android.gms.maps.GoogleMap;
import Android.support.v4.app.Fragment;
import com.google.Android.gms.maps.SupportMapFragment;
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.Marker;
import com.google.Android.gms.maps.model.MarkerOptions;
import com.google.Android.gms.maps.model.Polyline;
import com.google.Android.gms.maps.model.PolylineOptions;
import com.demo.map.R;
import Android.app.ProgressDialog;
import Android.content.Context;
import Android.graphics.Color;
import Android.location.Criteria;
import Android.location.Location;
import Android.location.LocationManager;
import Android.os.Bundle;
import Android.os.Handler;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.Toast;
public class HowToReach extends Fragment
{
public static final String TAG = "fragment_5";
ProgressDialog dialog;
GoogleMap googleMap;
Marker marker;
LocationManager locationManager;
Location location;
Criteria criteria;
String provider;
double latitude, longitude;
public HowToReach(){}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.howtoreach, container, false);
dialog = ProgressDialog.show(getActivity(),"","Loading",true,false);
int secondsDelayed = 4;
new Handler().postDelayed(new Runnable()
{
public void run()
{
dialog.dismiss();
}
}, secondsDelayed * 1000);
try
{
// Loading map
if (googleMap == null)
{
googleMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();
googleMap.setMyLocationEnabled(true);
locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, true);
location = locationManager.getLastKnownLocation(provider);
latitude = location.getLatitude();
longitude = location.getLongitude();
// create marker
marker = googleMap.addMarker(new MarkerOptions().position(
new LatLng(latitude, longitude)).title("You are Here"));
marker.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
marker.showInfoWindow();
CameraPosition cameraPosition = new CameraPosition.Builder().target(
new LatLng(latitude, longitude)).zoom(15).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
Polyline line = googleMap.addPolyline(new PolylineOptions()
.add(new LatLng(latitude, longitude), new LatLng(18.520897,73.772396))
.width(2).color(Color.RED).geodesic(true));
marker = googleMap.addMarker(new MarkerOptions().position(
new LatLng(18.520897, 73.772396)).title("DSK Ranwara Road"));
marker.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
// check if map is created successfully or not
if (googleMap == null)
{
Toast.makeText(getActivity(),"Sorry! unable to create maps", Toast.LENGTH_SHORT).show();
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return v;
}
}
Yes.. I want Map inside a Fragment.
Vous devriez utiliser un MapView
http://developer.Android.com/reference/com/google/Android/gms/maps/MapView.html
public class HowToReach extends Fragment {
MapView mapView;
GoogleMap map;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment2, container, false);
// Gets the MapView from the XML layout and creates it
try {
MapsInitializer.initialize(getActivity());
} catch (GooglePlayServicesNotAvailableException e) {
Log.e("Address Map", "Could not initialize google play", e);
}
switch (GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()) )
{
case ConnectionResult.SUCCESS:
Toast.makeText(getActivity(), "SUCCESS", Toast.LENGTH_SHORT).show();
mapView = (MapView) v.findViewById(R.id.map);
mapView.onCreate(savedInstanceState);
// Gets to GoogleMap from the MapView and does initialization stuff
if(mapView!=null)
{
map = mapView.getMap();
map.getUiSettings().setMyLocationButtonEnabled(false);
map.setMyLocationEnabled(true);
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(43.1, -87.9), 10);
map.animateCamera(cameraUpdate);
}
break;
case ConnectionResult.SERVICE_MISSING:
Toast.makeText(getActivity(), "SERVICE MISSING", Toast.LENGTH_SHORT).show();
break;
case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
Toast.makeText(getActivity(), "UPDATE REQUIRED", Toast.LENGTH_SHORT).show();
break;
default: Toast.makeText(getActivity(), GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()), Toast.LENGTH_SHORT).show();
}
// Updates the location and zoom of the MapView
return v;
}
@Override
public void onResume() {
mapView.onResume();
super.onResume();
}
@Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}
fragment2.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<com.google.Android.gms.maps.MapView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:id="@+id/map" />
</RelativeLayout>
Mettre à jour:
https://developers.google.com/Android/reference/com/google/Android/gms/maps/MapView#public-constructors
getMap()
est obsolète. Utilisez getMapAsync(OnMapReadyCallback)
à la place. La méthode de rappel vous fournit une instance de GoogleMap garantie comme étant non nulle et prête à être utilisée.
Donc, si cela se bloque après avoir ouvert le fragment une seconde fois ... Tout ce dont vous avez besoin est dans OnDestroy
@Override
public void onDestroy() {
super.onDestroy();
getFragmentManager().beginTransaction().remove(mapfragmentnamehere).commit();
}
Apportez les modifications nécessaires si vous utilisez fragment de support.
Mes expériences faites avec des fragments ajoutés par xml-tag
<fragment>...</fragment>.
Ces fragments sont normalement imbriqués et ne sont pas détruits lorsque le fragment parent est détruit. Une fois que vous essayez de les gonfler à nouveau, vous obtenez une exception qui se plaint fondamentalement d'avoir ce fragment déjà gonflé .. C'est pourquoi je détruis mes fragments imbriqués manuellement lorsque le fragment parent est détruit. Utilisez simplement les éléments suivants et ajustez-les à vos besoins. Ce code réside dans le fragment parent qui contient le fragment imbriqué en tant que balise xml.
@Override
public void onDestroy() {
super.onDestroy();
final FragmentManager fragManager = this.getFragmentManager();
final Fragment fragment = fragManager.findFragmentById(/*id of fragment*/);
if(fragment!=null){
fragManager.beginTransaction().remove(fragment).commit();
}
}
Avec les fragments créés dynamiquement, il n’ya aucun problème. Dynamiquement signifie: vous n'avez pas utilisé fragment-xml-tag
J'espère que cela t'aides! Bonne programmation!
Je mets ça dans mon fragment
@Override
public void onPause() {
super.onPause();
getChildFragmentManager().beginTransaction()
.remove(mMapFragment)
.commit();
}
Cela fonctionne sans remplacer à la MapView.
Change ça
googleMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();
à
googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();
Dans votre classe
View mTrackView = inflater.inflate(R.layout.mylayout, container, false);
SupportMapFragment mSupportMapFragment = SupportMapFragment.newInstance();
FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.mapwhere, mSupportMapFragment);
fragmentTransaction.commit();
if(mSupportMapFragment!=null){
googleMap = mSupportMapFragment.getMap();
if(googleMap!=null){
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
googleMap.getUiSettings().setMyLocationButtonEnabled(false);
googleMap.setMyLocationEnabled(false);
if (mgpr_tracker.canGetLocation())
CURREN_POSITION = new LatLng(mgpr_tracker.getLatitude(),
mgpr_tracker.getLongitude());
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(
CURREN_POSITION, ZOOM_LEVEL);
googleMap.animateCamera(cameraUpdate);
}
}
mylayout.xml
<LinearLayout
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"
Android:gravity="center"
Android:orientation="vertical" >
<FrameLayout
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="1.03"
Android:id="@+id/mapwhere" />
<TextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"/>
</LinearLayout>
Vérifiez que vous ayez ou non l'autorisation exacte du manifeste. Je n'avais pas inclus l'autorisation ci-dessous dans le manifeste, et c'était donner cette erreur.
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>
Veuillez inclure certaines des autorisations suivantes dans votre fichier manifeste
<!-- - THIS IS THE USER PERMISSION FOR GETTING LATITUDE AND LONGTITUDE FROM INTERNET -->
<uses-permission Android:name="Android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission Android:name="Android.permission.READ_PHONE_STATE" />
<uses-permission Android:name="Android.permission.GET_ACCOUNTS" />
<uses-permission Android:name="Android.permission.ACCESS_WIFI_STATE"/>
<uses-permission Android:name="Android.permission.UPDATE_DEVICE_STATS"/>
<uses-permission Android:name="Android.permission.CHANGE_WIFI_STATE"/>
J'ai reçu le même message d'erreur:
public View onCreateView(
LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState){
super.onCreateView(inflater,container,savedInstanceState);
self_view=inflater.inflate(R.layout.fragment_player,container,false);
return self_view;
}
onCreateView
peut être appelé plus d'une fois.Lorsque cela se produit, le code ci-dessus crée une nouvelle vue pour le fragment alors que l'ancienne est toujours là.
L'erreur apparaît avec un adaptateur et pas avec un autre; dans mon cas, FragmentStatePagerAdapter était heureux et FragmentPagerAdapter était meurtrier parce que le premier a détruit ses fragments et le dernier les a réutilisés.
Je mets ceci dans mon fragment quand j'ai un viewpager:
@Override
public void onPause() {
Fragment fragment = (getChildFragmentManager().findFragmentById(R.id.fragment_map_map));
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.remove(fragment);
ft.commit();
super.onPause();
}
Comment j'ai résolu mon problème après avoir beaucoup cherché, mettez ces lignes à l'intérieur de la méthode fragment onPause.
@Override
public void onPause() {
super.onPause();
final FragmentManager fragManager = this.getChildFragmentManager();
final Fragment fragment = fragManager.findFragmentById(R.id.map);
if(fragment!=null){
fragManager.beginTransaction().remove(fragment).commit();
googleMap=null;
}
}
Il est obligatoire de null googlemap . Il n'est pas nécessaire d'utiliser MapView, vous pouvez le faire sans utiliser MapView
Pour que Google API v2 fonctionne (j'utilise également SupportMapFragment), vous devez inclure ces autorisations.
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission Android:name="Android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission Android:name="Android.permission.INTERNET"/>
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
<uses-feature Android:glEsVersion="0x00020000" Android:required="true"/>
J'espère que cela va vous aider les gars.
P.S J'ai utilisé ces autorisations pour ajouter une carte simple dans mon application. Il existe certaines autres autorisations que ce lien suggère également.
Lorsque vous dites que votre code fonctionne pour la première fois, je pense que lorsque vous appelez à nouveau votre carte, votre objet googlemap
n'est pas null
et vous ne l'avez pas traité correctement. Essayez d'implémenter comme ceci dans votre code.
if (googleMap == null) {
// Your code
} else if(googleMap != null) {
marker = googleMap.addMarker(new MarkerOptions().position(new LatLng(18.520897, 73.772396)).title("DSK Ranwara Road"));
}