Android MapView avec des fragments ne peut pas être ajouté deux fois?
-
26-10-2019 - |
Question
J'utilise la classe de compatibilité Android avec le hack pour l'utilisation mapviews dans un fragment trouvé ici: https: // github.com/petedoyle/android-support-v4-googlemaps
Malheureusement, ce que je trouve est que si le mapfragment se retire de l'activité, puis readded, je reçois le « Vous ne sont autorisés à avoir un seul MapView dans une MapActivity » erreur « .
Je comprends le principe de l'erreur, et a essayé de détruire la MapView dans les fragments OnPause méthode. Malheureusement, je ne peux pas sembler détruire le MapView complètement, puisque je reçois encore. Mon code ressemble à ceci:
private RelativeLayout layout;
private MapView mp;
public void onResume(){
super.onResume();
Bundle args = getArguments();
if(mp == null)
{
mp = new MapView(getActivity(), this.getString(R.string.map_api_key));
mp.setClickable(true);
}
String request = args.getString("requestId");
layout = (RelativeLayout) getView().findViewById(R.id.mapholder);
layout.addView(mp);
//TextView txt = (TextView) getView().findViewById(R.id.arguments);
//txt.setText(request);
}
public void onPause(){
super.onPause();
layout.removeView(mp);
mp = null;
}
Quelqu'un at-il des idées sur ce que la référence je néglige de détruire ici?
La solution
Je rencontrais la même question. Voici comment je l'ai résolu:
-
Comme il devrait y avoir qu'une seule instance du Mapview dans l'activité, je lsinitialisez dans la méthode onCreate dans l'activité:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // initialize MapView programmatically to be used in Fragment : this.mActivityMapView = new MapView(MainActivity.this, getString(R.string.debug_mapview_apikey)); setContentView(R.layout.activity_main); }
-
Puis-je le récupérer dans la méthode du fragment:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { this.mMapView = ((MainActivity) getActivity()).getMapView(); return this.mMapView; }
-
Et je détruis dans la méthode fragment de OnDestroy:
public void onDestroy() { NoSaveStateFrameLayout parentView = (NoSaveStateFrameLayout) this.mMapView.getParent(); parentView.removeView(this.mMapView); super.onDestroy(); }
Autres conseils
Vous pouvez supprimer l'affichage de la carte dans la méthode OnPause (au lieu de la méthode OnDestroy)
public void onPause() {
NoSaveStateFrameLayout parentView = (NoSaveStateFrameLayout) this.mMapView.getParent();
parentView.removeView(this.mMapView);
super.onPause();}
De cette façon, vous pouvez ajouter un MapFragment au backstack. (FragmentTransaction.addToBackStack empêche un fragment de la destruction)
Max et les réponses de Bleeker fonctionnent bien, mais vous devez prendre des précautions particulières si vous voulez soutenir les changements d'orientation de l'écran, comme je le fais. Il se trouve lorsque vous faites pivoter l'écran, il appellera à nouveau OnCreateView sans appeler la méthode OnPause, ajoutant ainsi la MapView deux fois. Pour résoudre ce problème, à l'intérieur OnCreateView je l'ai fait ce qui suit:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
this.mMapView = ((MyGameActivity) getActivity()).getMapView();
if (this.mMapView.getParent()!=null)
{
NoSaveStateFrameLayout parentView = (NoSaveStateFrameLayout) this.mMapView.getParent();
parentView.removeView(this.mMapView);
}
return this.mMapView;
}
J'ai essayé de trouver une solution simple à ce problème.
Sur la classe poignées mes Voir détails (une extension RelativeLayout), je déclarai un private static MapView myMapView;
.
Ensuite, la méthode override onFinishInflate (), comme l'extrait de code suivant:
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//myMapView = (MapView) findViewById(R.id.map_view);
if (myMapView==null)
myMapView = new MapView(context, getResources().getString(R.string.map_view_api_key));
if (myMapView.getParent() != null)
((ViewGroup)myMapView.getParent()).removeView(myMapView);
myMapView.setClickable(true);
myMapView.setEnabled(true);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
myMapView.setLayoutParams(lp);
this.addView(myMapView);
}
De cette façon, vous avez une seule instance de MapView.
Voici comment je résolu cette question en cas de Fragment.
Créer la mise en page
<LinearLayout
android:id="@+id/ll_mapcontainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
Vous pouvez placer cette mise en page comme partout dans votre fichier XML où vous souhaitez afficher la carte
Maintenant, le code sera comme cela.
package com.yuviii.sample;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.yuviii.sample.R;
/**
* Created by yubraj Poudel on 12/20/15.
*/
public class ContactUsFragment extends Fragment {
static final LatLng PRACTICAL_ANSWER_LOCATION = new LatLng(53.558, 9.927);
private SupportMapFragment fragment;
private GoogleMap map;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.page_contactus, container, false);
return v;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initializeMap();
}
private void initializeMap() {
FragmentManager fm = getChildFragmentManager();
fragment = (SupportMapFragment) fm.findFragmentById(R.id.ll_mapcontainer);
if (fragment == null) {
fragment = SupportMapFragment.newInstance();
fm.beginTransaction().replace(R.id.ll_mapcontainer, fragment).commit();
}
}
@Override
public void onResume() {
super.onResume();
if (map == null) {
map = fragment.getMap();
map.addMarker(new MarkerOptions().position(PRACTICAL_ANSWER_LOCATION));
}
}
}
Cela fonctionne pour moi. Profitez !!!