MapView во фрагменте (соты)


теперь, что окончательный пакет SDK с API-интерфейсы Google - что является лучшим способом, чтобы создать фрагмент с Положение? MapView нуждается в MapActivity, чтобы работать правильно.

имея действие, управляющее фрагментами, наследуется от MapActivity (плохое решение, потому что оно противоречит идее, что фрагменты являются автономными) и использовать обычный макет на основе xml не работает. Я получаю NullPointerException в MapActivity.setupMapView ():

E/AndroidRuntime(  597): Caused by: java.lang.NullPointerException
E/AndroidRuntime(  597):    at com.google.android.maps.MapActivity.setupMapView(MapActivity.java:400)
E/AndroidRuntime(  597):    at com.google.android.maps.MapView.(MapView.java:289)
E/AndroidRuntime(  597):    at com.google.android.maps.MapView.(MapView.java:264)
E/AndroidRuntime(  597):    at com.google.android.maps.MapView.(MapView.java:247)

моя вторая идея состояла в том, чтобы создать MapView программно и передать соответствующее действие (через getActivity ()) в качестве контекста конструктору MapView. Не работает:

E/AndroidRuntime(  834): Caused by: java.lang.IllegalArgumentException: MapViews can only be created inside instances of MapActivity.
E/AndroidRuntime(  834):    at 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):    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:900)
E/AndroidRuntime(  834):    at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:978)
E/AndroidRuntime(  834):    at android.app.Activity.onCreateView(Activity.java:4090)
E/AndroidRuntime(  834):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:664)

действительно должно быть что-то вроде MapFragment, который заботится о фоновых потоках MapView, я думаю... Итак, какова текущая лучшая практика для этого?

спасибо и привет из Германии, Валентин

12 81

12 ответов:

по состоянию на 03.12.2012 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.гуглить.андроид.СБМ.карты.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"/>

мне удалось решить эту проблему с помощью TabHost в фрагменте.

вот идея (кратко):

  1. MainFragmentActivity выходит FragmentActivity (из библиотеки поддержки) и MapFragment.

  2. MyMapActivity выходит MapActivity и содержать MapView.

  3. LocalActivityManagerFragment hosts LocalActivityManager

  4. MapFragment расширяет LocalActivityManagerFragment.

  5. и LocalActivityManager содержит MyMapActivity активность в нем.

пример реализации:https://github.com/inazaruk/map-fragment.


enter image description here

Как уже обсуждалось в Группы Google, Питер Дойл построил пользовательскую библиотеку совместимости, поддерживающую Google Maps тоже. android-поддержка-v4-googlemaps

однако, есть и обратная сторона:

В настоящее время одним из недостатков является то, что все классы, расширяющие FragmentActivity, являются MapActivitys. Его можно сделать отдельным классом (т. е. FragmentMapActivity), но это требует некоторого рефакторинга кода FragmentActivity.

просто чтобы уточнить ответ. Я попробовал подход, предложенный иназаруком и Кристофом. На самом деле вы можете запустить любую деятельность в фрагменте - не только google maps. Вот код, который реализует активность google map в виде фрагмента благодаря inazaruk и ChristophK.

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());
    }
}

отличные новости от Google по этому поводу. Они выпускают сегодня новый Google Maps API, с внутренними картами и MapFragment.

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" />

Google Maps API не является частью AOSP. Пока ни один Гуглер не отвечает, едва ли можно сказать, будет ли MapFragment в будущем.

возможной ограниченной альтернативой является использование WebViewFragment и злоупотреблять им, чтобы загрузить пользовательский maps.google.com URL.

хм очень плохо, что Google еще не ответил. FWIW если вам действительно нужно это сделать я не нашел другого способа, чем:

есть вкладка управление деятельностью наследовать от MapActivity, создать MapView там программно, есть mapfragment.xml содержит ViewGroup и добавляет MapView в ViewGroup с помощью

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

очевидно, что это сильно противоречит идее о том, что фрагменты должны быть самодостаточными, но ...

здесь MonoDroid (Mono для 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();
    }
}

Это решает мою проблему при добавлении MapView во фрагментах. https://github.com/petedoyle/android-support-v4-googlemaps

с новой версией ABS 4.0, нет support для MapFragmentActivity, вот хорошее решение для того, чтобы иметь mapview во фрагменте!

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

могу я получить решение:

  1. создать класс TempFragmentActivity расширяет MapActivity
  2. внутри TempFragmentActivity есть объект MapView (например, normal define в xml)
  3. снимите этом положение объекта форма родителя(макет)(ничтожными позже исключение)
  4. держите этот объект MapView где-то(например: Статический член TempFragmentActivity)
  5. в вашем фрагменте добавьте этот объект MapView с помощью кода (не определяйте в xml) в некоторые LinearLayout

Я написал небольшую библиотеку, разминая решения на основе LocalActivityManager для проблемы MapFragment (также включает пример приложения, показывающего различные ситуации использования):

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