如何使用Google Map的V2 MapView for Android显示操作栏?

时间:2015-08-21 08:46:42

标签: android google-maps android-fragments android-mapview

我正在尝试在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.access$1500(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.access$1500(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)

感谢。

4 个答案:

答案 0 :(得分:11)

在build.gradle中定义依赖项

compile 'com.android.support:appcompat-v7:23.0.0'
compile 'com.google.android.gms:play-services:7.8.0'

获取标题可以从AppCompatActivity扩展您的活动,并使用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)));
        }
    }
}

答案 1 :(得分:0)

此处存在一个主要问题,请勿在{{1​​}}中使用com.google.android.gms.maps.MapView,而应在activity_mapview.xml中添加MapFragment,如下所示:

activity_mapview.xml

或使用<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,如果这不起作用,请告诉我。

答案 2 :(得分:0)

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

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

          }

地图声明应该在if条件之外

答案 3 :(得分:-1)

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

因为这里

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

你没有夸大包含这个片段的布局。