Changer de fragment avec fragment de carte laisse un écran noir

J’ai ajouté un fragment de carte en plein écran à l’un de mes trois fragments avec tabs. Tout fonctionne très bien, à part un problème que je rencontre avec la commutation entre les tabs.

Chaque fois que je passe du fragment contenant la carte à l’un des autres fragments, l’écran noir s’affiche pendant 0,2 seconde. Cela semble être un problème similaire aux problèmes de défilement dans une activité avec un fragment de carte.

J’ai essayé d’append une vue transparente en haut de la carte, comme d’autres l’ont suggéré, mais cela n’a pas aidé.

C’est mon xml:

   

Et voici mon code:

 public class ParkMapFragment extends Fragment { public ParkMapFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_map, container, false); } @Override public void onStart(){ super.onStart(); getActivity().setTitle("Map"); } @Override public void onDestroyView() { super.onDestroyView(); SupportMapFragment mapFragment = (SupportMapFragment) getFragmentManager().findFragmentById(R.id.fullParkMap); if (mapFragment != null) { getFragmentManager().beginTransaction().remove(mapFragment).commit(); } } } 

Quelqu’un a des suggestions?

Vérifiez si la vue est nulle et sinon, supprimez-la de la vue parent. De cette façon, vous ne verrez pas l’écran noir.

Essayez le code ci-dessous.

Fragment:

 import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.GoogleMap.OnMapClickListener; import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener; import com.google.android.gms.maps.model.BitmapDescriptorFactory; 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 android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.view.InflateException; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class ExhibhitionMap2 extends Fragment implements OnMapClickListener,OnMarkerClickListener{ View v; private GoogleMap mMap; FragmentManager fragmentManager; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // android = inflater.inflate(R.layout.activity_exhibhition_map, container, false); if (v != null) { ViewGroup parent = (ViewGroup) v.getParent(); if (parent != null) parent.removeView(v); } try { v = inflater.inflate(R.layout.activity_exhibhition_map, container, false); } catch (InflateException e) { /* map is already there, just return view as it is */ } setUpMapIfNeeded(); return v; } /***** Sets up the map if it is possible to do so *****/ public void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the map. if (mMap == null) { mMap = ((SupportMapFragment) this.getChildFragmentManager().findFragmentById(R.id.map2)).getMap(); // Check if we were successful in obtaining the map. if (mMap != null) { mMap.setOnMapClickListener(this); mMap.setOnMarkerClickListener((OnMarkerClickListener) this); MarkerOptions marker = new MarkerOptions().position(new LatLng(36.011513,-115.174853)) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)) .title("P-1"); MarkerOptions marker01 = new MarkerOptions().position(new LatLng(36.111513,-115.204853)) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)) .title("P-2"); MarkerOptions marker02 = new MarkerOptions().position(new LatLng(36.051513,-115.154853)) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)) .title("P-3"); MarkerOptions marker03 = new MarkerOptions().position(new LatLng(36.057513,-115.344853)) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)) .title("P-4"); MarkerOptions marker1 = new MarkerOptions().position(new LatLng(36.081513,-115.224853)) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN)) .title("F-1"); MarkerOptions marker2 = new MarkerOptions().position(new LatLng(36.051513,-115.334853)) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN)) .title("F-2"); MarkerOptions marker3 = new MarkerOptions().position(new LatLng(36.101513,-115.124853)) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN)) .title("F-1"); MarkerOptions marker4 = new MarkerOptions().position(new LatLng(36.031513,-115.154853)) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN)) .title("F-2"); MarkerOptions marker5 = new MarkerOptions().position(new LatLng(36.081513,-115.194853)) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN)) .title("F-2"); mMap.addMarker(marker); mMap.addMarker(marker01); mMap.addMarker(marker02); mMap.addMarker(marker03); mMap.addMarker(marker1); mMap.addMarker(marker2); mMap.addMarker(marker3); mMap.addMarker(marker4); mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(36.051513,-115.174853), 10.0f)); } } } @Override public boolean onMarkerClick(Marker marker) { /*Toast.makeText(getActivity(), "" + marker.getTitle(), Toast.LENGTH_LONG) .show();*/ marker.showInfoWindow(); return false; } @Override public void onMapClick(LatLng arg0) { // TODO Auto-generated method stub } public void onDestroy() { super.onDestroy(); } } 

XML:

                             
  @Override public void onDestroyView() { super.onDestroyView(); SupportMapFragment mapFragment = (SupportMapFragment) getFragmentManager().findFragmentById(R.id.fullParkMap); if (mapFragment != null) { getFragmentManager().beginTransaction().remove(mapFragment).commit(); } } 

ici, vous retirez le fragment sans le remplacer. J’utiliserais plutôt .replace avec un nouveau fragment.

Quelque chose comme ça:

 getFragmentManager().beginTransaction().replace(R.id.your_placeholder, new CustomFragment(), "cstmFragID").commit(); 

Comme vous remplacez toujours fragment, la carte est toujours créée, puis la solution de contournement consiste à ne charger votre fragment de carte qu’une seule fois, le rest du temps, il vous suffit d’afficher / masquer votre fragment (comme si vous monsortingez des fragments à tabs).

Je vous recommanderais d’utiliser MapView au lieu de SupportFragment pour éviter les fragments nesteds. Pour plus de détails, répondez au post suivant

Devrais-je utiliser MapView ou MapFragment

Maintenant, votre ParkFragment be ressembler

MapFragment.java

 public class MapFragment extends Fragment implements OnMapReadyCallback { private MapView mMapView; private GoogleMap mGoogleMap; public MapFragment() { // Required empty public constructor } public static MapFragment newInstance() { MapFragment fragment = new MapFragment(); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_map, container, false); mMapView = (MapView) rootView.findViewById(R.id.map); mMapView.onCreate(savedInstanceState); mMapView.getMapAsync(this); return rootView; } @Override public void onResume() { super.onResume(); mMapView.onResume(); } @Override public void onPause() { mMapView.onPause(); super.onPause(); } @Override public void onDestroy() { mMapView.onDestroy(); super.onDestroy(); } @Override public void onMapReady(GoogleMap googleMap) { googleMap.getUiSettings().setZoomControlsEnabled(true); } } 

fragment_map.xml

    

Le problème est peut-être parce qu’il est en Fragment recréer Fragment qui cause l’écran noir Si vous utilisez ViewPager vous pouvez utiliser

 // Note that you must set adapter before this line otherwise it can cause NullPointerException // Or add null check on getAdapter if required mViewPager.setOffscreenPageLimit(mViewPager.getAdapter().getCount()); 

Cela forcera ViewPager ne pas créer de fragments une seconde fois. Bien sûr, cela prend plus de mémoire, mais je pense que cela est plus efficace lorsque moins d’tabs sont utilisés, c’est pourquoi je le fais normalement pour éviter la reproduction de fragments.

Deuxièmement, je suggérerais de supprimer ces lignes de onDestroy :

 SupportMapFragment mapFragment = (SupportMapFragment) getFragmentManager().findFragmentById(R.id.fullParkMap); if (mapFragment != null) { getFragmentManager().beginTransaction().remove(mapFragment).commit(); } 

Et surmontez ce problème en mettant à jour onCreateView comme ceci:

 private View mView; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (mView == null) { mView = inflater.inflate(R.layout.fragment_map, container, false); } return mView; } 

Cela ne gonflera pas la présentation à chaque fois, vous ne ferez donc pas face à l’ ID de duplication, à la balise null ou à l’ID parent avec un autre fragment pour le problème com.google.android.gms.maps.MapFragment .
Mais assurez-vous de passer false dans attachToRoot (dernier argument de inflater.inflate), sinon vous pourriez obtenir des exceptions telles que L’enfant spécifié a déjà un parent

Dernière chose, lorsque vous utilisez MapFragment dans Fragment , ou en d’autres termes, lorsque vous utilisez des fragments nesteds, je vous recommande d’utiliser getChildFragmentManager () plutôt que getFragmentManager () pour éviter les problèmes inattendus.
Parce que comme le dit la documentation :
getFragmentManager : renvoie le FragmentManager pour interagir avec les fragments associés à l’activité de ce fragment. Notez que ceci sera légèrement non nul légèrement avant getActivity (), à partir du moment où le fragment est placé dans une FragmentTransaction jusqu’à ce qu’il soit validé et lié à son activité. Si ce fragment est un enfant d’un autre fragment, le gestionnaire FragmentManager renvoyé ici sera getChildFragmentManager () du parent.
getChildFragmentManager : Retourne un FragmentManager privé pour le placement et la gestion de fragments à l’intérieur de ce fragment.

Avez-vous essayé de masquer et d’afficher fragment (au lieu de l’enlever / l’append)?

 private FragmentA fragmentA; private FragmentB fragmentB; private FragmentC fragmentC; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState == null) { fragmentA = FragmentA.newInstance("foo"); fragmentB = FragmentB.newInstance("bar"); fragmentC = FragmentC.newInstance("baz"); } } 

