Bir Parçada MapView (Petek)


81

son SDK artık google apis ile çıktı - MapView ile Fragment oluşturmanın en iyi yolu nedir? MapView'ın doğru çalışması için bir MapActivity'ye ihtiyacı vardır.

Fragmentleri yöneten Aktivitenin MapActivity'den miras alınması (kötü bir çözüm çünkü Fragmentlerin kendi içinde bulunduğu fikrine aykırıdır) ve normal xml tabanlı bir düzen kullanmak işe yaramaz. MapActivity.setupMapView () içinde bir NullPointerException alıyorum:

E / AndroidRuntime (597): Neden olduğu: java.lang.NullPointerException
E / AndroidRuntime (597): com.google.android.maps.MapActivity.setupMapView (MapActivity.java:400) adresinde
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): com.google.android.maps.MapView. (MapView.java:247)

İkinci fikrim, MapView'i programlı olarak oluşturmak ve ilişkili etkinliği (getActivity () aracılığıyla) Bağlam olarak MapView yapıcısına iletmekti. Çalışmıyor:

E / AndroidRuntime (834): Neden olduğu: java.lang.IllegalArgumentException: MapViews yalnızca MapActivity örneklerinin içinde oluşturulabilir.
E / AndroidRuntime (834): com.google.android.maps.MapView. (MapView.java:291)
E / AndroidRuntime (834): com.google.android.maps.MapView. (MapView.java:235)
E / AndroidRuntime (834): at de.foo.FinderMapFragment.onCreateView (FinderMapFragment.java:225)
E / AndroidRuntime (834): android.app.FragmentManagerImpl.moveToState'de (FragmentManager.java:708)
E / AndroidRuntime (834): android.app.FragmentManagerImpl.moveToState'de (FragmentManager.java:900)
E / AndroidRuntime (834): android.app.FragmentManagerImpl.addFragment'da (FragmentManager.java:978)
E / AndroidRuntime (834): android.app.Activity.onCreateView'de (Activity.java:4090)
E / AndroidRuntime (834): android.view.LayoutInflater.createViewFromTag'de (LayoutInflater.java:664)

Gerçekten de MapFragment gibi MapView'ın ihtiyaç duyduğu arka plan iş parçacıklarıyla ilgilenen bir şey olmalı sanırım ... Peki bunu yapmak için mevcut en iyi uygulama nedir?

Almanya'dan teşekkürler ve saygılar Valentin


2
Bunun için bir özellik isteği bildirdim. Lütfen yıldız ekleyin. code.google.com/p/android/issues/detail?id=15347
Jeremy Edwards

Yanıtlar:


8

03.12.2012 itibariyle Google, Google Maps Android API v2'yi piyasaya sürdü . Artık bu sorunları unutabilirsiniz. https://developers.google.com/maps/documentation/android/

Yeni API kullanan örnek - https://developers.google.com/maps/documentation/android/start#add_a_map

Bu API, en azından Android API 8 için çalışacaktır, bu yüzden onu kullanın;).

Yani artık "com.google.android.gms.maps.MapFragment" parça sınıfını kullanabilirsiniz. Haritayı Aktivitenizde gösterecektir. Yukarıdaki bağlantıdan düzen örneği:

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

87

TabHost'u parça halinde kullanarak bunu çözmeyi başardım.

İşte fikir (kısaca):

  1. MainFragmentActivitygenişler FragmentActivity(destek kitaplığından) ve vardır MapFragment.

  2. MyMapActivitygenişler MapActivityve içerir MapView.

  3. LocalActivityManagerFragment ana bilgisayarlar LocalActivityManager

  4. MapFragmentgenişler LocalActivityManagerFragment.

  5. Ve LocalActivityManageriçinde MyMapActivityaktivite içerir .

Örnek uygulama: https://github.com/inazaruk/map-fragment .


görüntü açıklamasını buraya girin


4
Daha sonra MapActivity'nin ana Activity (Fragment ile kolay olan) ile iletişim kurmasını istiyorsanız, Activity.getParent ()
Dori

3
Gerçekten bir TabHost kullanmanıza gerek yok, ayrıca bir LocalActivityManager kullanabilir ve geri dönen pencereyi parçanızın içeriğine ekleyebilirsiniz
ChristophK

4
Başka birinin merak etmesi durumunda, kod Intent i = new Intent(getActivity().getParent(), MyMapActivity.class); Window w = localActivityManager.startActivity("tag", i); currentView=w.getDecorView(); currentView.setVisibility(View.VISIBLE); currentView.setFocusableInTouchMode(true); ((ViewGroup) currentView).setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); this.contentView.addView(currentView);
ChristophK

8
dikkatli olun, LocalActivityManager artık kullanımdan kaldırıldı
louiscoquio

4
Sekmeleri ve parçaları kullanarak benim için iyi çalışıyor. Açıklama soranlar için projeyi ve kodunu görmeyi tercih ederim, anlaşılması kolay. Ve evet, LocalActivityManagerkullanımdan kaldırıldı, ancak bu sadece bir hack, bu sorun, Haritalar için uygun desteği Fragments'a dahil etmeye karar verdiklerinde doğru bir şekilde çözülecektir.
mdelolmo

23

