web-dev-qa-db-ja.com

フラグメント内のMapView(ハニカム)

これで、最終的なSDKがGoogle APIとともにリリースされました。MapViewでフラグメントを作成する最良の方法は何ですか? MapViewを正しく動作させるには、MapActivityが必要です。

フラグメントを管理するアクティビティがMapActivityから継承し(フラグメントが自己完結型であるという考えに反するため、悪いソリューションです)、通常のxmlベースのレイアウトを使用しても機能しません。 MapActivity.setupMapView()でNullPointerExceptionが発生します。

 E/AndroidRuntime(597):原因:Java.lang.NullPointerException 
 E/AndroidRuntime(597):at com.google.Android.maps.MapActivity.setupMapView(MapActivity.Java:400 )
 E/AndroidRuntime(597):com.google.Android.maps.MapView。(MapView.Java:289)
 E/AndroidRuntime(597):com.google.Android。 maps.MapView。(MapView.Java:264)
 E/AndroidRuntime(597):at com.google.Android.maps.MapView。(MapView.Java:247)

私の2番目のアイデアは、MapViewをプログラムで作成し、関連するアクティビティ(getActivity()経由)をContextとしてMapViewコンストラクターに渡すことでした。動作しません:

 E/AndroidRuntime(834):原因:Java.lang.IllegalArgumentException:MapViewはMapActivityのインスタンス内でのみ作成できます。
 E/AndroidRuntime(834):com.google.Androidで。 maps.MapView。(MapView.Java:291)
 E/AndroidRuntime(834):at com.google.Android.maps.MapView。(MapView.Java:235)
 E/AndroidRuntime( 834):at de.foo.FinderMapFragment.onCreateView(FinderMapFragment.Java:225)
 E/AndroidRuntime(834):at Android.app.FragmentManagerImpl.moveToState(FragmentManager.Java:708)
 E/AndroidRuntime(834):Android.app.FragmentManagerImpl.moveToState(FragmentManager.Java:900)
 E/AndroidRuntime(834):at Android.app.FragmentManagerImpl.addFragment(FragmentManager.Java:978)
 E/AndroidRuntime(834):Android.app.Activity.onCreateView(Activity.Java:4090)
 E/AndroidRuntime(834):Android.view.LayoutInflater.createViewFromTag(LayoutInflater.Java :664)

MapViewが必要とするバックグラウンドスレッドを処理するMapFragmentのようなものが本当にあるはずです...では、これを行うための現在のベストプラクティスは何でしょうか。

ドイツ、バレンティンからの感謝と敬意

81
Valentin

2012年3月12日の時点で、GoogleはリリースしましたGoogle Maps Android API v2。これらの問題を忘れることができます。- https://developers.google.com/maps/documentation/Android/

新しいAPIを使用した例- https://developers.google.com/maps/documentation/Android/start#add_a_map

このAPIは、少なくともAndroid API 8なので使用してください;)。

そのため、単に「com.google.Android.gms.maps.MapFragment」フラグメントクラスを使用できます。アクティビティにマップが表示されます。上記のリンクのレイアウト例:

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/map"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    class="com.google.Android.gms.maps.MapFragment"/>
8
Paul Annekov

フラグメントでTabHostを使用して、これを解決することができました。

これがアイデアです(簡単に):

  1. MainFragmentActivityFragmentActivityを拡張し(サポートライブラリから)、MapFragmentを持ちます。

  2. MyMapActivityMapActivity を拡張し、 MapView を含みます。

  3. LocalActivityManagerFragmentホスト LocalActivityManager

  4. MapFragmentLocalActivityManagerFragmentを拡張します。

  5. そして LocalActivityManager にはMyMapActivityアクティビティが含まれています。

実装例: https://github.com/inazaruk/map-fragment


enter image description here

87
inazaruk

Googleグループ で説明したように、Peter DoyleはGoogleマップもサポートするカスタム互換性ライブラリを構築しました。 Android-support-v4-googlemaps

ただし、欠点もあります。

現在、欠点の1つは、FragmentActivityを拡張するすべてのクラスがMapActivityであるということです。別のクラス(FragmentMapActivity)を作成することは可能ですが、FragmentActivityコードのリファクタリングが必要です。

23
TomTasche

答えを明確にするだけです。 inazarukとChristophKが提案したアプローチを試しました。実際、Googleマップだけでなく、フラグメント内のあらゆるアクティビティを実行できます。これは、inazarukとChristophKのおかげで、Googleマップアクティビティをフラグメントとして実装するコードです。

import com.actionbarsherlock.app.SherlockFragment;
import Android.view.Window;

import Android.app.LocalActivityManager;
import Android.content.Intent;
import Android.os.Bundle;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;

public class MapFragment extends SherlockFragment {
    private static final String KEY_STATE_BUNDLE = "localActivityManagerState";

    private LocalActivityManager mLocalActivityManager;

    protected LocalActivityManager getLocalActivityManager() {
        return mLocalActivityManager;
    }

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

        Bundle state = null;
        if (savedInstanceState != null) {
            state = savedInstanceState.getBundle(KEY_STATE_BUNDLE);
        }

