ViewPager з Google Maps API v2: загадковий чорний вигляд


95

Я інтегрував новий фрагмент api v2 google maps у пейджер подання. Під час прокрутки з фрагмента карти чорний вигляд перекриває сусідні фрагменти. Хтось вирішив?

Редагувати: скріншот

введіть тут опис зображення

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

Чи трапляється це більше, ніж на одному пристрої? Можливо, кілька рядків коду від ViewPager та впровадження карти можуть допомогти краще зрозуміти вашу проблему.
Adinia

Так, це трапляється на всіх пристроях, які я пробував: samsung, htc, android 4.0, 2.3 та ін. Я інтегрував карту у свій додаток та у чистий маленький додаток лише з пейджером та картою, з однаковим результатом.
Пепе

@ Пепе, скажи, будь ласка, як ти отримуєш GoogleMapоб'єкт із ViewPager? Затримався на цьому тижнями. Якщо ви погано розумієте питання, знайдіть моє запитання, ви знайдете мій пост. Будь-ласка дайте відповідь.
azizbekian

Я хочу додати, що при виконанні screen recordпроблеми проблема, здається, не трапляється.
theblang

Відповіді:


115

Я зміг зупинити залишення чорної поверхні після переходу, розмістивши інший вигляд із прозорим фоном зверху ViewPagerвсередині 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>

1
Чудово! Це не ідеально, оскільки іноді під час руху пейджер з'являється частиною чорного виду. Але тепер це більше не залишається на екрані. Дякую! (у вас є якесь пояснення цьому рубанню?)
Пепе,

7
Не зовсім. Я щойно помітив, де елементи керування масштабуванням та розташуванням сиділи поверх поверхні карти, чорний слід не з’являвся, тому я розмістив вид зверху, щоб охопити всю карту, і це спрацювало. Я згоден, що це не ідеально - чорний фон, здається, є частиною вікна GLSurfaceView code.google.com/p/gmaps-api-issues/issues/detail?id=4639
Jeff Gilfelt

5
Здається, це виправило мою проблему з ViewPager. Дякую, але схоже, у мене є схожа проблема з SlideMenu (ліве меню, як G + / Yahoo), що робить те саме ... Будь-які думки щодо виправлення реалізації SlideMenu?
Chrispix

@Chrispix не анімує контейнер, використовуйте анімацію лише в бічному меню, це мені виправлено.
meh

1
Я зробив це та наведене нижче програмне рішення, вони працюють, поки програма знаходиться на передньому плані, але коли програма закрита і все ще працює, і ви повертаєтесь до неї, карта все ще залишається на вершині ..
L7ColWinters

43

Була та ж проблема з SlidingMenu та ViewPager. Я помітив, що кнопки керування у фрагменті карти не чорні в артефакті зліва. Я вирішив проблему, замінивши onCreateView()метод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;
}

Я також використовую його для SlidingMenu. Але у мене проблема мерехтіння (з ковзною анімацією), і це неприпустимо, виглядає жахливо. У вас теж є? Я тестував на HTC One S. Що цікаво, у мене це питання лише з початковою анімацією, а не при закритті SlidingMenu
Michał K

Жодне з виправлень у мене не спрацювало. У мене практично та ж проблема, що і у Міхала К. Використання SlidingMenu і повільне відкривання або закривання з постійною швидкістю, і проблем немає. Відкрийте вікно або натисніть назад, щоб закрити вікно, і схоже, карта трохи відстає, залишаючи порожній простір, поки слайд не закінчиться там, де карта повернеться у належне положення.
qubz

@qubz: Про "розсувне меню" спробуйте анімувати меню, а не карту. Це вирішило проблему для мене, якщо карта не рухається.
meh

@meh: Карта може рухатися, поки я відкриваю / закриваю SlidingMenu. Під рухом я маю на увазі CameraUpdate. Я подивлюсь, чи зможу я призупинити анімацію, хоча це буде заважати UX.
qubz

@Lubos Horacek: Не могли б ви опублікувати зразок коду. Я отримую помилку з винятком нульового покажчика ..
avinash

7

Google випустив це виправлення, але лише для версій 4.1+ (Вам не потрібно завантажувати нову версію PlayServices, вони використовували прапор на стороні сервера)

Ось те, що я використовую для обходу проблеми - гарантує, що ви не витрачаєте жоден цикл процесора на пристрої> = 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);
            }
        }
    }
}

Я припускаю , що ви посилаєтеся на клас наступним чином : FixMapFragment mapFragment = (FixMapFragment) fragmentManager.findFragmentById(R.id.map);і в файлі макета: <fragment android:id="@+id/map" android:name="com.example.fragments.FixMapFragment" .... Хоча, карта все ще мерехтить, наскільки я можу зрозуміти (Android 4.0.4).
JJD

