ViewPager z Google Maps API v2: tajemniczy czarny widok

95

Zintegrowałem nowy fragment google maps api v2 w pager widoku. Podczas przewijania z fragmentu mapy czarny widok zachodzi na sąsiednie fragmenty. Ktoś rozwiązał?

Edycja: zrzut ekranu

wprowadź opis obrazu tutaj

public static class PagerAdapter extends FragmentPagerAdapter{

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

    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    @Override
    public Fragment getItem(int position) {

        Fragment pageFragment;

        switch (position) {
        case 0:
            pageFragment = new TabAFragment();
            break;

        case 1:
            pageFragment = new TabBFragment();
            break;

        case 2:
            pageFragment = SupportMapFragment.newInstance();
            break;

        default:
            pageFragment = null;
            break;
        }

        return pageFragment;
    }
}
Pepe
źródło
Czy zdarza się, że jest więcej niż jedno urządzenie? Może kilka linii kodu z Twojego ViewPagera i implementacji mapy może pomóc w lepszym zrozumieniu problemu.
Adinia
Tak, dzieje się na wszystkich urządzeniach, które wypróbowałem: Samsung, HTC, Android 4.0, 2.3, itp. Zintegrowałem mapę w mojej aplikacji oraz w czystej, małej aplikacji z tylko pagerem i mapą, z tym samym wynikiem.
Pepe
@Pepe, czy mógłbyś powiedzieć, w jaki sposób otrzymujesz GoogleMapprzedmiot z ViewPager? Utknąłem w tym od tygodni. Jeśli nie zrozumiałeś dobrze pytania, spójrz na moje pytanie, znajdziesz mój post. Proszę odpowiedz.
azizbekian
Chcę dodać, że kiedy robienie screen recordproblemu wydaje się nie mieć miejsca.
theblang

Odpowiedzi:

115

Udało mi się zatrzymać pozostawienie czarnej powierzchni po przejściu, umieszczając inny widok z przezroczystym tłem na górze ViewPagerwewnątrz a FrameLayout:

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <android.support.v4.view.ViewPager
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </android.support.v4.view.ViewPager>

    <!-- hack to fix ugly black artefact with maps v2 -->
    <FrameLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent" 
        android:background="@android:color/transparent" />

</FrameLayout>
Jeff Gilfelt
źródło
1
Wspaniały! Nie jest to idealne, bo czasami podczas przesuwania pagera pojawia się część czarnego widoku. Ale teraz nie pozostaje już na ekranie. Dzięki! (czy masz jakieś wyjaśnienie tego włamania?)
Pepe,
7
Nie całkiem. Właśnie zauważyłem, gdzie elementy sterujące powiększeniem i lokalizacją znajdowały się na górze powierzchni mapy, czarny ślad się nie pojawił, więc umieściłem widok na górze, aby pokryć całą mapę i zadziałało. Zgadzam się, że nie jest idealne - czarne tło wydaje się być częścią okna GLSurfaceView code.google.com/p/gmaps-api-issues/issues/detail?id=4639
Jeff Gilfelt
5
Wygląda na to, że rozwiązało to mój problem z ViewPager. Dzięki, ale wygląda na to, że mam podobny problem z SlideMenu (lewe menu jak G + / Yahoo), robię to samo. Jakieś myśli o naprawieniu implementacji SlideMenu?
Chrispix,
@Chrispix nie animuje kontenera, użyj animacji tylko w bocznym menu, naprawił to za mnie.
meh
1
Zrobiłem to i poniższe rozwiązanie programistyczne, działają one, gdy aplikacja jest na pierwszym planie, ale kiedy aplikacja jest zamknięta i nadal działa, a ty wracasz do niej, mapa pozostaje nadal na górze ..
L7ColWinters
43

Miałem ten sam problem z SlidingMenu i ViewPager. Zauważyłem, że przyciski sterujące we fragmencie mapy nie są czarne w lewym artefakcie. Rozwiązałem problem, zastępując onCreateView()metodęMapFragment (SupportMapFragment)

