在 kotlin 中的 requestLocationUpdates 之后移动标记而不是添加它

Posted

技术标签:

【中文标题】在 kotlin 中的 requestLocationUpdates 之后移动标记而不是添加它【英文标题】:Move marker instead of adding it after requestLocationUpdates in kotlin 【发布时间】:2018-08-04 07:06:51 【问题描述】:

在本教程Introduction to Google Maps API for android with Kotlin 的帮助下,我在 kotlin 中使用谷歌地图。在本教程中展示了如何在位置更新后添加标记,但是当它更新时,以前的位置仍然有一个标记并一次又一次地添加。此代码中没有 Marker 对象,我想保留首先添加的标记,然后移动它。我怎样才能做到这一点?谢谢

 class MapsActivity : AppCompatActivity(), OnMapReadyCallback,
    GoogleMap.OnMarkerClickListener 

private lateinit var map: GoogleMap
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var lastLocation: Location

private lateinit var locationCallback: LocationCallback
private lateinit var locationRequest: LocationRequest
private var locationUpdateState = false

companion object 
    private const val LOCATION_PERMISSION_REQUEST_CODE = 1
    private const val REQUEST_CHECK_SETTINGS = 2
    private const val PLACE_PICKER_REQUEST = 3


override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_maps)
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    val mapFragment = supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment
    mapFragment.getMapAsync(this)

    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)

    locationCallback = object : LocationCallback() 
        override fun onLocationResult(p0: LocationResult) 
            super.onLocationResult(p0)

            lastLocation = p0.lastLocation
            placeMarkerOnMap(LatLng(lastLocation.latitude, lastLocation.longitude))
        
    

    createLocationRequest()

    val fab = findViewById<FloatingActionButton>(R.id.fab)
    fab.setOnClickListener 
        loadPlacePicker()
    


override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) 
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == REQUEST_CHECK_SETTINGS) 
        if (resultCode == Activity.RESULT_OK) 
            locationUpdateState = true
            startLocationUpdates()
        
    
    if (requestCode == PLACE_PICKER_REQUEST) 
        if (resultCode == RESULT_OK) 
            val place = PlacePicker.getPlace(this, data)
            var addressText = place.name.toString()
            addressText += "\n" + place.address.toString()

            placeMarkerOnMap(place.latLng)
        
    


override fun onPause() 
    super.onPause()
    fusedLocationClient.removeLocationUpdates(locationCallback)


public override fun onResume() 
    super.onResume()
    if (!locationUpdateState) 
        startLocationUpdates()
    


override fun onMapReady(googleMap: GoogleMap) 
    map = googleMap

    map.uiSettings.isZoomControlsEnabled = true
    map.setOnMarkerClickListener(this)

    setUpMap()


override fun onMarkerClick(p0: Marker?) = true

private fun setUpMap() 
    if (ActivityCompat.checkSelfPermission(this,
            android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) 
        ActivityCompat.requestPermissions(this,
                arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
        return
    

    map.isMyLocationEnabled = true
    map.mapType = GoogleMap.MAP_TYPE_NORMAL

    fusedLocationClient.lastLocation.addOnSuccessListener(this)  location ->
        // Got last known location. In some rare situations this can be null.
        if (location != null) 
            lastLocation = location
            val currentLatLng = LatLng(location.latitude, location.longitude)
            placeMarkerOnMap(currentLatLng)
            map.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 12f))
        
    


private fun placeMarkerOnMap(location: LatLng) 
    val markerOptions = MarkerOptions().position(location)

    val titleStr = getAddress(location)  // add these two lines
    markerOptions.title(titleStr)

    map.addMarker(markerOptions)




private fun startLocationUpdates() 
    if (ActivityCompat.checkSelfPermission(this,
            android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) 
        ActivityCompat.requestPermissions(this,
                arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
                LOCATION_PERMISSION_REQUEST_CODE)
        return
    
    fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null /* Looper */)



private fun createLocationRequest() 
    locationRequest = LocationRequest()
    locationRequest.interval = 10000
    locationRequest.fastestInterval = 5000
    locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY

    val builder = LocationSettingsRequest.Builder()
            .addLocationRequest(locationRequest)
    val client = LocationServices.getSettingsClient(this)
    val task = client.checkLocationSettings(builder.build())

    task.addOnSuccessListener 
        locationUpdateState = true
        startLocationUpdates()
    
    task.addOnFailureListener  e ->
        if (e is ResolvableApiException) 
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try 
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                e.startResolutionForResult(this@MapsActivity,
                        REQUEST_CHECK_SETTINGS)
             catch (sendEx: IntentSender.SendIntentException) 
                // Ignore the error.
            
        
    


private fun loadPlacePicker() 
    val builder = PlacePicker.IntentBuilder()

    try 
        startActivityForResult(builder.build(this@MapsActivity), PLACE_PICKER_REQUEST)
     catch (e: GooglePlayServicesRepairableException) 
        e.printStackTrace()
     catch (e: GooglePlayServicesNotAvailableException) 
        e.printStackTrace()
    


【问题讨论】:

【参考方案1】:

GoogleMap 的addMarker() 方法返回一个Marker。

您需要保留对返回标记的引用,然后使用setPosition 方法更新它的位置。

【讨论】:

【参考方案2】:

@LordRaydenMK's answer 是正确的。我花了一周的时间试图解决这个问题,最终发现它得到了它。您引用的 raywenderlich tutorial 很好,只是他们错误地编码了 placeMarkerOnMap() 函数。

首先,在onCreate上方为您的位置标记设置一个变量:

private var userLocationMarker: Marker? = null

然后用此代码替换您的 placeMarkerOnMap() 函数,它应该可以正常工作:

private fun placeMarkerOnMap(location: Location) 
    val latLng = LatLng(location.latitude, location.longitude)
    if (userLocationMarker == null) 
        //Create a new marker
        val markerOptions = MarkerOptions()
        markerOptions.position(latLng)
        markerOptions.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_user_location))
        markerOptions.rotation(location.bearing)
        markerOptions.anchor(0.5.toFloat(), 0.5.toFloat())
        userLocationMarker = map.addMarker(markerOptions)
        map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 20f))
     else 
        //use the previously created marker
        userLocationMarker!!.position = latLng
        userLocationMarker!!.rotation = location.bearing
        map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 20f))
    

如果您想摆脱蓝点,请确保将isMyLocationEnabled 设置为false

【讨论】:

以上是关于在 kotlin 中的 requestLocationUpdates 之后移动标记而不是添加它的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 中的意图

干货丨Kotlin在Spring Boot中的应用

Kotlin 中的单例类

AsyncTask 在 Kotlin 中的使用

Kotlin 中的“宁愿在该类上运行匕首处理器”

Kotlin 中的 RecyclerView itemClickListener [关闭]