【问题标题】:MapFragment in Fragment, alternatives?片段中的MapFragment,替代方案?
【发布时间】:2013-03-04 06:01:30
【问题描述】:

我需要你的帮助...我会努力完成 3 天。我的应用程序正在处理片段。 其中一个片段必须显示来自 Android 版 Google Maps V2 api 的地图。

目前,我正在使用 MapFragment,但毫不奇怪,片段中的片段不是一个好主意,但它可以工作,地图正在显示,我可以编辑它但是当我切换主片段并返回时它。

原因:java.lang.IllegalArgumentException:二进制 XML 文件第 59 行:重复 id 0x7f070041、标签 null 或父 id 0x7f070040 与 com.google.android.gms.maps.MapFragment 的另一个片段

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

在 android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:673)

当我继续处理另一个片段并返回包含地图的片段时,这就是原因。 我正在寻找 3 天来解决这个问题,但没有很好的结果。

为您恢复,我有一个 Activity,它调用一个片段,该片段在布局文件中包含一个 MapFragment。 如果您需要更多,请询问:)

谢谢

编辑: 这是在主Activity中更改Fragment的代码

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

【问题讨论】:

  • 显示你的片段切换代码...
  • 新增片段切换功能:)
  • 您是以静态方式将地图作为参考,还是将其传递给其他可能仍然存在的类?

标签: android fragment google-maps-android-api-2 mapfragment


【解决方案1】:

使用 SupportMapFragment 来克服这个错误:

在片段布局中

<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

【讨论】:

  • 这是最好的方法。这会更改 Google 示例中的一行代码并使其正常工作。干得好阿德南
【解决方案2】:

在 Fragment 的布局中使用 MapView 而不是 MapFragment。记得调用 MapView 的生命周期方法:

  • onCreate(Bundle)
  • onResume()
  • onPause()
  • onDestroy()
  • onSaveInstanceState(Bundle)
  • onLowMemory()

here 所述。

顺便说一句。你不应该使用 MapFragment,只有 SupportMapFragment 和 support library

编辑:

如果您切换到支持库,您可以在此处使用注释 #1 中的代码: http://code.google.com/p/gmaps-api-issues/issues/detail?id=5064#c1

【讨论】:

  • 出于兴趣,我们为什么不使用 MapFragment?
  • @JamesMundy 一个原因可能是支持库包含Fragments,在 Android 4.x 的早期版本中,这些库的错误可能比原生库少,所以即使您只针对 4.x 版本。 x,您在 APK 中以几百 kB 的价格使用更少的错误代码。另一件事,如果客户最终决定您仍然需要支持 2.3.3,那么您的工作量就会减少。
  • 谢谢,非常感谢!有道理。
【解决方案3】:

As described here

在片段内显示 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
         }
        });
      }
     }
    }

文档

嵌套片段您现在可以在片段中嵌入片段。这是 适用于您想要放置动态的各种情况 并将可重用的 UI 组件转换为本身是动态的 UI 组件 并可重复使用。例如,如果您使用 ViewPager 创建片段 左右滑动并占用大部分屏幕空间, 您现在可以在每个片段页面中插入片段。

要嵌套一个片段,只需调用 getChildFragmentManager() 要在其中添加片段的片段。这会返回一个 您可以像往常一样使用的 FragmentManager 创建片段事务的顶级活动。例如, 这是一些从现有片段中添加片段的代码 类:

片段 videoFragment = new VideoPlayerFragment(); FragmentTransaction 交易 = getChildFragmentManager().beginTransaction(); transaction.add(R.id.video_fragment, videoFragment).commit();从 在嵌套片段中,您可以获得对父级的引用 通过调用 getParentFragment() 进行片段。

Android 支持库现在也支持嵌套片段,因此您 可以在 Android 1.6 及更高版本上实现嵌套片段设计。

注意:当该布局时,您不能将布局膨胀为片段 包括一个 .仅在添加时才支持嵌套片段 动态到一个片段。

来源: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 ...

【讨论】:

  • 您好,我的 googlemap 实例为空。您能帮我解决这个问题吗?
  • 很好地将地图片段与其他片段一起保存在选项卡或导航抽屉中,谢谢
【解决方案4】:

在你的课堂上

      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】:

    在您的布局文件中

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

    在您的fragment onCreate() 中,使用childFragmentManager

    在您的fragment 布局文件 中引用ma​​p fragment
    // 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)
    

    【讨论】:

      【解决方案6】:

      在犯了很多错误之后,我终于做到了,这是我的 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" />
      

      结果看起来像这样:-

      需要注意的最重要的一点是,不要将 app.Fragment 与 v4.Fragments 混合使用,否则应用程序会严重崩溃。

      如您所见,我使用 app.Fragment 附加和删除我的 MapView 片段

      希望对大家有所帮助

      【讨论】:

        【解决方案7】:

        您可以尝试在 FragmentContainerViewandroidx Fragment 包中添加 MapFragment:

        【讨论】:

          【解决方案8】:
                      <fragment
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"
                      android:name="com.google.android.gms.maps.SupportMapFragment"
                      android:id="@+id/location_map"
                      android:layout_above="@id/atmLocation_recyclerView"
                      />
          
          
          View root= inflater.inflate(R.layout.fragment_a_t_m_locations, container, false);
              SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.location_map);
              mapFragment.getMapAsync(googleMap -> {
                  mMap=googleMap;
                  if(mMap!=null){
                      mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                  }
              });
          

          【讨论】:

            猜你喜欢
            • 2012-02-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-04-16
            • 2020-02-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多