Zduplikowany identyfikator, tag null lub identyfikator nadrzędny z innym fragmentem dla com.google.android.gms.maps.MapFragment

333

Mam aplikację z trzema zakładkami.

Każda karta ma własny plik .xml układu. Plik main.xml ma własny fragment mapy. To ten, który pojawia się przy pierwszym uruchomieniu aplikacji.

Wszystko działa dobrze, z wyjątkiem sytuacji, gdy zmieniam karty. Jeśli spróbuję wrócić do karty fragmentu mapy, pojawia się ten błąd. Przełączanie między kartami i między nimi działa dobrze.

Co może być nie tak?

To jest moja główna klasa i mój main.xml, a także odpowiednia klasa, której używam (dziennik błędów znajduje się również na dole)

główna klasa

package com.nfc.demo;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.widget.Toast;

public class NFCDemoActivity extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ActionBar bar = getActionBar();
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);

        bar.addTab(bar
                .newTab()
                .setText("Map")
                .setTabListener(
                        new TabListener<MapFragment>(this, "map",
                                MapFragment.class)));
        bar.addTab(bar
                .newTab()
                .setText("Settings")
                .setTabListener(
                        new TabListener<SettingsFragment>(this, "settings",
                                SettingsFragment.class)));
        bar.addTab(bar
                .newTab()
                .setText("About")
                .setTabListener(
                        new TabListener<AboutFragment>(this, "about",
                                AboutFragment.class)));

        if (savedInstanceState != null) {
            bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
        }
        // setContentView(R.layout.main);

    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
    }

    public static class TabListener<T extends Fragment> implements
            ActionBar.TabListener {
        private final Activity mActivity;
        private final String mTag;
        private final Class<T> mClass;
        private final Bundle mArgs;
        private Fragment mFragment;

        public TabListener(Activity activity, String tag, Class<T> clz) {
            this(activity, tag, clz, null);
        }

        public TabListener(Activity activity, String tag, Class<T> clz,
                Bundle args) {
            mActivity = activity;
            mTag = tag;
            mClass = clz;
            mArgs = args;

            // Check to see if we already have a fragment for this tab,
            // probably from a previously saved state. If so, deactivate
            // it, because our initial state is that a tab isn't shown.
            mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
            if (mFragment != null && !mFragment.isDetached()) {
                FragmentTransaction ft = mActivity.getFragmentManager()
                        .beginTransaction();
                ft.detach(mFragment);
                ft.commit();
            }
        }

        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            if (mFragment == null) {
                mFragment = Fragment.instantiate(mActivity, mClass.getName(),
                        mArgs);
                ft.add(android.R.id.content, mFragment, mTag);
            } else {
                ft.attach(mFragment);
            }
        }

        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            if (mFragment != null) {
                ft.detach(mFragment);
            }
        }

        public void onTabReselected(Tab tab, FragmentTransaction ft) {
            Toast.makeText(mActivity, "Reselected!", Toast.LENGTH_SHORT)
                         .show();
        }
    }

}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <fragment
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mapFragment"
        android:name="com.google.android.gms.maps.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

odpowiednia klasa (MapFragment.java)

package com.nfc.demo;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MapFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        return inflater.inflate(R.layout.main, container, false);
    }

    public void onDestroy() {
        super.onDestroy();
    }
}

błąd

android.view.InflateException: Binary XML file line #7: 
     Error inflating class fragment
   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
   at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
   at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
   at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
   at com.nfc.demo.MapFragment.onCreateView(MapFragment.java:15)
   at android.app.Fragment.performCreateView(Fragment.java:1695)
   at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:885)
   at android.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1255)
   at android.app.BackStackRecord.run(BackStackRecord.java:672)
   at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)
   at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441)
   at android.os.Handler.handleCallback(Handler.java:725)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:5039)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
   at dalvik.system.NativeStart.main(Native Method)

Caused by: java.lang.IllegalArgumentException: 
     Binary XML file line #7: Duplicate id 0x7f040005, tag null, or 
     parent id 0xffffffff with another fragment for 
     com.google.android.gms.maps.MapFragment
   at android.app.Activity.onCreateView(Activity.java:4722)
   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:680)
   ... 19 more
hermann
źródło
spróbuj tego - zwróć super.onCreateView (inflator, pojemnik, saveInstanceState); zamiast super.onCreateView (inflator, pojemnik, saveInstanceState); return inflater.inflate (R.layout.main, kontener, false);
Nik
nie należy dodawać fragmentu, gdy parametr saveInstanceState nie ma wartości NULL.
muyiou,
Spójrz na ten komentarz. Może ci to pomóc: stackoverflow.com/questions/15562416/…
Oleksandr
2
Zmień zaakceptowaną odpowiedź! Wybrałeś bardzo złą odpowiedź, która powoduje przeciek pamięci! Prawidłowa odpowiedź to: stackoverflow.com/a/19815266/902276
Daniele Segato

