ViewPager с Google Maps API v2: таинственный черный вид
Я интегрировал новый фрагмент карты Google Api v2 в пейджер просмотра. При прокрутке от фрагмента карты черный вид перекрывает соседние фрагменты. Кто-то решил?
Редактировать: скриншот
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;
}
}
9 ответов
Я смог остановить черную поверхность, оставшуюся после перехода, поместив другой вид с прозрачным фоном поверх 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>
Была такая же проблема с 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;
}
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);
}
}
}
}
Мой обходной путь: используйте новый интерфейс снимков из 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), который называется "зарегистрированный фрагмент".
Поэтому, когда вы прокручиваете карту на карту или с нее, вы всегда видите ее снимок. Это работает очень хорошо для меня.
У меня была та же проблема черного экрана при прокрутке представления списка, я использовал фрагмент карты с представлением списка на том же экране, я решил эту проблему с использованием магического свойства в xml, где я говорю в виде списка, просто мы должны поставить Android: scrollingCache = "false". Моя проблема устранена, попробуйте это свойство, чтобы перестать отставать и мерцать на ваших картах.
Вы не дали много подробностей, поэтому я могу предложить только так много. У меня была похожая проблема, что экран мерцал между представлениями в пейджере. Оказалось, что mapView раздувается при первом переключении страниц.
Чтобы было ясно, у меня было 3 страницы в моем пейджере, и моя карта была последней страницей.
Чтобы решить эту проблему, я обнаружил, что установив количество страниц за пределами экрана равным 2 (это работало в случае выше), чтобы при запуске моего фрагмента загружались все представления одновременно.
См. http://developer.android.com/reference/android/support/v4/view/ViewPager.html (int).
Ни один из вышеперечисленных методов не работал для меня, даже другие, которые я нашел в другом месте. Наконец, я выбрал частичное решение. Я слушаю изменения страницы с помощью onPageChangeListener ViewPager и скрываю карту, когда ее страница начинает прокручиваться, и также показываю ее снова, когда она перестает прокручиваться. Я также добавил белый вид, который будет отображаться при прокрутке.
Есть еще одно решение этой проблемы. Я показываю 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);
}
});
Просто скопируйте мой собственный фрагмент карты в ваш проект. И если у вас есть черные линии с ScrollView сверху и снизу, установленным на ваш Android ScrollView: 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();
}
}