@JJD у мене є mapview, який мерехтить, чи є спосіб це вирішити?
Rat-a-tat-a-tat Ratatouille

@ Rat-a-tat-a-tatRatatouille Не існує надійних обхідних шляхів, щоб уникнути мерехтіння вигляду карти, наскільки мені відомо.
JJD

я не знаю, чи те, що я зробив на даний момент, є правильним чи ні, але це працює. Я встановлюю видимість mapview на невидиму, а потім через кілька секунд встановлюю видимість mapviews назад на видиму. зменшує мерехтіння.
Rat-a-tat-a-tat Ratatouille

6

Моє обхідне рішення: скористайтеся новим інтерфейсом знімків від GoogleMap і покажіть знімок карти під час прокрутки сторінки.

Ось мій код для встановлення знімка (він знаходиться в тому ж фрагменті, що і карта, що називається 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;
    }
}

Де "mapFragment" - це мій SupportedMapFragment, а "iv" - ImageView (зробіть його match_parent).

І тут я керую прокруткою:

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

Мій фрагмент з картою (FragmentMap) знаходиться в позиції 1, тому мені потрібно керувати прокруткою з позиції 0 до 1 і з позиції 1 до 2 (перше речення if). "getRegisteredFragment ()" - це функція в моєму користувацькому FragmentPagerAdapter, в якій у мене є SparseArray (Fragment), який називається "registeredFragments".

Отже, кожного разу, коли ви прокручуєте карту або з неї, ви завжди бачите її знімок. Для мене це дуже добре працює.


Інші відповіді для мене не спрацювали - це єдиний, який спрацював. Дякую!
alice_silver_man

4

У мене була така ж проблема з чорним екраном при прокрутці перегляду списку, я використовував фрагмент карти з переглядом списку на тому ж екрані, я вирішив цю проблему за допомогою магічної властивості в xml, де я говорю про перегляд списку, просто ми повинні поставити android: scrollingCache = "false". моя помилка виправлена, спробуйте цю властивість, щоб припинити відставання та мерехтіння на ваших картах.


2

Ви не надали багато деталей, тому я можу запропонувати лише стільки. У мене була подібна проблема, коли екран переходив між переглядами на пейджері. Виявилося, що mapView надувається при першій обміні сторінками.

Щоб бути зрозумілим, у мене на пейджері було 3 сторінки, і моя карта була останньою.

Щоб вирішити це, я виявив, що встановлення кількості позаекранних сторінок до 2 (це спрацювало у випадку вище), що коли мій фрагмент запускався, він завантажував всі перегляди відразу.

Див. Http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit (int)


Спасибі, але не спрацювало. Проблема полягає в тому, що частина екрану, покрита картою, при переході на інший фрагмент залишається чорною, закриваючи вигляд цього іншого фрагмента.
Пепе

хммм цікаво. Я подумаю над цим.
Грехем Сміт

Я не можу знайти setOffscreenPageLimit на цій сторінці, до якої ви
посилалися

0

Існує ще одне рішення цієї проблеми. Я показую MapFragment в іншому фрагменті. MapFragment динамічно додається до FrameLayout.

Рішення полягає у використанні frameLayout.setVisibility (View.Visible) та frameLayout.setVisibility (View.Gone) для відкритих та закритих подій розсувного меню. Для цього не потрібно додати додатковий огляд. І чорна зона повністю зникла.

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

getSlidingMenu().setOnClosedListener(
        new OnClosedListener() {

            @Override
            public void onClosed() {
                frameLayout.setVisibility(View.VISIBLE);
            }
        });

0

Жоден із наведених вище методів не спрацював для мене, навіть інші, які я знайшов деінде. Нарешті, я вибрав часткове рішення. Я прослуховую зміни сторінок за допомогою onPageChangeListener ViewPager і приховую карту, коли її сторінка починає прокручуватися, і також показую її знову, коли вона перестає прокручуватися. Я також додав білий подання, яке відображатиметься під час прокрутки.


Його можна додатково розширити, щоб захопити поточне зображення подання у растрове зображення, а потім відобразити його на ImageView під час прокрутки пейджера. Таким чином, користувачі не помітили б хакерства. Однак, я знайшов це обчислення занадто дорогим, оскільки це уповільнило б реакцію інтерфейсу користувача на проведення.
azyoot

-2

Просто скопіюйте мій фрагмент власної карти у свій проект. І якщо у вас є чорні лінії зі ScrollView зверху та знизу, встановлені для вашого 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();
}

}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.