Search code examples
androidarcgisesrimapfragment

MapFragment ArcGis - The specified child already has a parent


I'm trying to display a MapView from ArcGis in Android Studio. I'm using Map Fragments for that, I put in the xml the Map and my other UI stuff. Putting the MapView element in the layout file always crashes, so I'm doing it this way:

my_main_activity.xml

<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/maps_app_activity_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<!-- The main content view -->

<FrameLayout
    android:id="@+id/maps_app_activity_content_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<!-- The navigation drawer -->
<ListView
    android:id="@+id/maps_app_activity_left_drawer"
    style="@style/drawer_listView_style"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="@android:color/darker_gray"
    android:choiceMode="singleChoice"
    android:divider="@color/esri_gray"
    android:dividerHeight="1px" />

and this is the framgent layout: map_fragment_layout.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map_fragment_map_container_frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The map configuration -->
<com.esri.android.map.MapView
    android:id="@+id/map_layout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    initExtent = "-9934033.827 1537316.31 -9933312.043 1537940.728" > <!-- xmin ymin xmax ymax -->
</com.esri.android.map.MapView>

My map fragment class holds every configuration of the MapView:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {

    mMapContainer = (FrameLayout) inflater.inflate(R.layout.map_fragment_layout,container,false);

    // Add dynamic layer to MapView (Base)
    // Retrieve the map and initial extent from XML layout
    MapView mapView = (MapView)mMapContainer.findViewById(R.id.map_layout);
    ArcGISDynamicMapServiceLayer baseMap = new ArcGISDynamicMapServiceLayer(baseMapURL);
    mapView.addLayer(baseMap);
    //Creates a dynamic layer using service URL
    ArcGISDynamicMapServiceLayer dynamicLayer = new ArcGISDynamicMapServiceLayer(dynamicMapURL);
    //Adds layer into the 'MapView'
    mapView.addLayer(dynamicLayer);

    // Set the MapView to allow the user to rotate the map when as part of a pinch gesture.
    setMapView(mapView);
    mapView.zoomin();

    return mMapContainer;
}

the function setMapView configures the rest of MapView options:

private void setMapView(final MapView mapView) {

    mMapView = mapView;
    mMapView.setEsriLogoVisible(false);
    mMapView.enableWrapAround(true);
    mapView.setAllowRotationByPinch(true);

    // Creating an inflater
    mInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    // Setting up the layout params for the searchview and searchresult layout
    mlayoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP);
    mlayoutParams.setMargins(LEFT_MARGIN_SEARCH, TOP_MARGIN_SEARCH,RIGHT_MARGIN_SEARCH, BOTTOM_MARGIN_SEARCH);

    // set MapView into the activity layout
    mMapContainer.addView(mMapView);

    // Displaying the searchbox layout
    showSearchBoxLayout();

After debuging this error shows up:

java.lang.RuntimeException: Unable to start activity ComponentInfo{zero.ucamaps/zero.ucamaps.MainActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
        at android.app.ActivityThread.access$800(ActivityThread.java:151)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
 Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
        at android.view.ViewGroup.addViewInner(ViewGroup.java:3936)
        at android.view.ViewGroup.addView(ViewGroup.java:3786)
        at android.view.ViewGroup.addView(ViewGroup.java:3727)
        at android.view.ViewGroup.addView(ViewGroup.java:3700)
        at zero.ucamaps.MapFragment.setMapView(MapFragment.java:313)
        at zero.ucamaps.MapFragment.onCreateView(MapFragment.java:209)
        at android.app.Fragment.performCreateView(Fragment.java:2053)

I've tried removing the the MapView from it's parent before returning from getMapView(), and that still crashes. Any help at all would be appreciated.


Solution

  • You're trying to add the MapView to the same container twice, once in Java and once in XML.

    In map_fragment_layout.xml, you create the MapView as a child of a FrameLayout called map_fragment_map_container_frame_layout. That's fine.

    Then in setMapView, you call mMapContainer.addView(mMapView), which tries to add the MapView again as a child of the same FrameLayout. That causes the exception and is unnecessary. Remove that line of code.