Android ActionBar 第一次用 Google Map 加载 Fragment 时变黑

标签 android google-maps android-fragments android-actionbar google-maps-android-api-2

我在创建 DrawerLayout 的 Activity 中,在侧面菜单中有 5 个条目,每个菜单条目都在加载其 fragment (在下面的代码中,您只会看到 3 个 fragment ,这是因为最后两个菜单条目目前是虚拟的)。在那个 Activity 上,我设置了我的自定义 ActionBar。 Activity 及其 onCreate 方法看起来像这样:

public class ActivityOffline extends ActionBarActivity implements OnPreferencesFragmentListener {
    final String[] fragments = { array with fragments path };

    private String[] drawerListViewItems;
    private DrawerLayout drawerLayout;
    private ListView drawerListView;
    private ActionBarDrawerToggle actionBarDrawerToggle;

    private Fragment mF1
    private Fragment mF2
    private Fragment mF3

    @SuppressLint("InlinedApi")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
        setContentView(R.layout.activity_offline);

        mF1 = Fragment.instantiate(ActivityOffline.this, fragments[0]);
        mF2 = Fragment.instantiate(ActivityOffline.this, fragments[1]);
        mF3 = Fragment.instantiate(ActivityOffline.this, fragments[2]);

        LayoutInflater inflator = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View v = inflator.inflate(R.layout.action_bar_custom, null);

        final ActionBar actionBar = getSupportActionBar();

        actionBar.setDisplayShowCustomEnabled(true);
        actionBar.setCustomView(v, new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT, ActionBar.LayoutParams.WRAP_CONTENT, Gravity.CENTER_VERTICAL
                | Gravity.FILL_HORIZONTAL));

        // Get list items from strings.xml
        drawerListViewItems = getResources().getStringArray(R.array.items);

        // Get ListView defined in activity_main.xml
        drawerListView = (ListView)findViewById(R.id.left_drawer);

        // App Icon
        drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);

        // Set the adapter for the list view
        drawerListView.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_listview_item, drawerListViewItems));

        FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
        tx.replace(R.id.content_frame, mF1);
        tx.commit();

        // Create ActionBarDrawerToggle
        actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close);

        // Set actionBarDrawerToggle as the DrawerListener
        drawerLayout.setDrawerListener(actionBarDrawerToggle);

        // Еnable and show "up" arrow
        actionBar.setDisplayHomeAsUpEnabled(true);

        // Јust styling option
        drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
        drawerListView.setOnItemClickListener(new DrawerItemClickListener());
    }
    }

当我在菜单项之间切换时,我总是像这样替换 fragment :

private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(@SuppressWarnings("rawtypes") AdapterView parent, View view, final int position, long id) {
            drawerLayout.setDrawerListener(new DrawerLayout.SimpleDrawerListener() {
                @Override
                public void onDrawerClosed(View drawerView) {
                    super.onDrawerClosed(drawerView);

                    if (position < 3) {
                        FragmentTransaction tx = getSupportFragmentManager().beginTransaction();

                        switch (position) {
                        case 0:
                            tx.replace(R.id.content_frame, mF1);
                            break;
                        case 1:
                            tx.replace(R.id.content_frame, mF2);
                            break;
                        case 2:
                            tx.replace(R.id.content_frame, mF3);
                            break;
                        default:
                            tx.replace(R.id.content_frame, mF1);
                            break;
                        }

                        tx.commit();
                    }
                }
            });

            drawerLayout.closeDrawer(drawerListView);
        }
    }

因此,我的具有 Google map 的 fragment 是 mF2。它的实现和布局文件如下:

实现:

public class FragmentRouteView extends Fragment {
    static final LatLng MY_LOCATION = new LatLng(54.002858, 7.956872);

    private MapView mMapView;
    private GoogleMap mGoogleMap;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_route_view, container, false);
        mMapView = (MapView)v.findViewById(R.id.mapView);
        mMapView.onCreate(savedInstanceState);
        mMapView.onResume();

        try {
            MapsInitializer.initialize(getActivity());
        }
        catch (GooglePlayServicesNotAvailableException e) {
            e.printStackTrace();
        }

        mGoogleMap = mMapView.getMap();

        // Move the camera instantly to start point with a zoom of 15.
        mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(MY_LOCATION, 15));

        // Zoom in, animating the camera.
        mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);

        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mMapView.onDestroy();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mMapView.onLowMemory();
    }

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black" >

    <com.google.android.gms.maps.MapView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mapView"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