Odpowiedzi:

400

Odpowiedź, którą sugeruje Matt, działa, ale powoduje, że mapa jest odtwarzana i przerysowywana, co nie zawsze jest pożądane. Po wielu próbach i błędach znalazłem rozwiązanie, które działa dla mnie:

private static View view;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if (view != null) {
        ViewGroup parent = (ViewGroup) view.getParent();
        if (parent != null)
            parent.removeView(view);
    }
    try {
        view = inflater.inflate(R.layout.map, container, false);
    } catch (InflateException e) {
        /* map is already there, just return view as it is */
    }
    return view;
}

Dla lepszej oceny, oto „map.xml” (R.layout.map) z R.id.mapFragment (android: id = "@ + id / mapFragment"):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mapLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment" />
</LinearLayout>

Mam nadzieję, że to pomaga, ale nie mogę zagwarantować, że nie będzie miało to żadnych negatywnych skutków.

Edycja: Wystąpiły pewne negatywne skutki, na przykład podczas zamykania aplikacji i ponownego uruchamiania. Ponieważ aplikacja niekoniecznie musi zostać całkowicie zamknięta (ale po prostu uśpiona w tle), poprzedni kod, który przesłałem, nie powiedzie się po ponownym uruchomieniu aplikacji. Zaktualizowałem kod do czegoś, co działa dla mnie, wchodząc i wychodząc z mapy oraz wychodząc i uruchamiając ponownie aplikację. Nie jestem zbyt zadowolony z bitu try-catch, ale wydaje się, że działa wystarczająco dobrze. Kiedy patrzyłem na ślad stosu, przyszło mi do głowy, że mogę po prostu sprawdzić, czy fragment mapy znajduje się w FragmentManager, nie potrzeba bloku try-catch, zaktualizowano kod.

Więcej zmian: okazuje się, że mimo wszystko potrzebujesz tego catch-catch. Samo sprawdzenie fragmentu mapy okazało się jednak nie działać tak dobrze. Blergh.

Vidar Wahlberg
źródło
25
To zła odpowiedź -1! Wyciekasz aktywność za pomocą statycznego modyfikatora widoku. Główną przyczyną tego problemu jest prawdopodobnie inna wyciekająca czynność, której nie można wyrzucić śmieci, ponieważ utrzymujesz silne odniesienie do tego. W przypadku zgłoszenia wyjątku InflateException używasz widoku, który ma kontekst zniszczonej aktywności! Lepiej znajdź inne wycieki pamięci w swojej aplikacji, to rozwiąże wszystkie problemy.
tomrozb
1
Chyba możemy użyć WeakReference, aby uniknąć wycieku pamięci?
Desmond Lua,
2
To też działa dla mnie +1. Nie jesteś zobowiązany do używania statycznego odniesienia do widoku
Karol Żygłowicz 28.04.16
4
Nie rób tego !!! To powoduje wyciek pamięci. Jedynym powodem jest to, że napompujesz fragment z XML wewnątrz innego fragmentu. NIE powinieneś tego robić! Powinieneś użyć ChildFragmentManager i dodać fragment w onViewCreated ()!
Daniele Segato
1
Tak, to rzeczywiście wyciek aktywności. Znaleziono działające rozwiązanie w stackoverflow.com/a/27592123/683763 . Chodzi o to, aby ręcznie usunąć metodę SupportMapFragmentin onDestroyView.
ULazdins,
277

Problem polega na tym, że to, co próbujesz zrobić, nie powinno być zrobione. Nie powinieneś pompować fragmentów wewnątrz innych fragmentów. Z dokumentacji Androida :

Uwaga: Nie można nadmuchać układu do fragmentu, jeśli zawiera on <fragment>. Zagnieżdżone fragmenty są obsługiwane tylko wtedy, gdy są dynamicznie dodawane do fragmentu.

Chociaż możesz być w stanie wykonać zadanie za pomocą przedstawionych tutaj hacków, zdecydowanie sugeruję, abyś tego nie robił. Nie można mieć pewności, że te hacki poradzą sobie z tym, co robi każdy nowy system operacyjny Android, gdy próbujesz zawyżać układ dla fragmentu zawierającego inny fragment.

Jedynym obsługiwanym przez Androida sposobem dodania fragmentu do innego fragmentu jest transakcja z menedżera fragmentów potomnych.

Po prostu zmień układ XML na pusty kontener (w razie potrzeby dodaj identyfikator):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mapFragmentContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
</LinearLayout>