Google Grupları'nda tartışıldığı gibi , Peter Doyle Google Haritalar'ı da destekleyen özel bir uyumluluk kitaplığı oluşturdu.android-support-v4-googlemaps

Ancak, bir dezavantajı da var:

Şu anda, bir dezavantajı FragmentActivity'yi genişleten TÜM sınıfların MapActivitys olmasıdır. Ayrı bir sınıf (yani FragmentMapActivity) yapmak mümkündür, ancak FragmentActivity kodunun yeniden düzenlenmesini gerektirir.


6
Bu aynı zamanda uygulamanızın en son destek kitaplığıyla güncel olmayacağı anlamına gelir. Android-support-v4-googlemaps birkaç kez güncellenmiş olsa da, şu anda 2 sürüm geride. Bu değiştirilmiş kitaplığın, kullanımdan kaldırılmış LocalActivityManager'ı kullanmaktan daha büyük bir hack olduğu konusunda başkalarıyla aynı fikirdeyim.
Stan Kurdziel

1
github.com/petedoyle/android-support-v4-googlemaps şimdi güncel (bu mesaj itibariyle r10). Ayrıca işleri yeniden düzenledim, böylece gelecekte güncel tutmak çok kolay olacak.
Pete Doyle

Bir sorum var. Uygulama zaten konuşlandırılmış ve kuruluysa, "en son destek kitaplığıyla güncel olmamanın" dezavantajı nedir?
hendrix

Bu yaklaşımla ilgili temel sorun olan IMO, uygulamanızı isteğe bağlı Haritalar desteğiyle dağıtamayacak olmanızdır. Tüm FragmentActivities MapActivity'yi genişlettiğinden, Google API'leri olmayan cihazlarda (örneğin Kindle Fire) kilitlenecektir.
Paul Lammertsma

13

Sadece cevabı netleştirmek için. İnazaruk ve ChristophK tarafından önerilen yaklaşımı denedim. Aslında herhangi bir faaliyeti bir parça halinde çalıştırabilirsiniz - sadece google maps değil. İşte inazaruk ve ChristophK sayesinde google harita etkinliğini bir parça olarak uygulayan kod.

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

2
Ancak kaçınan tek çözüm LocalActivityManager(burada tartışıldığı gibi: code.google.com/p/android/issues/detail?id=15347 ) hepsini genişletmeyi içerir FragmentActivities, bu da daha az optimal görünmektedir.
Estel

LocalActivityManager daha çok kullanımdan kaldırıldı, çünkü ActivityGroup bu durumda hala kullanışlıdır ve insanlar eksikliklerini çözmek için kullanıyorsa Google muhtemelen gelecekteki sürümlerde onu kaldırmak için iki kez düşünecektir.
straya

4

Google'dan bu konuda harika bir haber. Bugün iç mekan haritaları ve MapFragment içeren yeni bir Google Haritalar API'si yayınlıyorlar.

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

Tam olarak değil. Bunu bir FragmentPagerAdapter içinde kullanmayı deneyin.
Thomas Dignan

Siyah görünümden bahsediyorsanız, düzeltmek için küçük bir hack var stackoverflow.com/questions/13837697/…
Marcelo

Teşekkürler. Bunu daha sonra görmeye başladım ama şimdi polaris ile ilk harita api sürümünü kullanıyorum.
Thomas Dignan

2

Google Maps API, AOSP'nin bir parçası değildir. Google çalışanı yanıt vermediği sürece, gelecekte bir MapFragment olup olmayacağını söylemek neredeyse imkansızdır.

Olası sınırlı bir alternatif, WebViewFragmentözel bir maps.google.comURL yüklemek için a kullanmak ve kötüye kullanmaktır .


1
Harita API'sinin yakında parçalar ve vektör çizimiyle güncelleneceğini umuyoruz!
Nathan Schwermann

2

Google'ın henüz yanıt vermemiş olması çok kötü. FWIW Bunu gerçekten yapmanız gerekiyorsa şunlardan başka bir yol bulamadım:

Tab Yönetme Etkinliğinin MapActivity'den devralınmasını sağlayın, orada programlı olarak MapView oluşturun, mapfragment.xml'nin bir ViewGroup içermesini sağlayın ve MapView'i ViewGroup'a ekleyin.

((ViewGroup) getFragmentManager (). FindFragmentById (R.id.finder_map_fragment) .getView ()). AddView (mapView) ;;

Açıkçası bu, parçaların kendi kendine yeten olduğu fikrine şiddetle karşı çıkıyor ama ...


Teşekkürler, Fragment managing Activity genişletme MapActivity benim için mükemmel çalıştı.
Pete Doyle

2

İşte bu MonoDroid ( Mono Android için çok-basitleştirilmiş bir) sürümü 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();
    }
}



1

Çözümü alabilir miyim:

  1. sınıf oluştur TempFragmentActivity MapActivity'yi genişletir
  2. TempFragmentActivity içinde bir MapView nesnesi var (xml'deki normal tanım gibi)
  3. bu MapView nesnesini ebeveyn formundan kaldır (LinearLayout) (daha sonra geçersiz kılın)
  4. bu MapView nesnesini bir yerde tutun (örn: TempFragmentActivity'nin statik üyesi)
  5. Fragment'inizde, bu MapView nesnesini kodu kullanarak ekleyin (xml'de tanımlamayın) bazı LinearLayout

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.