如果你问我为什么在布局文件中有这个 View - 不要。它为我解决了一些问题,与我目前遇到的问题无关。

无论如何。介绍完之后,问题来了:

当我第一次启动显示这些 fragment 的 Activity 并且我第一次导航到 mF2(它有 Google map )时,我看到了 map ,但我的 ActionBar 是全黑。没有标题,没有显示抽屉菜单的侧面按钮。另外,我在 Google map 上看不到 + 和 - 标志。

这是预览:

enter image description here

但是,虽然操作栏是全黑的,但如果我按下菜单按钮应该在的地方,菜单显示,菜单按钮和标题再次显示。

像这样:

enter image description here

之后,只要 Activity 处于 Activity 状态,我就不会遇到这个问题。

然后一切正常,如下所示:

enter image description here

当 Activity 被销毁并再次启动时,当我第一次使用 Google Map 导航到 mF2 时,我再次遇到这个问题。

这不会发生在搭载 Android 4.x.x 的设备上。 它只发生在 Android 2.x.x 的设备上。

知道是什么原因造成的吗?

为了防止任何不相关的反问:

  • 是的,我正在以正确的方式使用支持库
  • 是的,我已经正确设置了 Google Maps API V2 key
  • 是的,当我从 Eclipse 启动设备上的应用程序时,我正在使用调试 key
  • 为什么我在我的 map fragment 布局中使用 RelativeLayout 而不仅仅是 com.google.android.gms.maps.MapView? - 我需要那种神奇的景色 出于某种原因,如果尝试使用 com.google.android.gms.maps.MapView 这也没有区别,同样的事情发生了。

非常感谢。

[edit #1]:有一种情况是这个问题消失了:

我忘了添加:

如果我从我的 Maps Fragment 实现中注释掉这些行:

// Move the camera instantly to start point with a zoom of 15.
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(MY_LOCATION, 15));

// Zoom in, animating the camera.
mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);

我看到 Google map 以 (0,0) 坐标为中心,并且 ActionBar 显示正确。所以,看起来这个问题是在我对 map 做一些额外的事情(缩放、定位、绘制标记等)时发生的。

最佳答案

在 Maps API v2 View 顶部呈现 UI 项时存在一些已知问题([1][2][3]),这会在 UI 项中产生黑框。

这是来自 gmaps-api-issues issue #4659 的最新更新,截至 2013 年 8 月 27 日:

We just pushed an update that changes the base view of the map to a TextureView on Jelly Bean 4.1+ (API 16+) devices. This should resolve several issues, including black rectangles when a map view is moved on the screen.

TextureView was introduced in Ice Cream Sandwich, but we found many ICS devices with driver issues and/or buggy implementations of TextureView. Rendering artifacts cannot be resolved for those devices, or any pre-ICS devices.

To ensure your map can use TextureView, the view needs to be hardware accelerated. This can be done on the Application, Activity or Window level. See Android’s documentation for information on this: http://developer.android.com/guide/topics/graphics/hardware-accel.html

在您可能想尝试的关于该问题的评论中有一些报告的解决方法,但似乎无法解决 pre-ICS 设备上的潜在问题。

关于Android ActionBar 第一次用 Google Map 加载 Fragment 时变黑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19271450/

相关文章:

java - Android:FileProvider.getUriForFile "Failed to find configured root"

android - 使用 volley 发出请求

java - Toolbar/AppbarLayout 将 View 推送到屏幕外。如何将 View 保持在屏幕范围内?

java - Android-没有这样的列错误

android - ProgressDialog( fragment )跨方向开关工作

android - 在 Android 中转义 "@"字符

android - 包含图像和视频的幻灯片

google-maps - 带有服务帐户的 Google 地理编码 API

javascript - 这个 JavaScript 行在做什么(Google map API)?

google-maps - 提供的 key 不是有效的 Google API key