【问题标题】:MapFragment in Action Bar Tabs操作栏选项卡中的 MapFragment
【发布时间】:2019-05-02 01:23:17
【问题描述】:

我正在尝试构建一个将实现操作栏选项卡的应用程序。其中一个选项卡应包含 MapFragment。

如何实现带有标签的操作栏,其中一个标签下是地图片段?

你能帮我解决这个问题吗?

这是我目前所拥有的:

主类

package com.nfc.demo;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;

public class NFCDemoActivity extends Activity {

  Tab selectedTab = null;

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ActionBar bar = getActionBar();
    bar.setDisplayShowHomeEnabled(false);
    bar.setDisplayShowTitleEnabled(false);

    bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    bar.setCustomView(R.layout.main);

    ActionBar.Tab mapTab = bar.newTab().setText("Map");
    ActionBar.Tab settingsTab = bar.newTab().setText("Settings");
    ActionBar.Tab aboutTab = bar.newTab().setText("About");

    MapFragment mapFragment = new MapFragment();
    SettingsFragment settingsFragment = new SettingsFragment();
    AboutFragment aboutFragment = new AboutFragment();

    mapTab.setTabListener(new TabListener(mapFragment));
    settingsTab.setTabListener(new TabListener(settingsFragment));
    aboutTab.setTabListener(new TabListener(aboutFragment));

    Tab selectedTab = (Tab) getLastNonConfigurationInstance();

    if (selectedTab == null) {
      bar.addTab(mapTab, false);
      bar.addTab(settingsTab, false);
      bar.addTab(aboutTab, true);
    }

    setContentView(R.layout.main);

  }

  public Object onRetainNonConfigurationInstance() {
    return selectedTab;
  }

  protected boolean isRouteDisplayed() {
      return false;
  }

  protected class TabListener implements ActionBar.TabListener {
    private Fragment fragment;

    public TabListener(Fragment fragment) {
        this.fragment = fragment;
    }

    public void onTabSelected(Tab tab, FragmentTransaction fragmentTransaction) {
        fragmentTransaction.replace(R.id.mainFragment, this.fragment, null);
        selectedTab = tab;
    }

    public void onTabUnselected(Tab tab, FragmentTransaction fragmentTransaction) {
        fragmentTransaction.remove(this.fragment);
    }

    public void onTabReselected(Tab tab, FragmentTransaction fragmentTransaction) {
        //do nothing
    }
  }
}

片段类都只是返回一个带有 .xml 布局的充气器。

XML 布局:

main.xml(地图应该在这个 XML 文件上)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

</LinearLayout>

settings.xml 和 about.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/textView123"
        android:text="asdfg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

但添加 MapFragment 会出错:

Error inflating class fragment 
error caused by java.lang.IllegalArgumentException: 
Binary XML file line #2: Duplicate id 0x7f040005, tag null, or parent id 0x1020002 with another fragment for com.google.android.gms.maps.MapFragment 12-28 21:14:07.991: E/AndroidRuntime(26189): at android.app.Activity.onCreateView(Activity.java:4722)

几天来,我一直在试图弄清楚如何进行,但我真的很困惑。 任何帮助/提示将不胜感激。

另外,getLastNonConfigurationInstance() 呢?它已被弃用。

【问题讨论】:

  • 对不起,我以为我的问题很清楚。我对其进行了编辑,但如果需要进一步改进,请告诉我。
  • 嗯,你的整体问题很清楚,但是你递给我们一堆代码,并没有解释该代码的问题所在。将MapFragment 放在操作栏选项卡中与将任何其他片段放在操作栏选项卡中没有什么不同。
  • 不过,我似乎不知道该怎么做。一旦我改变了 main.xml 并添加了一个片段,我得到一个 Error inflating class fragment 错误 caused by java.lang.IllegalArgumentException: Binary XML file line #2: Duplicate id 0x7f040005, tag null, or parent id 0x1020002 with another fragment for com.google.android.gms.maps.MapFragment 12-28 21:14:07.991: E/AndroidRuntime(26189): at android.app.Activity.onCreateView(Activity.java:4722)

标签: android android-layout android-fragments android-maps google-maps-android-api-2


【解决方案1】:

在以下解决方案中,可以将 GoogleMap 添加到操作栏选项卡/下拉菜单。这样做的关键在于正确设置您的 Fragment 以在切换到 Action Bar 中的另一个 Fragment 时销毁 MapFragment。

创建一个实现操作栏功能的 Activity:

  1. 在 Eclipse 中创建一个项目,将 Tabs 用于主要活动。如果您不这样做,请继续执行步骤 2-5。
  2. 创建一个扩展 Activity 并实现 ActionBar.OnNavigationListener 的类。
  3. 创建一个布局 XML 文件,该文件是您在标签片段之间切换时的容器。
  4. 在您的 Activity 类中实现/覆盖以下方法:public boolean onNavigationItemSelected(int position, long id)
  5. 在此方法中,在 position 对象之间切换以确定选定的选项卡,并使用 FragmentManager 将片段设置为新实例,如下所示:getFragmentManager().beginTransaction().replace(R.id.container, fragment).commit()

创建一个包含地图的片段:

  1. 创建一个扩展Fragment 的类以用作选项卡的片段。阅读 [1] 以更好地理解 MapFragment。
  2. 创建一个包含片段元素的布局 XML 文件(如 [1] 中所示)。使用该页面中的 XML 创建布局 XML 文件并在您的片段类中使用它。
  3. 通过覆盖 onCreateView 在片段类中扩展该布局 XML 文件。
  4. 您的应用程序现在应该在使用您的片段类的选项卡中显示一个地图,但是,切换到另一个选项卡并返回到地图选项卡将导致重复的视图 ID。要克服这个问题,请继续下一步。
  5. 在您的片段类中,重写以下方法以专门销毁底层 GoogleMap 对象,以便在地图选项卡再次加载您的片段类时重新创建它:

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        MapFragment f = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
        if (f != null) 
            getFragmentManager().beginTransaction().remove(f).commit();
    }

【讨论】:

  • 现在我正在使用:if (f != null && f.isResumed()) 或者我在关闭我的应用程序按下返回按钮时遇到异常。 TY
  • 这行得通,但如果我旋转屏幕,我的应用程序会因以下异常而崩溃:原因:java.lang.IllegalStateException:onSaveInstanceState 后无法执行此操作
  • @Matt:我不认为这是一种干净的方法,因为在这种情况下,我们有一个嵌套片段(Tab-Fragment 中的 MapFragment),并且仍然不支持使用布局的静态方式。作者:要么使用 MapView 作为 MapFragment 的替代品,要么使用 .hide() / .show() 带有地图的 Fragment 而不是 .replace() / .remove()-ing 它(通过 FragmentTransaction)。您可能还想尝试支持程序化嵌套片段支持的支持库(rev 11 及更高版本)。
  • 我终于让它在我的自定义片段和普通 MapView 上顺利运行,请参阅此处的代码 stackoverflow.com/a/20505273/1005652
【解决方案2】:

不确定您是否已经解决。 您必须将 google play 服务添加为库项目才能使其正常工作。首先我尝试添加 jar 文件,但没有成功。

【讨论】:

  • 如果 google play 服务设置不正确,您的地图将无法加载。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多