web-dev-qa-db-fra.com

MapFragment in Fragment, alternatives?

J'ai besoin de votre aide ... Je travaille dessus jusqu'à 3 jours. Mon application utilise des fragments . L'un de ces fragments doit afficher une carte de l'API Google Maps V2 pour Android.

Actuellement, j'utilise un MapFragment, mais sans surprise, un fragment dans un fragment n'est pas une bonne idée, mais cela fonctionne, la carte s'affiche, je peux l'éditer mais quand je change de fragment principal et que je reviens dessus.

Causé par: Java.lang.IllegalArgumentException: ligne de fichier XML binaire # 59: ID dupliqué 0x7f070041, balise null ou id parent 0x7f070040 avec un autre fragment pour com.google.Android.gms.maps.MapFragment

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

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

C’est la cause lorsque je vais sur un autre fragment et que je reviens à celui qui contient la carte . Je cherche jusqu’à 3 jours pour résoudre ce problème mais aucun bon résultat.

Pour résumer pour vous, j'ai une activité qui appelle un fragment qui contient un MapFragment dans le fichier de mise en page . Si vous avez besoin de plus d'informations, demandez simplement :)

Merci

Edit: Voici le code pour changer le fragment dans l'activité principale

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_

Utilisez SupportMapFragment pour surmonter cette erreur:

En fragmentation

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

Dans votre fragment onCreateView

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

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

Puisque votre disposition est dans la disposition Fragment's, la valeur SupportMapFragment est donc la disposition enfant de votre fragment. Utilisez donc getChildFragmentManager() qui est Fragment's FragmentManager

23
Adnan

Comme décrit ici

Pour afficher MapFragment à l'intérieur du fragment (NestedFragment): À ce stade, je pense que vous avez

  1. ajout de l'autorisation nécessaire sur le manifeste
  2. ajout du service Google Play en tant que projet lib
  3. clé api dans le fichier manifeste . 4.

où.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>

classe:

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

Documentation:

Fragments imbriqués Vous pouvez maintenant incorporer des fragments dans des fragments. C'est utile pour une variété de situations dans lesquelles vous voulez placer dynamique et des composants d'interface utilisateur réutilisables dans un composant d'interface utilisateur qui est lui-même dynamique et réutilisable. Par exemple, si vous utilisez ViewPager pour créer des fragments qui glissent à gauche et à droite et consomment la majorité de l’écran, vous pouvez maintenant insérer des fragments dans chaque page de fragment.

Pour imbriquer un fragment, appelez simplement getChildFragmentManager () sur le fichier Fragment dans lequel vous voulez ajouter un fragment. Ceci retourne un FragmentManager que vous pouvez utiliser comme vous le faites normalement à partir du fichier activité de niveau supérieur pour créer des transactions de fragment. Par exemple, Voici du code qui ajoute un fragment à partir d’un fragment existant classe:

Fragment videoFragment = new VideoPlayerFragment (); FragmentTransaction transaction = getChildFragmentManager (). beginTransaction (); transaction.add (R.id.video_fragment, videoFragment) .commit (); De dans un fragment imbriqué, vous pouvez obtenir une référence au parent fragment en appelant getParentFragment ().

La bibliothèque de support Android prend également en charge les fragments imbriqués, de sorte que vous peut implémenter des conceptions de fragments imbriqués sur Android 1.6 et supérieur.

Remarque: Vous ne pouvez pas gonfler une mise en page dans un fragment lorsque cette mise en page comprend a. Les fragments imbriqués ne sont pris en charge que lorsqu'ils sont ajoutés à un fragment dynamiquement.

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

Cela corrigera aussi pour:

 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

Dans votre classe

      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

Après beaucoup d’erreurs, j’ai finalement fait, voici ma classe de fragments MapView: -

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


}

Mon fichier XML ressemble à ceci: -

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

Et le résultat ressemble à ceci: -

 enter image description here

La chose la plus importante à noter est que ne pas mélanger app.Fragment avec v4.Fragments sinon l'application va planter. 

Comme vous pouvez le constater, j'ai utilisé app.Fragment pour attacher et supprimer mon fragment MapView. 

J'espère que ça va aider quelqu'un 

0
Hitesh Sahu