Następnie w onViewCreated(View view, @Nullable Bundle savedInstanceState)metodzie Fragment :

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    FragmentManager fm = getChildFragmentManager();
    SupportMapFragment mapFragment = (SupportMapFragment) fm.findFragmentByTag("mapFragment");
    if (mapFragment == null) {
        mapFragment = new SupportMapFragment();
        FragmentTransaction ft = fm.beginTransaction();
        ft.add(R.id.mapFragmentContainer, mapFragment, "mapFragment");
        ft.commit();
        fm.executePendingTransactions();
    }
    mapFragment.getMapAsync(callback);
}
Justin Breitfeller
źródło
4
Zobacz stackoverflow.com/questions/13733299/…, aby zapoznać się z przykładami tworzenia fragmentu mapy programowo i inicjowania mapy.
Kristopher Johnson
1
Zobacz także stackoverflow.com/questions/19239175/... w celu obejścia problemu widocznego błędu w obsłudze fragmentów potomnych.
Kristopher Johnson
Napotkałem ten problem 4.3podczas korzystania ze SupportMapFragmentzdefiniowanego w XML. Dynamiczne utworzenie fragmentu i wstrzyknięcie go do widoku kontenera rozwiązało problem. Zobacz tę SO odpowiedź .
theblang
Bardzo przydatna odpowiedź. Jak możemy wywołać funkcję zwrotną do głównej funkcji onCreate ()?
Utopia,
2
Zgodnie z dokumentem, użyj SupportMapFragment.newInstance(); developers.google.com/maps/documentation/android-api/map
Jemshit Iskenderov
178

Miałem ten sam problem i udało się go rozwiązać poprzez ręczne usunięcie MapFragmentw onDestroy()sposobie Fragmentklasie. Oto kod, który działa i odwołuje się MapFragmentdo identyfikatora w pliku XML:

@Override
public void onDestroyView() {
    super.onDestroyView();
    MapFragment f = (MapFragment) getFragmentManager()
                                         .findFragmentById(R.id.map);
    if (f != null) 
        getFragmentManager().beginTransaction().remove(f).commit();
}

Jeśli nie usuniesz MapFragmentręcznie, zostanie on zawieszony, aby odtworzenie / pokazanie widoku mapy nie kosztowało dużo zasobów. Wygląda na to, że zachowanie bazy MapViewjest świetne do przełączania się między kartami, ale gdy jest używane we fragmentach, takie zachowanie powoduje tworzenie duplikatu MapViewprzy każdym nowym MapFragmento tym samym ID. Rozwiązaniem jest ręczne usunięcie, MapFragmenta tym samym odtworzenie podstawowej mapy za każdym razem, gdy fragment zostanie napompowany.

Zauważyłem to również w innej odpowiedzi [ 1 ].

Matt
źródło
Powoduje awarię aplikacji po kliknięciu przycisku strony głównej urządzenia z opcją „Nie zachowuj aktywności” w opcjach programisty.
lipiec
24
to działa, ale jeśli obrócę ekran, moja aplikacja ulega awarii z tym wyjątkiem: Przyczyna: java.lang.IllegalStateException: Nie można wykonać tej akcji po onSaveInstanceState
jramoyo 15.08.13
1
Dla tych, którzy mogą być zainteresowani, możesz wyeliminować wyjątek spowodowany obrotem ekranu, przechowując orientację początkową w konstruktorze fragmentu i wywołując powyższą transakcję tylko wtedy, gdy orientacja NIE została zmieniona. Jeśli został zmieniony, nie trzeba walczyć z duplikatem identyfikatora, ponieważ nie ma go, gdy widok jest tworzony od nowa po rotacji. Mogę edytować odpowiedź i podać fragment kodu, jeśli Matt nie ma nic przeciwko.
Stan
1
Hmm dla mnie fragment mapy nie jest usuwany. Muszę robić coś źle, ale jeśli wywołam getActivity (). GetSupportFragmentManager (). GetFragments (), fragment pozostaje po wywołaniu remove (f) .commit. Czy ktoś ma pojęcie dlaczego? (Wymieniłem getFragManager na getSupportFragManager)
Daniel Wilson
10
commitAllowingStateLoss uniknie wyjątku IllegalStateException.
Héctor Júdez Sapena
22

Oto moja odpowiedź:

1, Utwórz układ xml w następujący sposób:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>

