MapView dans un Fragment (nid D'abeille))
maintenant que le SDK final est sorti avec google apis-Quelle est la meilleure façon de créer un Fragment avec MapView? MapView a besoin d'une Mapactivité pour fonctionner correctement.
avoir l'activité Gérer les Fragments hériter de MapActivity (mauvaise solution car elle va à l'encontre de l'idée que les Fragments sont autonomes) et utiliser une mise en page xml régulière ne fonctionne pas. Je reçois une NullPointerException dans 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)
My la deuxième idée était de créer le MapView de manière programmatique et de passer l'activité associée (via getActivity()) comme contexte au constructeur MapView. Ne fonctionne pas:
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)
vraiment il devrait y avoir quelque chose comme MapFragment qui prend soin des fils de fond dont MapView a besoin je suppose... Quelle est donc la meilleure pratique actuelle pour ce faire?
remerciements et salutations de L'Allemagne, Valentin 151930920"
12 réponses
en date du 03.12.2012 Google a publié Google Maps API Android v2 . Maintenant, vous pouvez oublier ces problèmes. https://developers.google.com/maps/documentation/android /
exemple utilisant la nouvelle API - https://developers.google.com/maps/documentation/android/start#add_a_map
cette API fonctionnera pour au moins Android API 8, donc utilisez-le ;).
alors maintenant vous pouvez simplement utiliser "com.Google.Android.gms.cartographie.MapFragment" fragment de la classe. Il affiche la carte dans votre Activité. Exemple de Layout à partir du lien ci-dessus:
<?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"/>
j'ai réussi à résoudre ce problème en utilisant TabHost dans fragment.
Voici l'idée (brièvement):
-
MainFragmentActivity
étendFragmentActivity
(de la bibliothèque de soutien) et aMapFragment
. -
MyMapActivity
s'étendMapActivity
et contiennentMapView
. -
"151960920 hôtes"
LocalActivityManager
-
MapFragment
s'étendLocalActivityManagerFragment
. -
Et
LocalActivityManager
contientMyMapActivity
de l'activité.
exemple de mise en œuvre: https://github.com/inazaruk/map-fragment .
comme indiqué sur Google Groups , Peter Doyle a construit une bibliothèque de compatibilité personnalisée supportant aussi Google Maps. android-support-v4-googlemaps
cependant, il y a un inconvénient aussi:
actuellement, un inconvénient est que toutes les classes étendant L'activité de fragmentation sont des MapActivitys. Il est possible de faire une classe séparée (i.e. FragmentMapActivity), mais cela nécessite un certain remaniement de le code de Fragmentactivité.
Juste pour clarifier la réponse. J'ai essayé l'approche suggérée par inazaruk et Christophe. En fait, vous pouvez exécuter n'importe quelle activité dans un fragment - pas seulement Google maps. Voici le code qui implémente l'activité google map comme un fragment grâce à inazaruk et Christophe.
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());
}
}
grande nouvelle de Google à ce sujet. Ils sortent aujourd'hui un nouvelle API Google Maps , avec des cartes intérieures et 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" />
L'API GoogleMaps ne fait pas partie de L'AOSP. Tant qu'aucun Googler ne répond, il est à peine possible de dire s'il y aura un MapFragment dans le futur.
une alternative limitée possible est d'utiliser une WebViewFragment
et d'en abuser pour charger une URL personnalisée maps.google.com
.
HM dommage que Google n'ait pas encore répondu. FWIW si vous avez vraiment besoin de faire cela, je n'ai pas trouvé d'autre moyen que:
avoir L'onglet Gérer L'activité hériter de MapActivity, créer le MapView dans là programmatically, avoir le mapfragment.xml contiennent un ViewGroup et ajouter la MapView à la ViewGroup à l'aide de
((ViewGroup) getFragmentManager().findFragmentById(R.id.finder_map_fragment).getView()).addView(mapView);;
cela va clairement à l'encontre de l'idée que les fragments doivent être autonomes mais ...
Voici une version MonoDroid ( Mono for Android ) d'une version très simplifiée MapFragment :
public class MapFragment : Fragment
{
// FOLLOW /q/mapview-in-a-fragment-honeycomb-74111/"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();
}
}
cela résout mon problème en ajoutant MapView en Fragments. https://github.com/petedoyle/android-support-v4-googlemaps
avec la nouvelle version D'ABS 4.0, il n'y a pas de support pour MapFragmentActivity, voici une bonne solution pour avoir un mapview dans un Fragment!
https://xrigau.wordpress.com/2012/03/22/howto-actionbarsherlock-mapfragment-listfragment/#comment-21
Peut-on avoir la solution:
- créer une classe TempFragmentActivity extends MapActivity
- il y a un objet MapView à L'intérieur de TempFragmentActivity(comme normal define en xml)
- supprimer cette forme d'objet MapView parent (LinearLayout) (supprimer l'exception ultérieure)
- garder cet objet MapView quelque part (ex: membre statique de TempFragmentActivity)
- dans votre Fragment , ajouter cet objet MapView utilisant le code (ne pas définir en xml) dans un certain Liner-Layout
j'ai écrit une petite bibliothèque, écrasant le LocalActivityManager de solutions basées sur la MapFragment problème (comprend également un exemple d'application montrant les différentes situations d'utilisation):