2011-10-19 7 views
11

Sto usando la classe compatibilità Android con l'hack per utilizzare mapviews in un frammento trovato qui: https://github.com/petedoyle/android-support-v4-googlemapsLa mapview di Android con i frammenti non può essere aggiunta due volte?

Purtroppo, quello che sto trovando è che se il mapfragment viene rimosso dall'attività, e poi riaggiunto, ho la "Si può avere un solo errore di MapView in MapActivity".

Capisco il principio dietro l'errore e ho provato a distruggere il mapview nel metodo onPause dei frammenti. Sfortunatamente non riesco a distruggere il mapview completamente, dal momento che sto ancora ricevendo. Il mio codice è simile a questo:

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

Qualcuno ha qualche idea su quale sia il riferimento che sto trascurando di distruggere qui?

risposta

15

Ho riscontrato lo stesso problema. Ecco come ho risolto:

  • Come dovrebbe essere una sola istanza del MapView nell'attività, ho inizializzare nel metodo onCreate in attività:

    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); 
    } 
    
  • Poi mi riprendo in il frammento onCreateView metodo:

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
        this.mMapView = ((MainActivity) getActivity()).getMapView(); 
        return this.mMapView; 
    } 
    
  • E io distruggerlo nel metodo frammento OnDestroy:

    public void onDestroy() { 
        NoSaveStateFrameLayout parentView = (NoSaveStateFrameLayout) this.mMapView.getParent(); 
        parentView.removeView(this.mMapView); 
        super.onDestroy(); 
    } 
    
6

si potrebbe desiderare di rimuovere la visualizzazione della mappa nel metodo onPause (invece del metodo OnDestroy)

public void onPause() { 
    NoSaveStateFrameLayout parentView = (NoSaveStateFrameLayout) this.mMapView.getParent(); 
    parentView.removeView(this.mMapView); 
    super.onPause();} 

In questo modo, è possibile aggiungere un MapFragment al backstack. (FragmentTransaction.addToBackStack impedisce che un frammento venga distrutto)

6

Le risposte di Max e Bleeker funzionano bene ma è necessario prestare particolare attenzione se si desidera supportare i cambiamenti di orientamento dello schermo, come faccio io. Si scopre quando si ruota lo schermo, chiamerà nuovamente OnCreateView senza chiamare il metodo onPause, aggiungendo due volte mapview. Per risolvere il problema, all'interno OnCreateView ho fatto la seguente:

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

Ho cercato di ottenere una semplice soluzione a questo problema. Nella classe che gestisce i dettagli della vista (un'estensione RelativeLayout), ho dichiarato un private static MapView myMapView;.

Poi, sovrascrivere il metodo onFinishInflate() come il seguente frammento di codice:

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

} 

In questo modo si dispone di una sola istanza di MapView.

0

Ecco come ho risolto questo problema in caso di frammento.

creare lo schema di

<LinearLayout 
     android:id="@+id/ll_mapcontainer" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="vertical" /> 

È possibile inserire questo layout come ovunque nel file XML in cui si desidera visualizzare la mappa

Ora il codice sarà così.

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

Questo funziona per me. Godere !!!