        mLocalActivityManager = new LocalActivityManager(getActivity(), true);
        mLocalActivityManager.dispatchCreate(state);
    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
            //This is where you specify you activity class
        Intent i = new Intent(getActivity(), GMapActivity.class); 
        Window w = mLocalActivityManager.startActivity("tag", i); 
        View currentView=w.getDecorView(); 
        currentView.setVisibility(View.VISIBLE); 
        currentView.setFocusableInTouchMode(true); 
        ((ViewGroup) currentView).setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        return currentView;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBundle(KEY_STATE_BUNDLE,
                mLocalActivityManager.saveInstanceState());
    }

    @Override
    public void onResume() {
        super.onResume();
        mLocalActivityManager.dispatchResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mLocalActivityManager.dispatchPause(getActivity().isFinishing());
    }

    @Override
    public void onStop() {
        super.onStop();
        mLocalActivityManager.dispatchStop();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mLocalActivityManager.dispatchDestroy(getActivity().isFinishing());
    }
}
13
zmicer

これに関するGoogleからの素晴らしいニュース。彼らは本日、インドアマップとMapFragmentを備えた 新しいGoogle Maps API をリリースします。

With this new API, adding a map to your Activity is as simple as:

<fragment
  Android:id="@+id/map"
  Android:layout_width="match_parent"
  Android:layout_height="match_parent"
  class="com.google.Android.gms.maps.MapFragment" />
4
Marcelo

Google Maps APIはAOSPの一部ではありません。 Google社員が応答しない限り、将来MapFragmentがあるかどうかはほとんどわかりません。

可能性のある制限された代替手段は、 WebViewFragment を使用し、それを悪用してカスタムmaps.google.com URL。

2

MonoDroidMono for Android)非常に単純化されたMapFragmentのバージョンです:

public class MapFragment : Fragment
{
    // FOLLOW http://stackoverflow.com/questions/5109336/mapview-in-a-fragment-honeycomb
    private static  String KEY_STATE_BUNDLE = "localActivityManagerState";

    public override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        Bundle state = null;
        if (savedInstanceState != null) {
            state = savedInstanceState.GetBundle(KEY_STATE_BUNDLE);
        }
        mLocalActivityManager = new LocalActivityManager(Activity, true);
        mLocalActivityManager.DispatchCreate(state);
    }

    public override Android.Views.View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        //This is where you specify you activity class
        Intent i = new Intent(Activity, typeof(SteamLocationMapActivity)); 
        Window w = mLocalActivityManager.StartActivity("tag", i); 
        View currentView=w.DecorView; 
        currentView.Visibility = ViewStates.Visible; 
        currentView.FocusableInTouchMode = true; 
        ((ViewGroup) currentView).DescendantFocusability = DescendantFocusability.AfterDescendants;
        return currentView;
    }

    private LocalActivityManager mLocalActivityManager;
    protected LocalActivityManager GetLocalActivityManager() {
        return mLocalActivityManager;
    }   


    public override void OnSaveInstanceState(Bundle outState)
    {
        base.OnSaveInstanceState(outState);
        outState.PutBundle(KEY_STATE_BUNDLE,mLocalActivityManager.SaveInstanceState());
    }

    public override void OnResume()
    {
        base.OnResume();
        mLocalActivityManager.DispatchResume();

    }

    public override void OnPause()
    {
        base.OnPause();
        mLocalActivityManager.DispatchPause(Activity.IsFinishing);
    }

    public override void OnStop()
    {
        base.OnStop();
        mLocalActivityManager.DispatchStop();
    }
}
2

Googleがまだ応答していないのは残念です。 FWIWあなたが本当にこれを行う必要がある場合、私は他の方法を見つけませんでした:

タブ管理アクティビティにMapActivityを継承させ、プログラムでMapViewを作成し、mapfragment.xmlにViewGroupを含め、MapViewを使用してViewGroupに追加します

((ViewGroup)getFragmentManager()。findFragmentById(R.id.Finder_map_fragment).getView())。addView(mapView);; 

これは明らかに、フラグメントは自己完結型であるという考え方に大きく反しますが...

2
Valentin

ソリューションを入手できますか:

  1. 作成クラスTempFragmentActivityはMapActivityを拡張します
  2. tempFragmentActivity内にMapViewオブジェクトがあります(xmlの通常の定義と同様)
  3. parent(LinearLayout)からこのMapViewオブジェクトを削除します(後で例外を回避)
  4. このMapViewオブジェクトをどこかに保持します(例:TempFragmentActivityの静的メンバー)
  5. fragmentで、コードを使用してこのMapViewオブジェクトを追加します(xmlで定義しないでください)。
1
Joe Zhang

これにより、フラグメントにMapViewを追加する際の問題が解決します。 https://github.com/petedoyle/Android-support-v4-googlemaps

1
Sudhin Philip

ABS 4.0の新しいバージョンでは、MapFragmentActivityのサポートはありません。これは、フラグメントにマップビューを作成するための優れたソリューションです。

https://xrigau.wordpress.com/2012/03/22/howto-actionbarsherlock-mapfragment-listfragment/#comment-21

1
cesards

MapFragment問題に対するLocalActivityManagerベースのソリューションをマッシュアップする小さなライブラリを作成しました(さまざまな使用状況を示すサンプルアプリも含まれています)。

https://github.com/coreform/Android-tandemactivities

0
straya