2012-02-25 9 views
10

(ハッキングされた互換性ライブラリを使用して)フラグメント内にMapViewを表示しようとしています。以下は、過去にうまく働いている:MapView insideフラグメント指定子に親が既にあります

  • フラグメントのonCreateView()は、単に新しいFrameLayout
  • フラグメントのonActivityCreated()はAcitivityからのMapViewを取得し、そのビュー階層に追加します
  • onDestroyView()はそのからのMapViewを削除返しますビューの階層

ここで、他のUIの要素を持つことができるように、XMLで定義されたレイアウトをフラグメントに使用したいと思います。常にクラッシュレイアウトファイルでMapView要素を置くので、私はそれをこのようにやっている:

map_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を保持し、フラグメントはgetMapView()を呼び出します私は、「複数の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の方法と同じように動作するはずです。それはgetMapView()から戻る前に、親のだし、それがまだクラッシュから私はMapView削除しようとした

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 

:しかし、私はこのすべての時間を取得します。私は本当にこのアプローチがうまくいかない理由を理解していません。何の助けもありがたいです。

答えて

15

これはあなたと同じ問題であるかどうかはわかりませんが、あなたがルートに接続していない限り、膨張は問題ありません。あなたはinflate()コールにその最後のfalseの引数を追加するために失敗した場合、その後、あなたはIllegalStateExceptionが得られます

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

たとえば、あなたはこのような何かをする必要があります。

私は、余分なfalse引数がないと、膨らんだビューツリーがルートビュー(container)にアタッチされ、アクティビティが開始されると、システムはルートに再びビューツリーを追加しようとします。したがって、エラー。

+1

私はそのプロジェクトに再訪して以来、しばらくしていましたが、フラグメントは当時私のためにかなり新しくなっていましたので、これは実際に正解と思われます。 – Karakuri

+1

これはありがとう、最後の議論を示すまで何が起こっていたのか分からなかった:) – lfxgroove

+0

よろしくお願い致します。 :-) –

0

[UPDATE] 私はこれらすべてのLocalActivityManagerのソリューションを一緒にマッシュ、少しライブラリーを書いた:https://github.com/coreform/android-tandemactivities

[古い記事] あなたがに

あなたの前
mapContainer.removeView(mapView); 

mapContainer.addView(mapView); 

をすべきそのような例外は避けてください。

...文字通り前の行のように。

OK、コメントの後にフォロー:

はこのお試しください:物事の多くを試した後

if(mapView.getParent() != null) { 
    mapContainer.addView(mapView); 
} 
+0

私もそれを試してみましたが、うまくいきません。それでもまったく同じエラーが出ます。 – Karakuri

+0

私は '((ViewGroup)mapView.getParent()).removeView(mapView)'のバリエーションも試しましたが、どちらも動作しません。 – Karakuri

+0

あなたのMapViewが既にどの親に接続されているかを調べてみてください。あなたがすでにそれを追加しようとしている親であれば、それが追加され、ロジックまたはtry/catchステートメントでケースを処理できるようになります。私はこのスレッドのコメントに投稿した解決策を見つけます:http://nextlevelandroid.com/?p=114(lindoによるコメント)それは動作し、MapActivityを拡張するためにすべてのfriggen FragmentActivityを必要としません! – straya

1

を、私はこれをやってしまった:

私はonCreateView()で返さルートビューが作成されますプログラム的に、膨らまされていない。しかし、他のビューを膨らませて、それらをプログラムとして作成されたルートビューに子として追加しても問題は生じないようです。

この奇妙な行動の背後にあるものを見つけ出すことができる誰かに帽子があります。これが他の人にとって有益であることを願っています。

それは、私にとってこのでしょうではない仕事、私はこのトピックを再訪するのでしばらくして、私は思い出すようだEDIT

...このに対し

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saved) { 
    return inflater.inflate(R.layout.some_layout, container, false); 
} 

...私のために働くでしょう...

private ViewGroup mapContainer; 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saved) { 
    mapContainer = new LinearLayout(getActivity()); 
    return mapContainer; 
} 

.. 。そして後でonActivityCreated()私は、アクティビティからMapViewを取得し、それをmapContainerの子として追加します。他のビュー(MapViewの上のヘッダーのようなもの)が必要な場合、このコードスニペットが示すように、それらを別々に膨張させてmapContainerに追加することができます。私は断片を切り替えるたび

private ViewGroup mapContainer; 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saved) { 
    mapContainer = new LinearLayout(getActivity()); 
    mapContainer.setOrientation(LinearLayout.VERTICAL); 
    View headerView = inflater.inflate(R.layout.some_layout, mapContainer, false); 
    mapContainer.addView(headerView); 
    return mapContainer; 
} 
+0

例を挙げてください。 –

0

これは私のために働いていたものです... は私が

if (mapContainer.getChildAt(0) != null){ 
     mapContainer.removeViewAt(0); 
} 

私は私のonDestroy()またはonPause()メソッドでそれを入れていなかったのでした。私は断片を切り替えるたびにそれをしました。何らかの理由で、私の断片はonPause()を呼び出さなかった。私は

mapContainer.addView(mapView); 

を行なったし、すべてが私の作品私のonResume()メソッドで

。 IllegalStateExceptionsはこれ以上ありません。

関連する問題