Dans votre cas, vous pouvez le changer en ParkMapFragment etc.

 protected void displayFragmentA() { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); if (fragmentA.isAdded()) { // if the fragment is already in container ft.show(fragmentA); } else { // fragment needs to be added to frame container ft.add(R.id.flContainer, fragmentA, "A"); } // Hide fragment B if (fragmentB.isAdded()) { ft.hide(fragmentB); } // Hide fragment C if (fragmentC.isAdded()) { ft.hide(fragmentC); } // Commit changes ft.commit(); } 

source: https://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragments

Essayez ceci dans createView:

 if (v != null) { ViewGroup parent = (ViewGroup) v.getParent(); if (parent != null) parent.removeView(v); } 

C’est un problème connu . Pour le moment, vous pouvez utiliser des contournements en plaçant une autre vue au-dessus de la carte utilisant une couleur d’arrière-plan identique à celle de son conteneur. Cela rend la carte en douceur entrer une fois qu’il est prêt.

 SupportMapFragment mapFragment = SupportMapFragment.newInstance(new GoogleMapOptions().zOrderOnTop(true)); 

Vous devriez faire la transition de fragments de cette façon:

 Fragment fragment = new YourFragmentToShow(); getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment, TAG).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE).commit(); 

Avec TRANSIT_FRAGMENT_FADE, le fragment doit simplement apparaître ou disparaître en fondu; c’est-à-dire qu’aucune navigation forte n’y est associée sauf qu’elle apparaît ou disparaît pour une raison quelconque.

Utilisez-le lorsque vous remplacez le fragment par map par un autre fragment. Dans le cas contraire, je recommande l’utilisation courante, sans (.setTransition …):

 Fragment fragment = new YourFragmentToShow(); getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment, TAG).commit();