2, w klasie Fragment dodaj programowo mapę google.

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * A simple {@link android.support.v4.app.Fragment} subclass. Activities that
 * contain this fragment must implement the
 * {@link MapFragment.OnFragmentInteractionListener} interface to handle
 * interaction events. Use the {@link MapFragment#newInstance} factory method to
 * create an instance of this fragment.
 * 
 */
public class MapFragment extends Fragment {
    // TODO: Rename parameter arguments, choose names that match
    private GoogleMap mMap;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_map, container, false);
        SupportMapFragment mMapFragment = SupportMapFragment.newInstance();
        mMap = mMapFragment.getMap();
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        transaction.add(R.id.map_container, mMapFragment).commit();
        return view;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.d("Attach", "on attach");
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }
} 
Zou
źródło
2
mMapFragment.getMap();zwraca null. Masz pomysł, dlaczego?
Anas Azeem,
@AnasAzeem, tworzenie fragmentu programowo dokładnie rozwiązuje problem, nie musisz mieć mMapy dla rozwiązania, być może w twoim przypadku.
takildal
@AnasAzeem powinieneś użyć getMapAsync, który zwróci poprawnie instancję mapy po zainicjowaniu (w tle). Jest to „poprawny” sposób pracy z mapami Google i nie ma nic wspólnego z fragmentami
Ganesh Krishnan
10
  1. Jak wspomniał @Justin Breitfeller, rozwiązanie @Vidar Wahlberg to włamanie, które może nie działać w przyszłej wersji Androida.
  2. @Vidar Wahlberg wykonuje hack, ponieważ inne rozwiązanie może „spowodować, że mapa zostanie odtworzona i przerysowana, co nie zawsze jest pożądane”. Przerysowaniu mapy można zapobiec, zachowując stary fragment mapy, zamiast tworzyć nowe wystąpienie za każdym razem.
  3. Rozwiązanie @Matt nie działa dla mnie (wyjątek IllegalStateException)
  4. Jak cytował @Justin Breitfeller: „Nie można nadmuchać układu do fragmentu, gdy zawiera on układ. Zagnieżdżone fragmenty są obsługiwane tylko wtedy, gdy są dynamicznie dodawane do fragmentu”.

Moje rozwiązanie:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,                              Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_map_list, container, false);

    // init
    //mapFragment = (SupportMapFragment)getChildFragmentManager().findFragmentById(R.id.map);
    // don't recreate fragment everytime ensure last map location/state are maintain
    if (mapFragment == null) {
        mapFragment = SupportMapFragment.newInstance();
        mapFragment.getMapAsync(this);
    }
    FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
    // R.id.map is a layout
    transaction.replace(R.id.map, mapFragment).commit();

    return view;
}
Desmond Lua
źródło
2
Dzięki @Desmond Twoje rozwiązanie działało dla mnie bezbłędnie. Jedyne, o czym musisz pamiętać, to NIE tworzyć mapy w układzie. Tworzenie mapy w tym rozwiązaniu jest osadzone w kodzie, więc zmień <fragment android: name = "com.google.android.gms.maps.SupportMapFragment"> na np. <LinearLayout id = "@ + id / map />
kosiara - Bartosz Kosarzycki,
7

Deklaruj obiekt SupportMapFragment globalnie

    private SupportMapFragment mapFragment;

W metodzie onCreateView () umieść poniższy kod

mapFragment = (SupportMapFragment) getChildFragmentManager()
            .findFragmentById(R.id.map);
 mapFragment.getMapAsync(this);

W onDestroyView () umieść poniżej kodu

@Override
public void onDestroyView() {
   super.onDestroyView();

    if (mapFragment != null)
        getFragmentManager().beginTransaction().remove(mapFragment).commit();
}

W swoim pliku xml umieść poniższy kod

 <fragment
    android:id="@+id/map"
    android:name="com.abc.Driver.fragment.FragmentHome"
    class="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

Powyższy kod rozwiązał mój problem i działa dobrze

Digvijay Machale
źródło
3

Polecam replace()raczej niż attach()/ detach()w obsłudze kart.

Lub zmień na ViewPager. Oto przykładowy projekt pokazujący ViewPager, z zakładkami, hosting 10 map.

CommonsWare
źródło
Ale zamień podać błąd outofmemry niż co należy zrobić, jeśli użyjemy okna odłączania, gdy wystąpi problem z mapą.
Programista Vishal Android
3

Inne rozwiązanie:

if (view == null) {
    view = inflater.inflate(R.layout.nearbyplaces, container, false);
}

To tyle, jeśli nie zero, nie trzeba go ponownie inicjować, usuwanie z elementu nadrzędnego jest niepotrzebnym krokiem.

AnonymousDev
źródło
To najlepsze rozwiązanie dla mojego przypadku. Otrzymałem ten błąd w wyniku użycia dwóch fragmentów dla mojego wykresu nawigacyjnego i to naprawiło mój problem.
Kennedy Kambo
To najlepsze rozwiązanie dla mojego przypadku. Otrzymałem ten błąd w wyniku użycia dwóch fragmentów dla mojego wykresu nawigacyjnego i to naprawiło mój problem.
Kennedy Kambo
2

Dziś straciłem godziny na znalezienie przyczyny, na szczęście ten problem nie wynika z implementacji MapFragment, niestety to nie działa, ponieważ zagnieżdżone fragmenty są obsługiwane tylko przez bibliotekę wsparcia z wersji 11.

Moja implementacja ma działanie z paskiem akcji (w trybie kart) z dwiema kartami (bez przeglądarki), jedna z mapą, a druga z listą wpisów. Oczywiście byłem dość naiwny, gdy korzystałem z MapFragment w moich fragmentach kart, i voila aplikacja ulegała awarii za każdym razem, gdy wracałem do mapy.