@Override
public View onCreateView(LayoutInflater inflater, 
                         ViewGroup view, 
                         Bundle savedInstance) {

    View layout = super.onCreateView(inflater, view, savedInstance);
    FrameLayout frameLayout = new FrameLayout(getActivity());
    frameLayout.setBackgroundColor(
        getResources().getColor(android.R.color.transparent));
    ((ViewGroup) layout).addView(frameLayout,
        new ViewGroup.LayoutParams(
            LayoutParams.FILL_PARENT, 
            LayoutParams.FILL_PARENT
        )
    );
    return layout;
}
Lubos Horacek
źródło
Używam go też do SlidingMenu. Ale mam problem z migotaniem (z animacją przesuwania) i jest to niedopuszczalne, wygląda okropnie. Ty też to masz? Testowałem na HTC One S. Co ciekawe mam ten problem tylko z animacją otwierającą a nie z zamykaniem SlidingMenu
Michał K
Żadna z poprawek nie zadziałała dla mnie. Mam praktycznie ten sam problem co Michał K. Używając SlidingMenu i otwierając lub zamykając powoli z ciągłą prędkością i nie ma problemu. Otwórz lub naciśnij wstecz, aby zamknąć okno i wygląda na to, że mapa trochę się opóźnia, pozostawiając puste miejsce, dopóki slajd nie zakończy się, a mapa powróci do właściwej pozycji.
qubz
@qubz: Jeśli chodzi o „przesuwane menu”, spróbuj animować menu, a nie mapę. Rozwiązało to dla mnie problem, jeśli mapa się nie porusza.
meh
@meh: Mapa może się poruszać, gdy otwieram / zamykam SlidingMenu. Poruszając mam na myśli CameraUpdate. Zobaczę, czy uda mi się wstrzymać animację, chociaż to utrudni UX.
qubz
@Lubos Horacek: Czy mógłbyś przesłać przykładowy kod? Otrzymuję błąd wyjątku wskaźnika zerowego ..
avinash
7

Google wydało poprawkę, ale tylko dla 4.1+ (nie musisz pobierać nowej wersji PlayServices, użyli flagi po stronie serwera)

Oto, czego używam, aby ominąć ten problem - zapewnia, że ​​nie marnujesz żadnych cykli procesora na urządzeniach> = 4.1

public class FixMapFragment extends SupportMapFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, 
                             ViewGroup container, 
                             Bundle savedInstanceState) {

        View view = super.onCreateView(inflater, container, savedInstanceState);

        // Fix for black background on devices < 4.1
        if (android.os.Build.VERSION.SDK_INT < 
            android.os.Build.VERSION_CODES.JELLY_BEAN) {
            setMapTransparent((ViewGroup) view);
        }
        return view;
    }

    private void setMapTransparent(ViewGroup group) {
        int childCount = group.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = group.getChildAt(i);
            if (child instanceof ViewGroup) {
                setMapTransparent((ViewGroup) child);
            } else if (child instanceof SurfaceView) {
                child.setBackgroundColor(0x00000000);
            }
        }
    }
}
Łyżka
źródło
Chyba odwołać klasę w następujący sposób: FixMapFragment mapFragment = (FixMapFragment) fragmentManager.findFragmentById(R.id.map);w pliku layoutu: <fragment android:id="@+id/map" android:name="com.example.fragments.FixMapFragment" .... Chociaż mapa nadal migocze, o ile wiem (Android 4.0.4).
JJD
@JJD Mam migający widok mapy, czy istnieje sposób na rozwiązanie tego problemu?
Rat-a-tat-a-tat Ratatouille
@ Rat-a-tat-a-tatRatatouille O ile wiem, nie ma niezawodnego obejścia, które pozwoliłoby uniknąć migotania widoku mapy.
JJD
nie wiem, czy to, co zrobiłem, jest poprawne, czy nie, ale działa. ustawiłem widoczność widoku mapy na niewidoczną, a po kilku sekundach ponownie ustawiłem widoczność widoków mapy na widoczną. zmniejsza migotanie.
Rat-a-tat-a-tat Ratatouille
6

Moje obejście: skorzystaj z nowego interfejsu migawki z GoogleMap i wyświetl migawkę mapy podczas przewijania strony.

Oto mój kod do ustawiania migawki (znajduje się w tym samym fragmencie co mapa, o nazwie FragmentMap.java):

public void setSnapshot(int visibility) {
    switch(visibility) {
    case View.GONE:
        if(mapFragment.getView().getVisibility() == View.VISIBLE) {
            getMap().snapshot(new SnapshotReadyCallback() {
                @Override
                public void onSnapshotReady(Bitmap arg0) {
                    iv.setImageBitmap(arg0);
                }
            });
            iv.setVisibility(View.VISIBLE);
            mapFragment.getView().setVisibility(View.GONE);
        }
        break;
    case View.VISIBLE:
        if(mapFragment.getView().getVisibility() == View.GONE) {
            mapFragment.getView().setVisibility(View.VISIBLE);
            iv.setVisibility(View.GONE);
        }
        break;
    }
}

Gdzie „mapFragment” to mój SupportedMapFragment, a „iv” to ImageView (ustaw go jako match_parent).

I tutaj kontroluję zwoje:

pager.setOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if(position == 0 && positionOffsetPixels > 0 || position == 1 && positionOffsetPixels > 0) {
                ((FragmentMap)adapter.getRegisteredFragment(1)).setSnapshot(View.GONE);
            } else if(position == 1 && positionOffsetPixels == 0) {
                ((FragmentMap)adapter.getRegisteredFragment(1)).setSnapshot(View.VISIBLE);
            }
        }
        @Override
        public void onPageScrollStateChanged(int arg0) {}
        @Override
        public void onPageSelected(int arg0) {}
    });

