android - Fragment 内的 MapView - 指定的子项已有父项

标签 android android-mapview fragment

我正在尝试在 fragment 中显示 MapView(使用被黑的兼容库)。以下在过去工作得很好:

  • fragment 的 onCreateView() 只是返回一个新的 FrameLayout
  • fragment 的 onActivityCreated() 从 Acitivity 中获取 MapView 并将其添加到其 View 层次结构中
  • onDestroyView() 从其 View 层次结构中删除 MapView

现在我希望该 fragment 使用在 xml 中定义的布局,以便我可以拥有一些其他 UI 内容。将 MapView 元素放在布局文件中总是会崩溃,所以我是这样做的:

ma​​p_screen_fragment.xml

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


    <FrameLayout
        android:id="@+id/map_container"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    </FrameLayout>

</LinearLayout>

我的 MapScreenActivity 包含实际的 MapView, fragment 调用 getMapView(),所以我不会遇到“can”有多个 MapView"问题:

MapScreenActivity.java

public class MapScreenActivity extends FragmentActivity {
    protected Fragment fragment;
    protected MapView mapView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.single_pane_empty);

        if (savedInstanceState == null) {
            fragment = new MapScreenFragment();

            getSupportFragmentManager().beginTransaction().add(R.id.root_container, fragment)
                    .commit();
        }
    }

    public MapView getMapView() {
        if (mapView == null) {
            mapView = new MapView(this, getResources().getString(R.string.maps_api_key));
        }

        return mapView;
    }
}

MapScreenFragment.java

public class MapScreenFragment extends Fragment {
    protected ViewGroup mapContainer;
    protected MapView mapView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle args) {
        View root = inflater.inflate(R.layout.map_screen_fragment, container);
        mapContainer = (ViewGroup) root.findViewById(R.id.map_container);
        return root;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mapView = ((MapScreenActivity) getActivity()).getMapView();
        mapView.setClickable(true);
        mapView.setBuiltInZoomControls(true);

        mapContainer.addView(mapView);

    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mapContainer.removeView(mapView);
    }   

}

从理论上讲,这应该与首先描述的 new FrameLayout 方法的工作方式相同。但是,我每次都得到这个:

02-24 18:01:28.139: E/AndroidRuntime(502): FATAL EXCEPTION: main
02-24 18:01:28.139: E/AndroidRuntime(502): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.mapfragment/com.example.mapfragment.MapScreenActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.app.ActivityThread.access$1500(ActivityThread.java:117)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.os.Handler.dispatchMessage(Handler.java:99)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.os.Looper.loop(Looper.java:130)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.app.ActivityThread.main(ActivityThread.java:3683)
02-24 18:01:28.139: E/AndroidRuntime(502):  at java.lang.reflect.Method.invokeNative(Native Method)
02-24 18:01:28.139: E/AndroidRuntime(502):  at java.lang.reflect.Method.invoke(Method.java:507)
02-24 18:01:28.139: E/AndroidRuntime(502):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
02-24 18:01:28.139: E/AndroidRuntime(502):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
02-24 18:01:28.139: E/AndroidRuntime(502):  at dalvik.system.NativeStart.main(Native Method)
02-24 18:01:28.139: E/AndroidRuntime(502): Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.view.ViewGroup.addViewInner(ViewGroup.java:1976)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.view.ViewGroup.addView(ViewGroup.java:1871)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.view.ViewGroup.addView(ViewGroup.java:1828)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.view.ViewGroup.addView(ViewGroup.java:1808)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.support.v4.app.NoSaveStateFrameLayout.wrap(Unknown Source)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.support.v4.app.BackStackRecord.run(Unknown Source)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.support.v4.app.FragmentManagerImpl.execPendingActions(Unknown Source)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.support.v4.app.FragmentActivity.onStart(Unknown Source)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.app.Activity.performStart(Activity.java:3791)
02-24 18:01:28.139: E/AndroidRuntime(502):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1620)
02-24 18:01:28.139: E/AndroidRuntime(502):  ... 11 more

在从 getMapView() 返回之前,我尝试从它的父级中删除 MapView,但仍然崩溃。我真的不明白为什么这种方法不起作用,我们将不胜感激。

最佳答案

我不确定这是否与您遇到的问题相同,但事实证明膨胀是可以的,只要您不附加到根即可。

例如,你需要做这样的事情:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.id.my_layout, container, false);
}

如果您未能将最后一个 false 参数添加到 inflate() 调用,那么您将得到 IllegalStateException。

我认为发生的事情是,如果没有额外的 false 参数,您的膨胀 View 树将附加到 Root View (container),然后在 Activity 启动时,系统尝试再次将 View 树添加到根。因此错误。

关于android - Fragment 内的 MapView - 指定的子项已有父项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9440606/

相关文章:

android - 无法链接到 jni/ndk 共享库中的 libjpeg.so

android - 将 Square Picasso 的缓存大小限制为最大 60MB

android - 无法从收件箱中删除单个消息(Android 版本 4.1.2)

android - 在 map View 中添加错误的位置?

android - 谷歌地图 Android API v2 : My location marker always over other markers?

android - 如何创建 Rest api,以及如何使用 android 应用程序使用 rest api

java - 如何在标记下移动 map ?安卓

android - 如何在 onCreate 中将 View 添加到 fragment

android - 扩展到另一个的 fragment

Android - 滑动 fragment