ViewPager с Google Maps API v2: таинственный черный вид

95

Я интегрировал новый фрагмент api v2 карт Google в пейджер просмотра. При прокрутке от фрагмента карты черный вид перекрывает соседние фрагменты. Кто-то решил?

Изменить: скриншот

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

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 и реализации карты могут помочь лучше понять вашу проблему.
Адиния
Да, происходит на всех устройствах, которые я пробовал: 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
Джефф Гилфельт
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: Не могли бы вы опубликовать образец кода. Я получаю ошибку исключения нулевого указателя ..
Авинаш
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 У меня мерцает вид карты, есть ли способ решить эту проблему?
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 (фрагмент) под названием «registerFragments».

Таким образом, всякий раз, когда вы прокручиваете карту или с нее, вы всегда видите ее снимок. У меня это работает очень хорошо.

Наменлос
источник
Другие ответы у меня не сработали - это единственный, который сработал. Спасибо!
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);
            }
        });
JehandadK
источник
0

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

азиут
источник
Его можно дополнительно расширить, чтобы захватить текущее изображение View в растровое изображение, а затем отобразить его в 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();
}

}

user2728452
источник