(Ten sam problem, który miałbym również w przypadku, gdyby mój fragment tabulatora nadmuchał jakikolwiek układ zawierający jakikolwiek inny fragment).

Jedną z opcji jest użycie MapView (zamiast MapFragment), jednak z pewnym narzutem (patrz Dokumenty MapView jako zamiennik drop-in w layout.xml, inną opcją jest użycie biblioteki pomocniczej w górę od wersji 11, ale następnie podejście programowe ponieważ zagnieżdżone fragmenty nie są obsługiwane przez układ lub po prostu programowo działają poprzez jawne zniszczenie fragmentu (jak w odpowiedzi Matt / Vidar), btw: ten sam efekt osiąga się przy użyciu MapView (opcja 1).

Ale tak naprawdę nie chciałem zgubić mapy za każdym razem, gdy odsuwam kartę, to znaczy chciałem zachować ją w pamięci i wyczyścić tylko po zamknięciu aktywności, więc postanowiłem po prostu ukryć / pokazać mapę podczas tabulacji, zobacz FragmentTransakcja / ukryj

chodź weź trochę
źródło
2

Dla tych, którzy wciąż napotykają ten problem, najlepszym sposobem, aby upewnić się, że nie pojawia się ten błąd z mapą w zakładce, jest wydłużenie fragmentu SupportMapFragmentzamiast zagnieżdżenia SupportMapFragmentwewnątrz fragmentu używanego na karcie.

Właśnie dostałem to za ViewPagerpomocą a FragmentPagerAdapter, z SupportMapFragment w trzeciej zakładce.

Oto ogólna struktura, zauważ, że nie ma potrzeby przesłonięcia onCreateView()metody i nie ma potrzeby pompowania żadnego xml układu:

public class MapTabFragment extends SupportMapFragment 
                                    implements OnMapReadyCallback {

    private GoogleMap mMap;
    private Marker marker;


    public MapTabFragment() {
    }

    @Override
    public void onResume() {
        super.onResume();

        setUpMapIfNeeded();
    }

    private void setUpMapIfNeeded() {

        if (mMap == null) {

            getMapAsync(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {

        mMap = googleMap;
        setUpMap();
    }

    private void setUpMap() {

        mMap.setMyLocationEnabled(true);
        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        mMap.getUiSettings().setMapToolbarEnabled(false);


        mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {

            @Override
            public void onMapClick(LatLng point) {

                //remove previously placed Marker
                if (marker != null) {
                    marker.remove();
                }

                //place marker where user just clicked
                marker = mMap.addMarker(new MarkerOptions().position(point).title("Marker")
                        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));

            }
        });

    }


}

Wynik:

wprowadź opis zdjęcia tutaj

Oto pełny kod klasy, którego użyłem do testowania, w tym fragment zastępczy Fragment użyty dla pierwszych dwóch Tab i Fragment mapy użyty dla trzeciej Tab:

public class MainActivity extends AppCompatActivity implements ActionBar.TabListener{


    SectionsPagerAdapter mSectionsPagerAdapter;

    ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        final ActionBar actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                actionBar.setSelectedNavigationItem(position);
            }
        });

        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
        }

    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
        mViewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {

    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {

    }


    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    return PlaceholderFragment.newInstance(position + 1);
                case 1:
                    return PlaceholderFragment.newInstance(position + 1);
                case 2:
                    return MapTabFragment.newInstance(position + 1);
            }

            return null;
        }

        @Override
        public int getCount() {
            // Show 3 total pages.
            return 3;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            Locale l = Locale.getDefault();

            switch (position) {
                case 0:
                    return getString(R.string.title_section1).toUpperCase(l);
                case 1:
                    return getString(R.string.title_section2).toUpperCase(l);
                case 2:
                    return getString(R.string.title_section3).toUpperCase(l);
            }
            return null;
        }
    }


    public static class PlaceholderFragment extends Fragment {

        private static final String ARG_SECTION_NUMBER = "section_number";

        TextView text;

        public static PlaceholderFragment newInstance(int sectionNumber) {
            PlaceholderFragment fragment = new PlaceholderFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            return fragment;
        }

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);

            text = (TextView) rootView.findViewById(R.id.section_label);
            text.setText("placeholder");

            return rootView;
        }
    }

    public static class MapTabFragment extends SupportMapFragment implements
            OnMapReadyCallback {

        private static final String ARG_SECTION_NUMBER = "section_number";

        private GoogleMap mMap;
        private Marker marker;


        public static MapTabFragment newInstance(int sectionNumber) {
            MapTabFragment fragment = new MapTabFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            return fragment;
        }

        public MapTabFragment() {
        }

        @Override
        public void onResume() {
            super.onResume();

            Log.d("MyMap", "onResume");
            setUpMapIfNeeded();
        }

        private void setUpMapIfNeeded() {

            if (mMap == null) {

                Log.d("MyMap", "setUpMapIfNeeded");

                getMapAsync(this);
            }
        }

        @Override
        public void onMapReady(GoogleMap googleMap) {
            Log.d("MyMap", "onMapReady");
            mMap = googleMap;
            setUpMap();
        }

        private void setUpMap() {

            mMap.setMyLocationEnabled(true);
            mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
            mMap.getUiSettings().setMapToolbarEnabled(false);


            mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {

                @Override
                public void onMapClick(LatLng point) {

                    Log.d("MyMap", "MapClick");

                    //remove previously placed Marker
                    if (marker != null) {
                        marker.remove();
                    }

                    //place marker where user just clicked
                    marker = mMap.addMarker(new MarkerOptions().position(point).title("Marker")
                            .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));

                    Log.d("MyMap", "MapClick After Add Marker");

                }
            });

        }
    }
}
Daniel Nugent
źródło
2

