webentwicklung-frage-antwort-db.com.de

MapFragment in Fragment, Alternativen?

Ich brauche deine Hilfe ... Ich arbeite bis 3 Tage daran. Meine App arbeitet mit Fragmenten . Eines dieser Fragmente muss eine Karte aus der Google Maps V2-API für Android anzeigen.

Momentan verwende ich MapFragment, aber keine Überraschung, ein Fragment in einem Fragment ist keine gute Idee, aber es funktioniert, die Karte wird angezeigt, ich kann es bearbeiten, aber wenn ich das Hauptfragment wechsle und darauf zurückkomme.

Verursacht durch: Java.lang.IllegalArgumentException: Binäre XML-Datei, Zeile # 59: Doppelte ID 0x7f070041, Tag null oder übergeordnete ID 0x7f070040 mit einem anderen Fragment für com.google.Android.gms.mapFragment

bei Android.app.Activity.onCreateView (Activity.Java:4252)

bei Android.view.LayoutInflater.createViewFromTag (LayoutInflater.Java:673)

Dies ist die Ursache, wenn ich auf ein anderes Fragment gehe und zu dem zurückkehre, das die Karte enthält ... Ich suche bis 3 Tage, um dies zu beheben, aber keine großartigen Ergebnisse.

Um für Sie fortzufahren, habe ich eine Activity, die ein Fragment aufruft, das ein MapFragment in der Layout-Datei enthält. Wenn Sie mehr benötigen, fragen Sie einfach :)

Vielen Dank

Bearbeiten: Hier ist der Code zum Ändern des Fragments in der Hauptaktivität

private void swtichFragment(Fragment fragment, Bundle bundle)
{
fragment.setBundle(this, bundle);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.rightFragmentPlaceHolder, fragment);
fragmentTransaction.commit();
mRightFragment = fragment;
}
24
Kyu_

Verwenden Sie MapView anstelle von MapFragment im Layout Ihres Fragments. Denken Sie daran, die Lebenszyklusmethoden von MapView aufzurufen:

  • onCreate (Bundle)
  • auf Wiederaufnahme()
  • onPause ()
  • onDestroy ()
  • onSaveInstanceState (Bundle)
  • onLowMemory ()

wie beschrieben hier .

Übrigens Sie sollten MapFragment nicht verwenden, sondern nur SupportMapFragment und Support Library .

Bearbeiten:

Wenn Sie zur Unterstützungsbibliothek wechseln, können Sie Code aus Kommentar 1 hier verwenden: http://code.google.com/p/gmaps-api-issues/issues/detail?id=5064#c1

26
MaciejGórski

Verwenden Sie SupportMapFragment, um diesen Fehler zu beheben:

Im Fragmentlayout

<fragment
Android:id="@+id/googleMap"
Android:name="com.google.Android.gms.maps.SupportMapFragment"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />

In deinem Fragment onCreateView

SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.googleMap);

        if (mapFragment != null) {
            mapFragment.getMapAsync(this);
        }

Da sich Ihr Layout im Fragment's-Layout befindet, ist SupportMapFragment das untergeordnete Layout Ihres Fragments. Verwenden Sie daher getChildFragmentManager(), was Fragment's FragmentManager ist.

23
Adnan

Wie hier beschrieben

So zeigen Sie MapFragment im Fragment (NestedFragment) an: An diesem Punkt glaube ich, dass Sie dies getan haben

  1. notwendige Berechtigung für Manifest hinzugefügt
  2. google play service als lib projekt hinzugefügt
  3. api-Schlüssel in der Manifestdatei . 4.

wo.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:name="com.google.Android.gms.maps.SupportMapFragment"
           Android:id="@+id/mapwhere" />


          <TextView
           Android:layout_width="match_parent"
           Android:layout_height="wrap_content"/>

        </LinearLayout>

