问题
I am trying to display the actionbar above Google Maps, but I realize that once Google Maps open, it is not using my app, but Google's app, therefore the title bar disappears.
I understand that using a MapView allows me to achieve this but I'm not sure how to transition from using a fragment to a MapView as I am getting a NullPointerException
.
Here's the 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>
My 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" />
My 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>
My 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)));
}
}
}
The 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" />
Based on doing some log statements, it appears as though GO HERE
is printed out but it never reaches GO THERE
, so the issue lies in the following code, but I'm not sure how to fix it, as I'm new to Android programming:
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)
Thanks.
回答1:
Define dependencies in your build.gradle
compile 'com.android.support:appcompat-v7:23.0.0'
compile 'com.google.android.gms:play-services:7.8.0'
For getting title extend your activity from AppCompatActivity and set title with setTitle()
For using MapView you don't need to make any checks in onResume.
Just get your map by async method in onCreate.
This setUpMap
method will be called when map is ready.
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)));
}
}
}
回答2:
There is one major problem here, don't use the com.google.android.gms.maps.MapView
in your activity_mapview.xml
rather include the MapFragment
in your activity_mapview.xml
like this:
<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>
or use a FrameLayout
and replace it with the SupportMapFragment
, let me know if this doesn't work.
回答3:
SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
map = fm.getMap();
if (map != null) {
//Do some thing here
}
map declaration should be outside of if condition
回答4:
please change setContentView(R.layout.activity_mapview) to setContentView(R.layout.activity_map).
Because here
((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
you did not inflate layout which contains this fragment.
来源:https://stackoverflow.com/questions/32136078/how-to-use-google-maps-v2-mapview-for-android-to-display-the-actionbar