我希望MapView
Fragment
这是我的FragmentLayout
xml文件
<?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="#17df0d"
android:orientation="vertical" >
<com.google.android.gms.maps.MapView
android:id="@+id/mapview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/textView1"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="70dp" >
</com.google.android.gms.maps.MapView>
</RelativeLayout>
我的AndroidManifest.xml
文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="a.b.c.d"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="your_api_key" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
</application>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<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" />
<permission
android:name="a.b.c.d.permission.MAPS_RECEIVE"
android:protectionLevel="signature" />
<uses-permission android:name="a.b.c.d.permission.MAPS_RECEIVE" />
<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" />
</manifest>
和我的片段类
public class ReportFragment extends Fragment implements LocationListener {
MapView mapView = null; //eventually it is being read from view and assigned
当我启动应用程序时,我在Fragment中看不到任何地图视图
答案 0 :(得分:39)
来自Josh Holtz's example on GitHub:
您应该在MapView
中添加Layout
<com.google.android.gms.maps.MapView
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
并实施您的Fragment
public class SomeFragment extends Fragment {
MapView mapView;
GoogleMap map;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.some_layout, container, false);
// Gets the MapView from the XML layout and creates it
mapView = (MapView) v.findViewById(R.id.mapview);
mapView.onCreate(savedInstanceState);
// Gets to GoogleMap from the MapView and does initialization stuff
map = mapView.getMap();
map.getUiSettings().setMyLocationButtonEnabled(false);
map.setMyLocationEnabled(true);
// Needs to call MapsInitializer before doing any CameraUpdateFactory calls
try {
MapsInitializer.initialize(this.getActivity());
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
// Updates the location and zoom of the MapView
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(43.1, -87.9), 10);
map.animateCamera(cameraUpdate);
return v;
}
@Override
public void onResume() {
mapView.onResume();
super.onResume();
}
@Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}
答案 1 :(得分:18)
加入M D的回答:
必须使用getMapAsync(OnMapReadyCallback)获取GoogleMap。 MapView会自动初始化地图系统和视图。
根据这一点,初始化GoogleMap
的更正确的方法是使用getMapAsync
。
请注意,您的课程必须实施OnMapReadyCallback
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_map_page, container, false);
mMapView = (MapView) v.findViewById(R.id.map_view);
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(this); //this is important
return v;
}
@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.getUiSettings().setZoomControlsEnabled(true);
mGoogleMap.addMarker(new MarkerOptions().position(/*some location*/));
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(/*some location*/, 10));
}
@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 onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mMapView.onSaveInstanceState(outState);
}
@Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
答案 2 :(得分:5)
如果有人正在寻找Kotlin版本的MapView Fragment;)
class MapViewKotlinFragment : Fragment(), OnMapReadyCallback {
private var mMap: MapView? = null
override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
mMap?.onSaveInstanceState(outState)
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater?.inflate(R.layout.fragment_map, container, false)
mMap = view?.findViewById(R.id.mapViewPlaces) as MapView
mMap?.onCreate(savedInstanceState)
mMap?.getMapAsync(this)
return view
}
override fun onResume() {
super.onResume()
mMap?.onResume()
}
override fun onPause() {
super.onPause()
mMap?.onPause()
}
override fun onStart() {
super.onStart()
mMap?.onStart()
}
override fun onStop() {
super.onStop()
mMap?.onStop()
}
override fun onDestroy() {
super.onDestroy()
mMap?.onDestroy()
}
override fun onLowMemory() {
super.onLowMemory()
mMap?.onLowMemory()
}
override fun onMapReady(googleMap: GoogleMap) {
googleMap.addMarker(MarkerOptions().position(LatLng(0.0, 0.0)).title("Marker"))
}
答案 3 :(得分:0)
确保您要覆盖或调用OnDestroy View 以及OnDestroy。像...
public override void OnDestroy()
{
base.OnDestroy();
MapView.OnDestroy();
OnDestroyView();
}
public override void OnDestroyView()
{
base.OnDestroyView();
mapReadyCallbackList.Clear();
}
答案 4 :(得分:0)
旧帖子,但可能对正在片段中实现地图的人有所帮助。以下是使用kotlin的详细示例:
首先,在AndroidManifest.xml文件中添加权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
然后在application标记下在AndroidManifest.xml文件中添加元数据:
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/map_api_key"/>
<uses-library
android:name="org.apache.http.legacy"
android:required="false" />
*要获取api链接,请访问:https://developers.google.com/maps/documentation/android-sdk/get-api-key
在build.gradle文件中实现播放服务:
implementation "com.google.android.gms:play-services-location:15.0.1"
implementation "com.google.android.gms:play-services-places:15.0.1"
implementation 'com.google.android.libraries.places:places:2.3.0'
添加标签:应用插件:“ com.google.gms.google-services”
在您的fragment.xml文件中添加地图片段:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
在fragment.kt文件中,实现OnMapReadyCallback。使用getMapAsync()初始化Google地图。下面的代码可让您集成Google地图并将其指向您当前的位置。
package "Your_Package_Name"
import android.Manifest
import android.content.ContentValues.TAG
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.location.Location
import android.os.Bundle
import androidx.core.app.ActivityCompat
import androidx.fragment.app.Fragment
import androidx.core.content.ContextCompat
import androidx.appcompat.app.AlertDialog
import android.util.Log
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.TextView
import android.widget.Toast
import com.example.utilitybox.R
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.maps.*
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Marker
import com.google.android.gms.maps.model.MarkerOptions
import com.google.android.libraries.places.api.model.Place
import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest
import com.google.android.libraries.places.api.net.PlacesClient
class FragmentHome : Fragment(), OnMapReadyCallback {
private var v:View?=null
private var locationPermissionGranted = false
private var googleMap: GoogleMap?=null
private var fusedLocationProviderClient: FusedLocationProviderClient?=null
private val defaultLocation = LatLng(-33.8523341, 151.2106085)
private var cameraPosition: CameraPosition? = null
private var placesClient: PlacesClient?=null
private var lastKnownLocation: Location? = null
private var likelyPlaceNames: Array<String?> = arrayOfNulls(0)
private var likelyPlaceAddresses: Array<String?> = arrayOfNulls(0)
private var likelyPlaceAttributions: Array<List<*>?> = arrayOfNulls(0)
private var likelyPlaceLatLngs: Array<LatLng?> = arrayOfNulls(0)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
if (savedInstanceState != null) {
lastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION)
cameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION)
}
v = inflater.inflate(R.layout.fragment_fragment_home, container, false)
if(getString(R.string.map_api_key).isEmpty()){
Toast.makeText(activity, "Add your own API key in MapWithMarker/app/secure.properties as MAPS_API_KEY=YOUR_API_KEY", Toast.LENGTH_LONG).show()
}
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as? SupportMapFragment
mapFragment?.getMapAsync(this)
getLocationPermission()
return v
}
override fun onSaveInstanceState(outState: Bundle) {
googleMap?.let { map ->
outState.putParcelable(KEY_CAMERA_POSITION, map.cameraPosition)
outState.putParcelable(KEY_LOCATION, lastKnownLocation)
}
super.onSaveInstanceState(outState)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.option_get_place) {
showCurrentPlace()
}
return true
}
override fun onMapReady(googleMap: GoogleMap) {
this.googleMap = googleMap
this.googleMap?.setInfoWindowAdapter(object : GoogleMap.InfoWindowAdapter {
override fun getInfoWindow(arg0: Marker): View? {
return null
}
override fun getInfoContents(marker: Marker): View {
val infoWindow = layoutInflater.inflate(R.layout.custom_info_contents,
v?.findViewById(R.id.map), false)
val title = infoWindow.findViewById<TextView>(R.id.title)
title.text = marker.title
val snippet = infoWindow.findViewById<TextView>(R.id.snippet)
snippet.text = marker.snippet
return infoWindow
}
})
getLocationPermission()
updateLocationUI()
getDeviceLocation()
}
private fun getLocationPermission() {
if (ContextCompat.checkSelfPermission(this.requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
locationPermissionGranted = true
} else {
ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION)
}
}
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>,
grantResults: IntArray) {
locationPermissionGranted = false
when (requestCode) {
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION -> {
if (grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
locationPermissionGranted = true
}
}
}
updateLocationUI()
}
private fun showCurrentPlace() {
if (googleMap == null) {
return
}
if (locationPermissionGranted) {
val placeFields = listOf(Place.Field.NAME, Place.Field.ADDRESS, Place.Field.LAT_LNG)
val request = FindCurrentPlaceRequest.newInstance(placeFields)
val placeResult = placesClient?.findCurrentPlace(request)
placeResult?.addOnCompleteListener { task ->
if (task.isSuccessful && task.result != null) {
val likelyPlaces = task.result
val count = if (likelyPlaces != null && likelyPlaces.placeLikelihoods.size < M_MAX_ENTRIES) {
likelyPlaces.placeLikelihoods.size
} else {
M_MAX_ENTRIES
}
var i = 0
likelyPlaceNames = arrayOfNulls(count)
likelyPlaceAddresses = arrayOfNulls(count)
likelyPlaceAttributions = arrayOfNulls<List<*>?>(count)
likelyPlaceLatLngs = arrayOfNulls(count)
for (placeLikelihood in likelyPlaces?.placeLikelihoods ?: emptyList()) {
likelyPlaceNames[i] = placeLikelihood.place.name
likelyPlaceAddresses[i] = placeLikelihood.place.address
likelyPlaceAttributions[i] = placeLikelihood.place.attributions
likelyPlaceLatLngs[i] = placeLikelihood.place.latLng
i++
if (i > count - 1) {
break
}
}
openPlacesDialog()
} else {
Log.e(TAG, "Exception: %s", task.exception)
}
}
} else {
Log.i(TAG, "The user did not grant location permission.")
googleMap?.addMarker(MarkerOptions()
.title(getString(R.string.default_info_title))
.position(defaultLocation)
.snippet(getString(R.string.default_info_snippet)))
getLocationPermission()
}
}
private fun updateLocationUI() {
if (googleMap == null) {
return
}
try {
if (locationPermissionGranted) {
googleMap?.isMyLocationEnabled = true
googleMap?.uiSettings?.isMyLocationButtonEnabled = true
} else {
googleMap?.isMyLocationEnabled = false
googleMap?.uiSettings?.isMyLocationButtonEnabled = false
lastKnownLocation = null
getLocationPermission()
}
} catch (e: SecurityException) {
Log.e("Exception: %s", e.message, e)
}
}
private fun getDeviceLocation() {
try {
if (locationPermissionGranted) {
val locationResult = fusedLocationProviderClient?.lastLocation
if (locationResult != null) {
locationResult.addOnCompleteListener(this.requireActivity()) { task ->
if (task.isSuccessful) {
// Set the map's camera position to the current location of the device.
lastKnownLocation = task.result
if (lastKnownLocation != null) {
googleMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(
LatLng(lastKnownLocation!!.latitude,
lastKnownLocation!!.longitude), DEFAULT_ZOOM.toFloat()))
}
} else {
Log.d(TAG, "Current location is null. Using defaults.")
Log.e(TAG, "Exception: %s", task.exception)
googleMap?.moveCamera(CameraUpdateFactory
.newLatLngZoom(defaultLocation, DEFAULT_ZOOM.toFloat()))
googleMap?.uiSettings?.isMyLocationButtonEnabled = false
}
}
}
}
} catch (e: SecurityException) {
Log.e("Exception: %s", e.message, e)
}
}
private fun openPlacesDialog() {
val listener = DialogInterface.OnClickListener { dialog, which ->
val markerLatLng = likelyPlaceLatLngs[which]
var markerSnippet = likelyPlaceAddresses[which]
if (likelyPlaceAttributions[which] != null) {
markerSnippet = """
$markerSnippet
${likelyPlaceAttributions[which]}
""".trimIndent()
}
googleMap?.addMarker(MarkerOptions()
.title(likelyPlaceNames[which])
.position(markerLatLng!!)
.snippet(markerSnippet))
googleMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(markerLatLng,
DEFAULT_ZOOM.toFloat()))
}
AlertDialog.Builder(this.requireContext())
.setTitle(R.string.pick_place)
.setItems(likelyPlaceNames, listener)
.show()
}
companion object {
private const val DEFAULT_ZOOM = 15
private const val PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1
private const val KEY_CAMERA_POSITION = "camera_position"
private const val KEY_LOCATION = "location"
private const val M_MAX_ENTRIES = 5
}
}
完成后,在布局文件夹中添加custom_info_contents.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layoutDirection="locale"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="#ff000000"
android:textStyle="bold" />
<TextView
android:id="@+id/snippet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff7f7f7f" />
</LinearLayout>
在strings.xml文件中添加以下代码:
<string name="map_api_key">YOUR_API_KEY</string>
<!--Map strings-->
<string name="title_activity_maps">Current Place Details</string>
<string name="default_info_title">Default Location</string>
<string name="default_info_snippet">No places found, because location permission is disabled.</string>
<string name="option_get_place">Get place</string>
<string name="pick_place">Choose a place</string>
在菜单文件夹中创建current_place_menu.xml文件并添加以下代码:
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/option_get_place"
android:title="@string/option_get_place"
app:showAsAction="always"/>
</menu>