klasse:

 public class WhereFragment extends SupportMapFragment {

    @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
     {
      super.onCreateView(inflater, container, savedInstanceState);
      View root = inflater.inflate(R.layout.where, null, false); 
      initilizeMap();
      return root;
     }

    private void initilizeMap()
     {
      mSupportMapFragment = (SupportMapFragment) getFragmentManager().findFragmentById(R.id.mapwhere);
      if (mSupportMapFragment == null) {
       FragmentManager fragmentManager = getFragmentManager();
       FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
       mSupportMapFragment = SupportMapFragment.newInstance();
       fragmentTransaction.replace(R.id.mapwhere, mSupportMapFragment).commit();
         }
      if (mSupportMapFragment != null)
      {
       googleMap = mSupportMapFragment.getMap();
       if (googleMap != null)
        googleMap.setOnMapClickListener(new OnMapClickListener()
        {
         @Override
         public void onMapClick(LatLng point)
         {
          //TODO: your onclick stuffs
         }
        });
      }
     }
    }

Dokumentation:

Verschachtelte Fragmente Sie können jetzt Fragmente in Fragmente einbetten. Das ist nützlich für eine Vielzahl von Situationen, in denen Sie dynamisch platzieren möchten und wiederverwendbare UI-Komponenten in eine UI-Komponente, die selbst dynamisch ist und wiederverwendbar. Wenn Sie zum Beispiel mit ViewPager Fragmente erstellen, __. wischen Sie nach links und rechts und verbrauchen einen Großteil des Bildschirms, Sie können jetzt Fragmente in jede Fragmentseite einfügen.

Um ein Fragment zu verschachteln, rufen Sie einfach getChildFragmentManager () für .__ auf. Fragment, in dem Sie ein Fragment hinzufügen möchten. Dies gibt ein .__ zurück. FragmentManager, den Sie wie gewohnt mit dem .__ verwenden können. Aktivität auf oberster Ebene zum Erstellen von Fragmenttransaktionen. Zum Beispiel, Hier ist ein Code, der ein Fragment aus einem vorhandenen Fragment hinzufügt Klasse:

Fragment videoFragment = new VideoPlayerFragment (); FragmentTransaction-Transaktion = getChildFragmentManager (). beginTransaction (); transaction.add (R.id.video_fragment, videoFragment) .commit (); Von In einem verschachtelten Fragment können Sie einen Verweis auf das übergeordnete Element erhalten Fragment durch Aufruf von getParentFragment ().

Die Android Support Library unterstützt jetzt auch verschachtelte Fragmente, so dass Sie kann verschachtelte Fragmentdesigns unter Android 1.6 und höher implementieren.

Hinweis: Sie können ein Layout nicht in ein Fragment aufpumpen, wenn dieses Layout enthält a. Verschachtelte Fragmente werden nur unterstützt, wenn sie hinzugefügt werden dynamisch zu einem Fragment.

source: http://developer.Android.com/about/versions/Android-4.2.html#NestedFragments

Dies wird auch korrigiert für:

 11-06 11:36:01.509: E/AndroidRuntime(6309): FATAL EXCEPTION: main
    11-06 11:36:01.509: E/AndroidRuntime(6309): Android.view.InflateException: Binary XML file line #9: Error inflating class fragment
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.view.LayoutInflater.createViewFromTag(LayoutInflater.Java:710)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.view.LayoutInflater.rInflate(LayoutInflater.Java:752)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.view.LayoutInflater.rInflate(LayoutInflater.Java:760)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.view.LayoutInflater.rInflate(LayoutInflater.Java:760)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.view.LayoutInflater.rInflate(LayoutInflater.Java:760)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.view.LayoutInflater.rInflate(LayoutInflater.Java:760)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.view.LayoutInflater.inflate(LayoutInflater.Java:495)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.view.LayoutInflater.inflate(LayoutInflater.Java:397)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at com.abc.Android.ui.WhereFragment.onCreateView(WhereFragment.Java:60)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.support.v4.app.Fragment.performCreateView(Fragment.Java:1500)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:927)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1104)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at Android.support.v4.app.BackStackRecord.run(BackStackRecord.Java:682)
    11-06 11:36:01.509: E/AndroidRuntime(6309):  at a ...
