MapFragment in Fragment, альтернативы?

Мне нужна ваша помощь … Я работаю над ней до 3 дней. Мое приложение работает с фрагментами. Один из этих фрагментов должен отображать карту с Google Maps V2 api для Android.

В настоящее время я использую MapFragment, но не удивительно, что фрагмент в фрагменте не очень хорошая идея, но он работает, карта отображается, я могу ее редактировать, но когда я переключаю основной фрагмент и возвращаю его.

Вызывается: java.lang.IllegalArgumentException: двоичная строка XML-файла # 59: дубликат id 0x7f070041, тег null или родительский идентификатор 0x7f070040 с другим фрагментом для com.google.android.gms.maps.MapFragment

В android.app.Activity.onCreateView (Activity.java:4252)

На android.view.LayoutInflater.createViewFromTag (LayoutInflater.java:673)

Это причина, когда я иду на другой фрагмент и возвращаюсь к тому, который содержит карту. Я ищу до 3 дней, чтобы исправить это, но никаких отличных результатов.

Чтобы возобновить работу, у меня есть Activity, который вызывает фрагмент, содержащий MapFragment в файле макета. Если вам нужно больше, просто спросите 🙂

благодаря

Изменить: Вот код для изменения Фрагмента в основной деятельности

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

Solutions Collecting From Web of "MapFragment in Fragment, альтернативы?"

Используйте MapView вместо MapFragment в макете фрагмента. Не забудьте вызвать методы жизненного цикла MapView:

  • OnCreate (Bundle)
  • onResume ()
  • OnPause ()
  • OnDestroy ()
  • onSaveInstanceState (Bundle)
  • onLowMemory ()

Как описано здесь .

Btw. Вы не должны использовать MapFragment, только SupportMapFragment и библиотеку поддержки .

Редактировать:

Если вы переключитесь на поддержку библиотеки, вы можете использовать код из комментария # 1 здесь: http://code.google.com/p/gmaps-api-issues/issues/detail?id=5064#c1

Используйте UseMapFragment для преодоления этой ошибки:

В макете фрагмента

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

В вашем фрагменте onCreateView

 SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.googleMap); if (mapFragment != null) { mapFragment.getMapAsync(this); } 

Поскольку ваш макет находится в макете Fragment's , поэтому SupportMapFragment является дочерним макетом вашего фрагмента. Следовательно, используйте getChildFragmentManager() который является Fragment's FragmentManager

Как описано здесь

Чтобы отобразить MapFragment внутри фрагмента (NestedFragment): на данный момент я считаю, что у вас есть

  1. Добавлено необходимое разрешение на манифест
  2. Добавлена ​​служба google play как проект lib
  3. Api ключ в файле манифеста. 4.

where.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> 

класс:

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

Документация :

Вложенные фрагменты Теперь вы можете вставлять фрагменты внутри фрагментов. Это полезно для различных ситуаций, в которых вы хотите разместить динамические и повторно используемые компоненты пользовательского интерфейса в компонент пользовательского интерфейса, который сам по себе является динамическим и может использоваться повторно. Например, если вы используете ViewPager для создания фрагментов, которые прокручиваются влево и вправо и потребляют большую часть пространства экрана, теперь вы можете вставлять фрагменты на каждую страницу фрагмента.

Чтобы вставить фрагмент, просто вызовите getChildFragmentManager () на фрагменте, в который вы хотите добавить фрагмент. Это возвращает FragmentManager, который вы можете использовать, как обычно, из операции верхнего уровня для создания транзакций фрагментов. Например, вот какой-то код, который добавляет фрагмент из существующего класса фрагментов:

Фрагмент видеофрагмент = новый VideoPlayerFragment (); FragmentTransaction transaction = getChildFragmentManager (). BeginTransaction (); Transaction.add (R.id.video_fragment, videoFragment) .commit (); Изнутри вложенного фрагмента вы можете получить ссылку на родительский фрагмент, вызвав getParentFragment ().

Библиотека поддержки Android теперь также поддерживает вложенные фрагменты, поэтому вы можете реализовать вложенные фрагменты на Android 1.6 и выше.

Примечание. Вы не можете раздувать макет во фрагмент, если в этом макете есть a. Вложенные фрагменты поддерживаются только при динамическом добавлении к фрагменту.

Источник: http://developer.android.com/about/versions/android-4.2.html#NestedFragments

Это также будет исправлено для:

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

В вашем классе

  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> 

После многих ошибок я наконец сделал это, вот мой класс фрагментов 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(); } } } 

Мой Xml-файл выглядит так:

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

Результат выглядит так:

Введите описание изображения здесь

Самое главное отметить, что DO Not Mix app.Fragment с v4.Fragments else приложение сильно сработает.

Как вы можете видеть, я использовал app.Fragment для прикрепления и удаления фрагмента MapView

Надеюсь, это поможет кому-то