Szanuję wszystkie odpowiedzi, ale znalazłem jedno rozwiązanie liniowe: Jeśli n to liczba zakładek, to:

 mViewPager.setOffscreenPageLimit(n);

Przykład: w przypadku wspomnianym:

 mViewPager.setOffscreenPageLimit(2);

Pager widoku implementuje kolejkę, więc nie musisz pozwalać jej usuwać tego fragmentu. onCreateView jest wywoływany tylko raz.

Jayant Arora
źródło
1

Zwracasz lub nadmuchujesz układ dwukrotnie, po prostu sprawdź, czy napompujesz tylko raz.

Mahdi Giveie
źródło
0

Czy próbowałeś odwołać się do swojej MapFragmentklasy niestandardowej w pliku układu?

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <fragment
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mapFragment"
        android:name="com.nfc.demo.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
JJD
źródło
czy możesz napisać kod niestandardowego fragmentu mapy com.nfc.demo.MapFragment
Mina Fawzy
Nie jestem autorem kodu - właśnie użyłem kodu, o którym mowa. Musisz zapytać hermanna.
JJD
0

Jeśli użyjesz tylko odpowiedzi Vidara Wahlberga, podczas otwierania innej aktywności (na przykład) i powrotu do mapy pojawi się błąd. Lub w moim przypadku otwórz inną aktywność, a następnie z nowej aktywności ponownie otwórz mapę (bez użycia przycisku Wstecz). Ale kiedy połączysz rozwiązanie Vidar Wahlberg i rozwiązanie Matt, nie będziesz mieć wyjątków.

układ

<com.example.ui.layout.MapWrapperLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/map_relative_layout">

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/root">

        <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.SupportMapFragment" />
    </RelativeLayout>
</<com.example.ui.layout.MapWrapperLayout>

Fragment

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    setHasOptionsMenu(true);
    if (view != null) {
        ViewGroup parent = (ViewGroup) view.getParent();
        if (parent != null){
            parent.removeView(view);
        }
    }
    try {
        view = inflater.inflate(R.layout.map_view, null);
        if(view!=null){
            ViewGroup root = (ViewGroup) view.findViewById(R.id.root);
...

@Override
public void onDestroyView() {
    super.onDestroyView();
    Fragment fragment = this.getSherlockActivity().getSupportFragmentManager().findFragmentById(R.id.map);
    if (fragment != null)
        getFragmentManager().beginTransaction().remove(fragment).commit();
}
Vlad Hudnitsky
źródło
0

Miałem to w viewPager, a awaria spowodowana była tym, że każdy fragment musiał mieć własny tag, duplikaty tagów lub identyfikatory dla tego samego fragmentu nie są dozwolone.

użytkownik1396018
źródło
0

Myślę, że było kilka błędów w poprzedniej wersji biblioteki App-Compat dla Fragmentu potomnego. Próbowałem @Vidar Wahlberg i @ Matt, że nie działały dla mnie. Po zaktualizowaniu biblioteki appcompat mój kod działa idealnie bez żadnego dodatkowego wysiłku.

maddy d
źródło
0

Należy zwrócić uwagę na to, że aplikacja ulegnie awarii w jednym z dwóch przypadków: -

1) Aby ponownie użyć fragmentu z Mapami, fragment MapView musi zostać usunięty, gdy fragment pokazujący Mapy został zastąpiony innym fragmentem w wywołaniu zwrotnym onDestroyView.

w przeciwnym razie przy próbie dwukrotnego napompowania tego samego fragmentu wystąpi zduplikowany identyfikator, tag null lub identyfikator nadrzędny z innym fragmentem dla com.google.android.gms.maps.MapFragment .

2) Po drugie, nie wolno mieszać operacji app.Fragment z operacjami API.support.v4.app.Fragment API, np. Nie należy używać android.app.FragmentTransaction do usunięcia v4.app.Fragment typu MapView Fragment. Mieszanie tego ponownie spowoduje awarię od strony fragmentu.

Oto przykładowy fragment kodu do prawidłowego korzystania z MapView

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.serveroverload.yago.R;

/**
 * @author 663918
 *
 */