11
ToolFan

In deiner Klasse

      SupportMapFragment mSupportMapFragment;
      private GoogleMap googleMap;
      int ZOOM_LEVEL=15;

      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
       View mTrackView = inflater
            .inflate(R.layout.mylayout, container, false);
        mSupportMapFragment = SupportMapFragment.newInstance();
        FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
        fragmentTransaction.add(R.id.mapwhere, mSupportMapFragment);
        fragmentTransaction.commit();

        return mTrackView;
    }

      @Override
      public void onStart() {
        // TODO Auto-generated method stub
          super.onStart();

        if(mSupportMapFragment!=null){

            googleMap = mSupportMapFragment.getMap();
            if(googleMap!=null){
            googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
            googleMap.getUiSettings().setMyLocationButtonEnabled(false);
            googleMap.setMyLocationEnabled(false);


            CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(
                    new LatLng(12.12122,
                        17.22323), 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>
5
Ravv

In Ihrer Layout-Datei

<fragment
                Android:id="@+id/map"
                Android:name="com.google.Android.gms.maps.SupportMapFragment"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"/>

Verweisen Sie in Ihrem FragmentonCreate() auf das Kartenfragment in Ihrem Fragmentlayoutdatei mit childFragmentManager

// Obtain the SupportMapFragment and get notified when the map is ready to be used.
        val mapFragment: SupportMapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
        // Set callback on the fragment
        mapFragment.getMapAsync(this)
0
Anga Koko

Nach vielen Fehlern habe ich es endlich gemacht, hier ist meine MapView-Fragment-Klasse: -

import Android.content.Context;
import Android.location.Location;
import Android.location.LocationListener;
import Android.location.LocationManager;
import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.util.Log;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.Toast;

import com.google.Android.gms.maps.CameraUpdateFactory;
import com.google.Android.gms.maps.GoogleMap;
import com.google.Android.gms.maps.GoogleMap.OnMapClickListener;
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.MarkerOptions;
import com.serveroverload.yago.R;

/**
 * @author 663918
 *
 */
public class HomeFragment extends Fragment implements LocationListener {
    // Class to do operations on the Map
    GoogleMap googleMap;
    private LocationManager locationManager;

    public static Fragment newInstance() {
        return new HomeFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.home_fragment, container, false);
        Bundle bdl = getArguments();

        // setuping locatiomanager to perfrom location related operations
        locationManager = (LocationManager) getActivity().getSystemService(
                Context.LOCATION_SERVICE);

        // Requesting locationmanager for location updates
        locationManager.requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER, 1, 1, this);

        // To get map from MapFragment from layout
        googleMap = ((MapFragment) getActivity().getFragmentManager()
                .findFragmentById(R.id.map)).getMap();

        // To change the map type to Satellite
        // googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);

        // To show our current location in the map with dot
        // googleMap.setMyLocationEnabled(true);

        // To listen action whenever we click on the map
        googleMap.setOnMapClickListener(new OnMapClickListener() {

            @Override
            public void onMapClick(LatLng latLng) {
                /*
                 * LatLng:Class will give us selected position lattigude and
                 * longitude values
                 */
                Toast.makeText(getActivity(), latLng.toString(),
                        Toast.LENGTH_LONG).show();
            }
        });

        changeMapMode(3);

        // googleMap.setSatellite(true);
        googleMap.setTrafficEnabled(true);
        googleMap.setBuildingsEnabled(true);
        googleMap.setMyLocationEnabled(true);

        return v;
    }

    private void doZoom() {
        if (googleMap != null) {
            googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
                    new LatLng(18.520430, 73.856744), 17));
        }
    }

    private void changeMapMode(int mapMode) {

        if (googleMap != null) {
            switch (mapMode) {
            case 0:
                googleMap.setMapType(GoogleMap.MAP_TYPE_NONE);
                break;

            case 1:
                googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                break;

            case 2:
                googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
                break;

            case 3:
                googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
                break;

            case 4:
                googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                break;

            default:
                break;
            }
        }
    }

    private void createMarker(double latitude, double longitude) {
        // double latitude = 17.385044;
        // double longitude = 78.486671;

        // lets place some 10 random markers
        for (int i = 0; i < 10; i++) {
            // random latitude and logitude
            double[] randomLocation = createRandLocation(latitude, longitude);

            // Adding a marker
            MarkerOptions marker = new MarkerOptions().position(
                    new LatLng(randomLocation[0], randomLocation[1])).title(
                    "Hello Maps " + i);

            Log.e("Random", "> " + randomLocation[0] + ", " + randomLocation[1]);

            // changing marker color
            if (i == 0)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_Azure));
            if (i == 1)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
            if (i == 2)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_CYAN));
            if (i == 3)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
            if (i == 4)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_Magenta));
            if (i == 5)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_ORANGE));
            if (i == 6)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_RED));
            if (i == 7)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
            if (i == 8)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_Violet));
            if (i == 9)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_YELLOW));

            googleMap.addMarker(marker);

            // Move the camera to last position with a zoom level
            if (i == 9) {
                CameraPosition cameraPosition = new CameraPosition.Builder()
                        .target(new LatLng(randomLocation[0], randomLocation[1]))
                        .zoom(15).build();

                googleMap.animateCamera(CameraUpdateFactory
                        .newCameraPosition(cameraPosition));
            }
        }

    }

    /*
     * creating random postion around a location for testing purpose only
     */
    private double[] createRandLocation(double latitude, double longitude) {

        return new double[] { latitude + ((Math.random() - 0.5) / 500),
                longitude + ((Math.random() - 0.5) / 500),
                150 + ((Math.random() - 0.5) * 10) };
    }

    @Override
    public void onLocationChanged(Location location) {

        if (null != googleMap) {
            // To get lattitude value from location object
            double latti = location.getLatitude();
            // To get longitude value from location object
            double longi = location.getLongitude();

            // To hold lattitude and longitude values
            LatLng position = new LatLng(latti, longi);

            createMarker(latti, longi);

            // Creating object to pass our current location to the map
            MarkerOptions markerOptions = new MarkerOptions();
            // To store current location in the markeroptions object
            markerOptions.position(position);

            // Zooming to our current location with zoom level 17.0f
            googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(position,
                    17f));

            // adding markeroptions class object to the map to show our current
            // location in the map with help of default marker
            googleMap.addMarker(markerOptions);
        }

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onProviderEnabled(String provider) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onProviderDisabled(String provider) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onDestroyView() {
        // TODO Auto-generated method stub
        super.onDestroyView();

        locationManager.removeUpdates(this);

        Android.app.Fragment fragment = getActivity().getFragmentManager()
                .findFragmentById(R.id.map);
        if (null != fragment) {
            Android.app.FragmentTransaction ft = getActivity()
                    .getFragmentManager().beginTransaction();
            ft.remove(fragment);
            ft.commit();
        }
    }


}

Meine XML-Datei sieht folgendermaßen aus: -

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/map"
    Android:name="com.google.Android.gms.maps.MapFragment"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" />

Und das Ergebnis sieht so aus: -

 enter image description here

Das Wichtigste, was Sie beachten sollten, ist, dass DO Not Mix nicht funktioniert. 

Wie Sie sehen, habe ich app.Fragment zum Anhängen und Entfernen meines MapView-Fragments verwendet 

Ich hoffe es wird jemandem helfen 

0
Hitesh Sahu