Mój fragment z mapą (FragmentMap) znajduje się na pozycji 1, więc muszę kontrolować przewijanie od pozycji 0 do 1 i od pozycji 1 do 2 (pierwsza klauzula if). „getRegisteredFragment ()” to funkcja w moim niestandardowym FragmentPagerAdapter, w której mam SparseArray (Fragment) o nazwie „registeredFragments”.

Tak więc za każdym razem, gdy przewijasz do lub z mapy, zawsze widzisz jej migawkę. U mnie to działa bardzo dobrze.

Namenlos
źródło
Inne odpowiedzi nie działały dla mnie - to jedyna, która zadziałała. Dzięki!
alice_silver_man
4

Miałem ten sam problem z czarnym ekranem przy przewijaniu widoku listy, użyłem fragmentu mapy z widokiem listy na tym samym ekranie, rozwiązałem ten problem z użyciem magicznej właściwości w xml, gdzie mówię o widoku listy, tylko musimy umieścić androida: scrollingCache = "false". mój problem został rozwiązany. Wypróbuj tę właściwość, aby zatrzymać opóźnienia i migotanie na mapach.


źródło
2

Nie podałeś zbyt wielu szczegółów, więc mogę tylko zasugerować. Miałem podobny problem, że ekran migotał między widokami na pagerze. Okazało się, że mapView napompował się podczas pierwszej zamiany stron.

Dla jasności miałem 3 strony na moim pagerze, a moja mapa była ostatnią stroną.

Aby rozwiązać ten problem, stwierdziłem, że ustawiając liczbę stron poza ekranem na 2 (zadziałało to w powyższym przypadku), że kiedy mój fragment zaczął się, ładował wszystkie widoki naraz.

Zobacz http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit (int)

Graham Smith
źródło
Dzięki, ale nie udało się. Problem w tym, że część ekranu pokryta mapą po przejściu na inny fragment pozostaje czarna, zasłaniając widok tego innego fragmentu.
Pepe
hmmm interesujące. Przemyślę to.
Graham Smith
Nie mogę znaleźć setOffscreenPageLimit na tej stronie, do której prowadzi link
mplungjan
0

Jest jeszcze jedno rozwiązanie tego problemu. Pokazuję MapFragment w innym fragmencie. MapFragment jest dynamicznie dodawany do FrameLayout.

Rozwiązaniem jest użycie frameLayout.setVisibility (View.Visible) i frameLayout.setVisibility (View.Gone) do otwierania i zamykania zdarzeń menu przesuwanego. Nie wymaga to dodatkowego widoku. A czarny obszar całkowicie zniknął.

getSlidingMenu().setOnOpenListener(
        new OnOpenListener() {
            @Override
            public void onOpen() {
                frameLayout.setVisibility(View.GONE);
            }
        });

getSlidingMenu().setOnClosedListener(
        new OnClosedListener() {

            @Override
            public void onClosed() {
                frameLayout.setVisibility(View.VISIBLE);
            }
        });
JehandadK
źródło
0

Żadna z powyższych metod nie działała dla mnie, nawet inne, które znalazłem gdzie indziej. Wreszcie wybrałem częściowe rozwiązanie. Nasłuchuję zmian na stronie za pośrednictwem narzędzia onPageChangeListener ViewPagera i ukrywam mapę, gdy jej strona zaczyna się przewijać, i podobnie pokazuję ją ponownie, gdy przestaje się przewijać. Dodałem również biały widok, który ma być wyświetlany podczas przewijania.

azyoot
źródło
Można go dodatkowo rozszerzyć, aby przechwytywać bieżący obraz widoku do mapy bitowej, a następnie wyświetlać go w ImageView podczas przewijania pagera. W ten sposób użytkownicy nie zauważyliby włamania za tym. Jednak okazało się, że to obliczenie jest trochę za drogie, ponieważ spowolniłoby reakcję interfejsu użytkownika na przesuwanie.
azyoot
-2

Po prostu skopiuj mój niestandardowy fragment mapy do swojego projektu. A jeśli masz czarne linie z ScrollView na górze i na dole ustawionym na ScrollView android: fadingEdge = "none"

public class CustomMapFragment extends SupportMapFragment {
private OnActivityCreatedListener onActivityCreatedListener;

public CustomMapFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup view, Bundle savedInstance) {
    View layout = super.onCreateView(inflater, view, savedInstance);

    FrameLayout frameLayout = new FrameLayout(getActivity());
    frameLayout.setBackgroundColor(getResources().getColor(android.R.color.transparent));
    ((ViewGroup) layout).addView(frameLayout,
            new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    return layout;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (getOnActivityCreatedListener() != null)
        getOnActivityCreatedListener().onCreated();
}

public OnActivityCreatedListener getOnActivityCreatedListener() {
    return onActivityCreatedListener;
}

public void setOnActivityCreatedListener(
        OnActivityCreatedListener onActivityCreatedListener) {
    this.onActivityCreatedListener = onActivityCreatedListener;
}

public interface OnActivityCreatedListener {
    void onCreated();
}

}

user2728452
źródło