如何使用 Google Map 的 V2 MapView for Android 来显示 actionbar?

How to use Google Map's V2 MapView for Android to display the actionbar?

我试图在 Google 地图上方显示操作栏,但我意识到一旦 Google 地图打开,它就不会使用我的应用程序,而是 Google 的应用程序,因此标题栏消失了。

我知道使用 MapView 可以实现这一点,但我不确定如何从使用片段过渡到 MapView,因为我得到了 NullPointerException

这是AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.test" >

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/logo"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="@string/google_maps_key" />

        <activity
            android:name=".MapActivity"
            android:label="@string/title_activity_map" >
        </activity>

    </application>

</manifest>

我的activity_map.xml:

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/map"
    tools:context="org.test.MapActivity"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    map:cameraTargetLat="35.25215"
    map:cameraTargetLng="-112.24659"
    map:uiTiltGestures="true"
    map:uiZoomGestures="true"
    map:uiZoomControls="true" />

我的activity_mapview.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.gms.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</LinearLayout>

我的MapActivity.java:

public class MapActivity extends FragmentActivity {
  private GoogleMap mMap;
  private MapView mapView;
  private Marker marker;

  private static final LatLng ONE = new LatLng(32.882216, -117.222028);
  private static final LatLng TWO = new LatLng(32.872000, -117.232004);
  private static final LatLng THREE = new LatLng(32.880252, -117.233034);
  private static final LatLng FOUR = new LatLng(32.885200, -117.226003);

  private ArrayList<LatLng> coords = new ArrayList<LatLng>();
  private static final int POINTS = 4;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_mapview);
    mapView = (MapView) findViewById(R.id.mapView);
    mapView.onCreate(savedInstanceState);

    setUpMapIfNeeded();
  }

  @Override
  protected void onStop() {
    super.onStop();
  }

  @Override
  protected void onResume() {
    super.onResume();
    mapView.onResume();
    setUpMapIfNeeded();
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    mapView.onDestroy();
  }

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

  @Override
  protected void onPause() {
    super.onPause();
    mapView.onPause();
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mapView.onSaveInstanceState(outState);
  }

  private void setUpMapIfNeeded() {
    // Do a null check to confirm that we have not already instantiated the map.
    if (mMap == null) {
      Log.d("Test", "GO HERE");
      mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
      Log.d("Test", "GO THERE");
      if (mMap != null) {
        coords.add(ONE);
        coords.add(TWO);
        coords.add(THREE);
        coords.add(FOUR);

        setUpMap();
      }
    }
  }

  private void setUpMap() {
    for (int i = 0; i < POINTS; i++) {
      mMap.addMarker(new MarkerOptions().position(coords.get(i))
          .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
    }
  }
}

styles.xml:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>

    <style name="FullscreenTheme" parent="android:Theme.NoTitleBar">
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowBackground">@null</item>
        <item name="metaButtonBarStyle">@style/ButtonBar</item>
        <item name="metaButtonBarButtonStyle">@style/ButtonBarButton</item>
    </style>

    <!-- Backward-compatible version of ?android:attr/buttonBarStyle -->
    <style name="ButtonBar">
        <item name="android:paddingLeft">2dp</item>
        <item name="android:paddingTop">5dp</item>
        <item name="android:paddingRight">2dp</item>
        <item name="android:paddingBottom">0dp</item>
        <item name="android:background">@android:drawable/bottom_bar</item>
    </style>

    <!-- Backward-compatible version of ?android:attr/buttonBarButtonStyle -->
    <style name="ButtonBarButton" />

基于做一些日志语句,它看起来好像 GO HERE 被打印出来但它永远不会到达 GO THERE,所以问题出在下面的代码中,但我不确定如何解决它,因为我是 Android 编程新手:

mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                .getMap();

Logcat:

08-21 01:29:20.593  30698-30698/org.test E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to start activity ComponentInfo{org./org.test.MapActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
            at android.app.ActivityThread.access00(ActivityThread.java:117)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:130)
            at android.app.ActivityThread.main(ActivityThread.java:3683)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:507)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at 
org.test.MapActivity.setUpMapIfNeeded(MapActivity.java:183)
                at 
org.test.MapActivity.onCreate(MapActivity.java:77)
                at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
                at android.app.ActivityThread.access00(ActivityThread.java:117)
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
                at android.os.Handler.dispatchMessage(Handler.java:99)
                at android.os.Looper.loop(Looper.java:130)
                at android.app.ActivityThread.main(ActivityThread.java:3683)
                at java.lang.reflect.Method.invokeNative(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:507)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
                at dalvik.system.NativeStart.main(Native Method)

谢谢。

请将 setContentView(R.layout.activity_mapview) 更改为 setContentView(R.layout.activity_map)。

因为这里

((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                .getMap();

您没有扩充包含此片段的布局。

这里有一个主要问题,不要在 activity_mapview.xml 中使用 com.google.android.gms.maps.MapView,而是在 activity_mapview.xml 中包含 MapFragment,如下所示:

<LinearLayout
    xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/map"
    tools:context="org.test.MapActivity"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    map:cameraTargetLat="35.25215"
    map:cameraTargetLng="-112.24659"
    map:uiTiltGestures="true"
    map:uiZoomGestures="true"
    map:uiZoomControls="true" />

</LinearLayout>

或使用 FrameLayout 并将其替换为 SupportMapFragment,如果这不起作用,请告诉我。

SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);

        map = fm.getMap();
        if (map != null) {
       //Do some thing here

          }

map 声明应该在 if 条件之外

在 build.gradle

中定义依赖项
compile 'com.android.support:appcompat-v7:23.0.0'
compile 'com.google.android.gms:play-services:7.8.0'

要获取标题,请从 AppCompatActivity 扩展您的 activity 并使用 setTitle()

设置标题

对于使用 MapView,您不需要在 onResume 中进行任何检查。
只需在 onCreate 中通过异步方法获取您的地图。
setUpMap 方法将在地图准备就绪时调用。

public class MapActivity extends AppCompatActivity {
    private GoogleMap mMap;
    private MapView mapView;
    private Marker marker;

    private static final LatLng ONE = new LatLng(32.882216, -117.222028);
    private static final LatLng TWO = new LatLng(32.872000, -117.232004);
    private static final LatLng THREE = new LatLng(32.880252, -117.233034);
    private static final LatLng FOUR = new LatLng(32.885200, -117.226003);

    private ArrayList<LatLng> coords = new ArrayList<LatLng>();
    private static final int POINTS = 4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mapview);
        setTitle("My Map");
        mapView = (MapView) findViewById(R.id.mapView);
        mapView.onCreate(savedInstanceState);
        mapView.getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(GoogleMap googleMap) {
                setUpMap(googleMap);
            }
        });
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }
    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }
    @Override
    protected void onPause() {
        super.onPause();
        mapView.onPause();
    }
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mapView.onLowMemory();
    }
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
    }
    private void setUpMap(GoogleMap map) {
        mMap = map;

        coords.add(ONE);
        coords.add(TWO);
        coords.add(THREE);
        coords.add(FOUR);
        for (int i = 0; i < POINTS; i++) {
            mMap.addMarker(new MarkerOptions()
                    .position(coords.get(i))
                    .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
        }
    }
}