public class HomeFragment extends Fragment implements LocationListener {
    // Class to do operations on the Map
    GoogleMap googleMap;
    private LocationManager locationManager;

    public static Fragment newInstance() {
        return new HomeFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.home_fragment, container, false);
        Bundle bdl = getArguments();

        // setuping locatiomanager to perfrom location related operations
        locationManager = (LocationManager) getActivity().getSystemService(
                Context.LOCATION_SERVICE);

        // Requesting locationmanager for location updates
        locationManager.requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER, 1, 1, this);

        // To get map from MapFragment from layout
        googleMap = ((MapFragment) getActivity().getFragmentManager()
                .findFragmentById(R.id.map)).getMap();

        // To change the map type to Satellite
        // googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);

        // To show our current location in the map with dot
        // googleMap.setMyLocationEnabled(true);

        // To listen action whenever we click on the map
        googleMap.setOnMapClickListener(new OnMapClickListener() {

            @Override
            public void onMapClick(LatLng latLng) {
                /*
                 * LatLng:Class will give us selected position lattigude and
                 * longitude values
                 */
                Toast.makeText(getActivity(), latLng.toString(),
                        Toast.LENGTH_LONG).show();
            }
        });

        changeMapMode(2);

        // googleMap.setSatellite(true);
        googleMap.setTrafficEnabled(true);
        googleMap.setBuildingsEnabled(true);
        googleMap.setMyLocationEnabled(true);

        return v;
    }

    private void doZoom() {
        if (googleMap != null) {
            googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
                    new LatLng(18.520430, 73.856744), 17));
        }
    }

    private void changeMapMode(int mapMode) {

        if (googleMap != null) {
            switch (mapMode) {
            case 0:
                googleMap.setMapType(GoogleMap.MAP_TYPE_NONE);
                break;

            case 1:
                googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                break;

            case 2:
                googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
                break;

            case 3:
                googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
                break;

            case 4:
                googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                break;

            default:
                break;
            }
        }
    }

    private void createMarker(double latitude, double longitude) {
        // double latitude = 17.385044;
        // double longitude = 78.486671;

        // lets place some 10 random markers
        for (int i = 0; i < 10; i++) {
            // random latitude and logitude
            double[] randomLocation = createRandLocation(latitude, longitude);

            // Adding a marker
            MarkerOptions marker = new MarkerOptions().position(
                    new LatLng(randomLocation[0], randomLocation[1])).title(
                    "Hello Maps " + i);

            Log.e("Random", "> " + randomLocation[0] + ", " + randomLocation[1]);

            // changing marker color
            if (i == 0)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_AZURE));
            if (i == 1)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
            if (i == 2)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_CYAN));
            if (i == 3)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
            if (i == 4)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
            if (i == 5)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_ORANGE));
            if (i == 6)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_RED));
            if (i == 7)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
            if (i == 8)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_VIOLET));
            if (i == 9)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_YELLOW));

            googleMap.addMarker(marker);

            // Move the camera to last position with a zoom level
            if (i == 9) {
                CameraPosition cameraPosition = new CameraPosition.Builder()
                        .target(new LatLng(randomLocation[0], randomLocation[1]))
                        .zoom(15).build();

                googleMap.animateCamera(CameraUpdateFactory
                        .newCameraPosition(cameraPosition));
            }
        }

    }

    /*
     * creating random postion around a location for testing purpose only
     */
    private double[] createRandLocation(double latitude, double longitude) {

        return new double[] { latitude + ((Math.random() - 0.5) / 500),
                longitude + ((Math.random() - 0.5) / 500),
                150 + ((Math.random() - 0.5) * 10) };
    }

    @Override
    public void onLocationChanged(Location location) {

        if (null != googleMap) {
            // To get lattitude value from location object
            double latti = location.getLatitude();
            // To get longitude value from location object
            double longi = location.getLongitude();

            // To hold lattitude and longitude values
            LatLng position = new LatLng(latti, longi);

            createMarker(latti, longi);

            // Creating object to pass our current location to the map
            MarkerOptions markerOptions = new MarkerOptions();
            // To store current location in the markeroptions object
            markerOptions.position(position);

            // Zooming to our current location with zoom level 17.0f
            googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(position,
                    17f));

            // adding markeroptions class object to the map to show our current
            // location in the map with help of default marker
            googleMap.addMarker(markerOptions);
        }

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onProviderEnabled(String provider) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onProviderDisabled(String provider) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onDestroyView() {
        // TODO Auto-generated method stub
        super.onDestroyView();

        locationManager.removeUpdates(this);

        android.app.Fragment fragment = getActivity().getFragmentManager()
                .findFragmentById(R.id.map);
        if (null != fragment) {
            android.app.FragmentTransaction ft = getActivity()
                    .getFragmentManager().beginTransaction();
            ft.remove(fragment);
            ft.commit();
        }
    }

}

XML

 <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
       />

