【问题标题】:How to use Google Map's V2 MapView for Android to display the actionbar?如何使用 Google Maps V2 MapView for Android 显示操作栏?
【发布时间】:2015-08-21 08:46:42
【问题描述】:

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

我知道使用 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,所以问题在于以下代码,但我不知道如何解决它,因为我是新手安卓编程:

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)

谢谢。

【问题讨论】:

  • 你从哪里得到 NullPointerException,你能发布你的堆栈跟踪(logcat)
  • 如果有帮助,添加 logcat

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


【解决方案1】:

在 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方法会在map准备好时被调用。

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)));
        }
    }
}

【讨论】:

  • @Pangu 什么标题栏?为什么这是地图问题? :) 为什么要减去?
  • 正如我的问题中提到的,我想在地图上方显示一个标题栏,但是我的代码以及您的代码在整个屏幕上显示地图,这就是为什么我问如何使用 MapView,因为 MapView 允许我实现这一点。
  • @Pangu 但我们解决了 NullPointerException?你想要什么标题栏?现在是标准的 android 操作栏或工具栏吗?
  • 基本上我正在尝试关注这个视频:youtube.com/watch?v=sb1oqaptlWQ 最后你可以看到他有一个标题栏,标题为“我的地图”......我怎样才能用我的代码实现这一点?谢谢
  • @Pangu 与地图视图或地图片段无关。显示你的@style/AppTheme
【解决方案2】:

这里有一个主要问题,不要在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,如果这不起作用,请告诉我。

【讨论】:

  • 我正在尝试使用 MapView,而不是返回 Fragment。
  • 对不起,我有点糊涂了,你不是想用地图吗?
【解决方案3】:
SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);

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

          }

map 声明应该在 if 条件之外

【讨论】:

    【解决方案4】:

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

    因为这里

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

    您没有膨胀包含此片段的布局。

    【讨论】:

    • 然后我将在 activity_map.xml 中使用片段,并尝试在 activity_mapview.xml 中使用 MapView
    • @Pangu : 然后改变 ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)) .getMap(); findViewById(R.id.mapView)。
    • 对不起,我不明白,将 mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)) .getMap() 更改为 mMap = findViewById(R.id.mapView) 给了我一个错误
    猜你喜欢
    • 2013-02-14
    • 2015-02-19
    • 1970-01-01
    • 2013-02-15
    • 2012-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多