Vista del mapa en un fragmento (Panal)


Ahora que el SDK final está disponible con las api de Google, ¿cuál es la mejor manera de crear un fragmento con una vista de mapa? MapView necesita una MapActivity para funcionar correctamente.

Tener la Actividad que administra los Fragmentos heredados de MapActivity (mala solución porque va en contra de la idea de que los Fragmentos son autónomos) y usar un diseño regular basado en xml no funciona. Obtengo una excepción NullPointerException en 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)

Mi segunda idea fue crear la vista del mapa programáticamente y pasar la actividad asociada (a través de getActivity ()) como Contexto al constructor MapView. No funciona:

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)

Realmente debería haber algo como MapFragment que se encargue de los hilos de fondo que MapView necesita supongo... Entonces, ¿cuál es la mejor práctica actual para hacer esto?

Gracias y saludos desde Alemania, Valentin

Author: Programmer Bruce, 2011-02-24

12 answers

A partir del 03.12.2012 Google lanzó Google Maps Android API v2. Ahora puedes olvidarte de estos problemas. https://developers.google.com/maps/documentation/android /

Ejemplo usando nueva API - https://developers.google.com/maps/documentation/android/start#add_a_map

Esta API funcionará al menos para Android API 8, así que úsala ;).

Así que ahora puedes simplemente usar " com.Google.androide.gms.asignar.MapFragment " clase de fragmento. Se mostrará el mapa en tu Actividad. Ejemplo de diseño del enlace anterior:

<?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
Author: Paul Annekov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-11 15:18:09

He logrado resolver esto usando TabHost en fragment.

Aquí está la idea (brevemente):

  1. MainFragmentActivity extiende FragmentActivity (desde la biblioteca de soporte) y tiene MapFragment.

  2. MyMapActivity se extiende MapActivity y contener MapView.

  3. LocalActivityManagerFragment hosts LocalActivityManager

  4. MapFragment extiende LocalActivityManagerFragment.

  5. Y LocalActivityManager contiene MyMapActivity actividad en ella.

Ejemplo aplicación: https://github.com/inazaruk/map-fragment.


introduzca la descripción de la imagen aquí

 87
Author: inazaruk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-25 18:38:24

Como se discutió en Google Groups, Peter Doyle construyó una biblioteca de compatibilidad personalizada compatible con Google Maps también. android-soporte-v4-googlemaps

Sin embargo, también hay un inconveniente:

Actualmente, un inconveniente es que TODAS las clases que extienden FragmentActivity son MapActivitys. Es posible hacer una clase separada (es decir, FragmentMapActivity), pero requiere alguna refactorización del código FragmentActivity.

 23
Author: TomTasche,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-28 11:36:26

Solo para aclarar la respuesta. Probé el enfoque sugerido por inazaruk y Christoph. En realidad, puedes ejecutar cualquier actividad en un fragmento, no solo en google Maps. Aquí está el código que implementa la actividad de google map como un fragmento gracias a inazaruk y 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());
    }
}
 13
Author: zmicer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-24 14:11:56

Grandes noticias de Google sobre esto. Hoy están lanzando una nueva API de Google Maps, con mapas interiores y 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" />
 4
Author: Marcelo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-03 19:48:14

La API de Google Maps no forma parte del AOSP. Mientras ningún Googler responda, apenas es posible saber si habrá un MapFragment en el futuro.

Una posible alternativa limitada es utilizar un WebViewFragment y abusar de ella para cargar una URL personalizada maps.google.com.

 2
Author: Octavian Damiean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-24 19:26:20

Hm lástima que Google no ha respondido todavía. FWIW si realmente necesitas hacer esto, no encontré otra manera que:

Haga que la Pestaña Administrar Actividad herede de MapActivity, cree el MapView en allí programáticamente, tenga el mapfragment.xml contiene un ViewGroup y agrega el MapView al ViewGroup usando

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

Claramente esto va fuertemente en contra de la idea de que los fragmentos son ment para ser autónomo pero ...

 2
Author: Valentin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-25 17:25:50

He Aquí un MonoDroid (Mono para Android) versión muy simplificada 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
Author: BahaiResearch.com,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-02 02:15:01

Esto resuelve mi problema al agregar MapView en Fragmentos. https://github.com/petedoyle/android-support-v4-googlemaps

 1
Author: Sudhin Philip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-11 09:42:07

Con la nueva versión de ABS 4.0, no hay soporte para MapFragmentActivity, ¡aquí hay una buena solución para tener una vista de mapa en un fragmento!

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

 1
Author: cesards,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-04 07:08:31

Puedo obtener la solución:

  1. crear clase TempFragmentActivity extiende MapActivity
  2. hay un objeto MapView dentro de TempFragmentActivity(como normal define en xml)
  3. elimine este objeto MapView del padre (LinearLayout) (void later exception)
  4. mantenga este objeto MapView en algún lugar (ej: static member of TempFragmentActivity)
  5. en su fragmento , agregue este objeto MapView usando código (no defina en xml) en algún LinearLayout
 1
Author: Joe Zhang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-10 14:18:14

Escribí una pequeña biblioteca, mezclando las soluciones basadas en LocalActivityManager para el problema MapFragment (también incluye una aplicación de ejemplo que muestra varias situaciones de uso):

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

 0
Author: straya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-29 00:08:20