Wynik wygląda następująco: -wprowadź opis zdjęcia tutaj

Mam nadzieję, że to komuś pomoże.

Hitesh Sahu
źródło
0

W tym rozwiązaniu nie trzeba brać zmiennej statycznej;

Button nextBtn;

private SupportMapFragment mMapFragment;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);

    if (mRootView != null) {
        ViewGroup parent = (ViewGroup) mRootView.getParent();
        Utility.log(0,"removeView","mRootView not NULL");
        if (parent != null) {
            Utility.log(0, "removeView", "view removeViewed");
            parent.removeAllViews();
        }
    }
    else {
        try {
            mRootView = inflater.inflate(R.layout.dummy_fragment_layout_one, container, false);//
        } catch (InflateException e) {
    /* map is already there, just return view as it is  */
            e.printStackTrace();
        }
    }

    return  mRootView;
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    FragmentManager fm = getChildFragmentManager();
    SupportMapFragment mapFragment = (SupportMapFragment) fm.findFragmentById(R.id.mapView);
    if (mapFragment == null) {
        mapFragment = new SupportMapFragment();
        FragmentTransaction ft = fm.beginTransaction();
        ft.add(R.id.mapView, mapFragment, "mapFragment");
        ft.commit();
        fm.executePendingTransactions();
    }
    //mapFragment.getMapAsync(this);
    nextBtn = (Button) view.findViewById(R.id.nextBtn);
    nextBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Utility.replaceSupportFragment(getActivity(),R.id.dummyFragment,dummyFragment_2.class.getSimpleName(),null,new dummyFragment_2());
        }
    });

}`
Lalit Kumar
źródło
0

Jestem trochę spóźniony na przyjęcie, ale brak odpowiedzi pomógł mi w moim przypadku. Używałem mapy Google jako SupportMapFragment i PlaceAutocompleteFragment w moim fragmencie. Jak wszystkie odpowiedzi wskazywały na to, że problem polega na tym, że SupportMapFragment jest mapą do odtworzenia i przerysowania. Ale po wykopaniu dowiedziałem się, że mój problem był faktycznie z PlaceAutocompleteFragment

Oto więc skuteczne rozwiązanie dla tych, którzy napotykają ten problem z powodu SupportMapFragment i SupportMapFragment

 //Global SupportMapFragment mapFragment;
 mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.mapFragment);
    FragmentManager fm = getChildFragmentManager();

    if (mapFragment == null) {
        mapFragment = SupportMapFragment.newInstance();
        fm.beginTransaction().replace(R.id.mapFragment, mapFragment).commit();
        fm.executePendingTransactions();
    }

    mapFragment.getMapAsync(this);

    //Global PlaceAutocompleteFragment autocompleteFragment;


    if (autocompleteFragment == null) {
        autocompleteFragment = (PlaceAutocompleteFragment) getActivity().getFragmentManager().findFragmentById(R.id.place_autoCompleteFragment);

    }

A w onDestroyView wyczyść SupportMapFragment i SupportMapFragment

@Override
public void onDestroyView() {
    super.onDestroyView();


    if (getActivity() != null) {
        Log.e("res","place dlted");
        android.app.FragmentManager fragmentManager = getActivity().getFragmentManager();
        android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.remove(autocompleteFragment);
        fragmentTransaction.commit(); 
       //Use commitAllowingStateLoss() if getting exception 

        autocompleteFragment = null;
    }


}
Ratul Bin Tazul
źródło
0

Spróbuj ustawić identyfikator (android: id = "@ + id / map_dialog") dla układu nadrzędnego mapView. Pracuje dla mnie.

Hieudev Develo
źródło
0

Każdy, kto tu teraz przychodzi i ma ten typ błędu podczas otwierania tego Dialoglub innego miejsca Fragmentw Miejscach Google AutocompleteSupportFragment, wypróbuj ten jeden wiersz (nie wiem, jak to bezpieczne, ale działa dla mnie):

autocompleteFragment.getFragmentManager().beginTransaction().remove(autocompleteFragment).commit();

zanim odrzucisz / zniszczysz swój fragment.

barnacle.m
źródło
-1
<?xml version="1.0" encoding="utf-8"?>

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
   android:layout_height="match_parent" >


<com.google.android.gms.maps.MapView
    android:id="@+id/mapview"
    android:layout_width="100dip"
    android:layout_height="100dip"
    android:layout_alignParentTop="true"
    android:layout_alignRight="@+id/textView1"
    android:layout_marginRight="15dp" >
</com.google.android.gms.maps.MapView>

Dlaczego nie wstawisz mapy za pomocą obiektu MapView zamiast MapFragment? Nie jestem pewien, czy są jakieś ograniczenia w MapView, chociaż uznałem to za pomocne.

Ankur Gautam
źródło
Przykro mi, ale dowiedziałem się, że jest to przestarzała poprzednia wersja interfejsu API Map Google
Ankur Gautam