tutorial studio onattach navegar fragments example entre ejemplo activity android android-fragments

onattach - navegar entre fragments android studio



Android-android.view.InflateException: archivo XML binario lĂ­nea#8: error al inflar el fragmento de la clase (12)

Estoy desarrollando una aplicación usando un NavigationDrawer es decir, DrawerLayout y navegando a diferentes Fragments . Cuando llamo a Map_Fragment_Page la aplicación falla, pero no la primera vez. Por primera vez, muestra el Map correctamente, pero luego, cuando Map_Fragment_Page por diferentes fragmentos y vuelvo a Map_Fragment_Page , falla al dar un error android.view.InflateException: Binary XML file line #8: Error inflating class fragment

Probé con tantas soluciones diferentes y también busqué en Google pero aún no obtuve la solución requerida. El problema aún no está solucionado.

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; } }


Cómo solucioné mi problema después de buscar mucho, pongo estas líneas dentro del fragmento Método de Pausa.

@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; } }

Es obligatorio anular googlemap. No es necesario usar MapView, puede hacerlo sin usar MapView


Cambia esto

googleMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();

a

googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();


Como dices la primera vez que tu código está funcionando, creo que cuando vuelvas a llamar a tu mapa, tu objeto googlemap no es null y no lo has manejado correctamente. Intenta implementarlo así en tu código.

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")); }


En tu clase

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>


Entonces, si se bloquea después de abrir el fragmento por segunda vez. Todo lo que necesitas es esto en OnDestroy

@Override public void onDestroy() { super.onDestroy(); getFragmentManager().beginTransaction().remove(mapfragmentnamehere).commit(); }

Haga los cambios que necesita si está utilizando un fragmento de soporte


Mis experiencias hechas con fragmentos añadidos por xml-tag

<fragment>...</fragment>.

Esos fragmentos normalmente están anidados y no se destruyen cuando el fragmento principal se destruye. Una vez que intentas inflarlos de nuevo, obtienes la excepción que básicamente se queja de tener este fragmento ya inflado. Por lo tanto, destruyo mis fragmentos anidados manualmente una vez que el fragmento principal se destruye. Simplemente use el siguiente recorte y ajústelo a sus necesidades. Este código reside en el fragmento principal que tiene el fragmento anidado como xml-tag.

@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(); } }

Con fragmentos creados dinámicamente no hay ningún problema. Dinámicamente significa: No tiene una etiqueta fragment-xml-tag utilizada

¡Espero que esto ayude! Buena programación!


Para que Google API v2 funcione (también estoy usando SupportMapFragment), debe incluir estos permisos

<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"/>

Espero que esto los ayude chicos.

PD. Usé estos permisos para agregar un mapa simple en mi aplicación. Existen otros permisos que este enlace también sugiere.


Puse esto en mi fragmento

@Override public void onPause() { super.onPause(); getChildFragmentManager().beginTransaction() .remove(mMapFragment) .commit(); }

Funciona sin reemplazar a MapView.


Puse esto en mi fragmento cuando tengo 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(); }


Recibí el mismo mensaje de error:

La causa para mí fue simple: volver a crear una vista

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 se puede llamar más de una vez.

Cuando eso sucede, el código anterior crea una nueva vista para el fragmento mientras el anterior todavía está alrededor.

El error aparece con algún adaptador y no con otro; en mi caso, FragmentStatePagerAdapter estaba contento y FragmentPagerAdapter era asesino porque el primero destruía sus fragmentos y el último los reutilizaba.


Verifique si tiene el permiso de manifiesto exacto. No había incluido el permiso debajo en manifiesto, y estaba dando este error.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Por favor incluya algunos de los siguientes permisos en su archivo de manifiesto

<!-- - 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"/>


Yes.. I want Map inside a Fragment.

Deberías usar 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>

Actualizar:

https://developers.google.com/android/reference/com/google/android/gms/maps/MapView#public-constructors

getMap() está en desuso. Use getMapAsync(OnMapReadyCallback) lugar. El método de devolución de llamada le proporciona una instancia de GoogleMap que garantiza que no es nula y está lista para ser utilizada.