【问题标题】:ViewPager with Google Maps API v2: mysterious black view带有 Google Maps API v2 的 ViewPager:神秘的黑色视图
【发布时间】:2012-11-30 00:51:03
【问题描述】:

我已在视图寻呼机中集成了新的 google maps 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;
    }
}

【问题讨论】:

  • 它发生在多台设备上吗?也许您 ViewPager 和地图实现中的几行代码可能有助于更好地理解您的问题。
  • 是的,发生在我尝试过的所有设备上:samsung、htc、android 4.0、2.3 等。我已将地图集成到我的应用程序中,并且在一个只有寻呼机和地图的干净小应用程序中,结果相同。
  • @Pepe,请您说一下,您是如何从ViewPager 中获得GoogleMap 对象的?坚持了几个星期。如果你没有很好地理解问题,那么查看我的问题,你会找到我的帖子。请回复。
  • 我想补充一点,在执行screen record 时,问题似乎没有发生。

标签: android google-maps android-viewpager


【解决方案1】:

通过在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>

【讨论】:

  • 太棒了!这并不完美,因为有时在移动寻呼机时会出现部分黑色视图。但现在它不再留在屏幕上。谢谢! (你对这个黑客有什么解释吗?)
  • 并非如此。我只是注意到缩放和位置控件位于地图表面顶部的位置,黑色轨迹没有出现,所以我在顶部放置了一个视图以覆盖整个地图并且它起作用了。我同意它并不完美 - 黑色背景似乎是 GLSurfaceView 窗口的一部分 code.google.com/p/gmaps-api-issues/issues/detail?id=4639
  • 似乎解决了我的 ViewPager 问题。谢谢,但看起来我在使用 SlideMenu(左侧菜单,如 G+/Yahoo)时遇到了类似的问题,正在做同样的事情。关于修复 SlideMenu 实现的任何想法?
  • @Chrispix 不要为容器设置动画,仅在侧边菜单上使用动画,它为我修复了它。
  • 我已经完成了这个和下面的编程解决方案,它们在应用程序处于前台时工作,但是当应用程序关闭并仍在运行并且您返回它时,地图仍然保持在顶部..
【解决方案2】:

SlidingMenu 和 ViewPager 也有同样的问题。我注意到地图片段中的控制按钮在左侧工件中不是黑色的。 我通过覆盖MapFragment (SupportMapFragment)onCreateView()方法解决了这个问题

@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 时没有
  • 没有一个修复对我有用。我和 Michal K 几乎有同样的问题。使用 SlidingMenu 并以连续速度缓慢打开或关闭,没有问题。打开或按回以关闭窗口,看起来地图有点滞后,留下一个空白区域,直到幻灯片完成,地图返回到正确位置。
  • @qubz:关于“滑动菜单”,请尝试为菜单设置动画,而不是地图。如果地图没有移动,它为我解决了问题。
  • @meh:当我打开/关闭 SlidingMenu 时,地图可能正在移动。移动是指CameraUpdate。我会看看我是否可以暂停动画,但这会阻碍用户体验。
  • @Lubos Horacek :您能否发布一个示例代码。我收到空指针异常错误..
【解决方案3】:

Google 对此发布了修复,但仅适用于 4.1+(您无需下载新版本的 PlayServices,他们使用了服务器端标志)

这是我用来绕过该问题的方法 - 确保您不会在设备上浪费任何 CPU 周期 >= 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);,在布局文件中:&lt;fragment android:id="@+id/map" android:name="com.example.fragments.FixMapFragment" ...。不过,据我所知,地图仍在闪烁(Android 4.0.4)。
  • @JJD 我有一个闪烁的地图视图,有没有办法解决这个问题?
  • @Rat-a-tat-a-tatRatatouille 据我所知,没有可靠的解决方法来避免地图视图的闪烁。
  • 我不知道我现在所做的是否正确,但它确实有效。我将地图视图的可见性设置为不可见,然后在几秒钟后将地图视图的可见性设置回可见。减少闪烁。
【解决方案4】:

我的解决方法:使用新的snapshot interface from 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 中的一个函数,其中我有一个名为“registeredFragments”的 SparseArray(Fragment)。

因此,无论何时滚动到地图或从地图滚动,您总会看到它的快照。这对我来说效果很好。

【讨论】:

  • 其他答案对我不起作用 - 这是唯一起作用的答案。谢谢!
【解决方案5】:

我在滚动列表视图时遇到了同样的黑屏问题,我在同一屏幕中使用带有列表视图的地图片段我已经通过使用我所在的神奇属性 in xml 解决了这个问题谈话列表视图只是我们必须放 android:scrollingCache="false"。我的问题已修复尝试使用此属性来停止地图中的滞后和闪烁。

【讨论】:

    【解决方案6】:

    你没有提供太多细节,所以我只能建议这么多。我有一个类似的问题,即屏幕在寻呼机的视图之间闪烁。第一次在页面之间交换时,原来是 mapView 膨胀。

    需要明确的是,我的寻呼机中有 3 页,而我的地图是最后一页。

    为了解决这个问题,我发现将屏幕外页面的数量设置为 2(这在上述情况下有效),当我的片段启动时它会立即加载所有视图。

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

    【讨论】:

    • 谢谢,但没用。问题是地图覆盖的屏幕部分,当切换到其他fragment时,仍然是黑色的,覆盖了其他fragment的视图。
    • 嗯,很有趣。我会考虑一下。
    • 我在你链接到的那个页面上找不到 setOffscreenPageLimit
    【解决方案7】:

    这个问题还有另一种解决方案。我在另一个片段中显示 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);
                }
            });
    

    【讨论】:

      【解决方案8】:

      以上方法都不适合我,甚至我在别处找到的其他方法也不适合。最后,我选择了部分解决方案。 我通过 ViewPager 的 onPageChangeListener 监听页面更改,并在其页面开始滚动时隐藏地图,并在停止滚动时再次显示它。我还添加了一个在滚动时显示的白色视图。

      【讨论】:

      • 它可以进一步扩展为将View的当前图像捕获为位图,然后在寻呼机滚动时将其显示在ImageView上。这样,用户就不会注意到它背后的黑客行为。但是,我发现这种计算有点过于昂贵,因为它会减慢 UI 对滑动的响应。
      【解决方案9】:

      只需将my custom map fragment 复制到您的项目中即可。 如果您在顶部和底部设置了带有 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();
      }
      

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-06
        • 1970-01-01
        相关资源
        最近更新 更多