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

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

81 голосов
/ 24 февраля 2011

Теперь, когда окончательный SDK вышел с Google API - каков наилучший способ создания фрагмента с MapView? Для правильной работы 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 ]

87 голосов
/ 14 ноября 2011

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

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

  1. MainFragmentActivity расширяется FragmentActivity (из библиотеки поддержки) и имеет MapFragment.

  2. MyMapActivity расширяется MapActivity и содержит MapView.

  3. LocalActivityManagerFragment хостов LocalActivityManager

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

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

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


enter image description here

23 голосов
/ 28 июля 2011

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

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

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

13 голосов
/ 24 мая 2012

Просто чтобы уточнить ответ.Я попробовал подход, предложенный Иназаруком и Кристофом.На самом деле вы можете выполнять любые действия в фрагменте - не только карты Google.Вот код, который реализует активность карты Google в виде фрагмента благодаря 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());
    }
}
8 голосов
/ 10 декабря 2012

По состоянию на 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.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"/>
4 голосов
/ 03 декабря 2012

Отличные новости от Google по этому вопросу.Сегодня они выпускают новый API Карт Google с картами помещений и 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" />
2 голосов
/ 02 октября 2012

Вот MonoDroid ( Mono для Android ) версия очень упрощенного MapFragment :

public class MapFragment : Fragment
{
    // FOLLOW /4493121/mapview-vo-fragmente-soty
    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 голосов
/ 25 февраля 2011

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

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

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

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

2 голосов
/ 24 февраля 2011

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

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

1 голос
/ 10 мая 2012

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

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

В новой версии ABS 4.0 поддержка MapFragmentActivity отсутствует, вот хорошее решение для просмотра карты во фрагменте!

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

...