【问题标题】:Place tap listener on Google maps android在谷歌地图安卓上放置点击监听器
【发布时间】:2019-10-26 20:42:42
【问题描述】:

我有一个带有地图片段的安卓应用。 地图显示地点,我正在寻找一种方法来添加侦听器,以便在用户点击它们时获取该地点。

我找到的最相关的信息是建议在地图上添加点击监听器,获取经纬度,然后根据该信息搜索地点。 我以为我可以使用FetchPlaceRequest 来做到这一点,但这似乎也需要在实例化时首先使用placeId

我错过了一些非常基本的东西吗?

编辑

包含地图的片段的代码(我认为实现 PlaceSelectionlistener 就可以了)

class MapFragment : Fragment(), OnMapReadyCallback, GoogleMap.OnMarkerClickListener,
PlaceSelectionListener, KoinComponent {

private lateinit var mapViewModel: MapViewModel
private lateinit var map: GoogleMap
private var fusedLocationClient: FusedLocationProviderClient? = null
private var locationRequest: LocationRequest? = null
private var locationCallback: LocationCallback? = null
private val permissionsUtils : PermissionsUtils by inject()
private val preferencesUtils : PreferencesUtils by inject { parametersOf(activity!!.applicationContext)}
private var root : View? = null
private val defaultZoom : Float = 16f

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    mapViewModel = ViewModelProviders.of(this).get(MapViewModel::class.java)
    root = inflater.inflate(R.layout.fragment_map, container, false)

    if (canAccessLocation()) {
        initialiseMap(true)
    } else {
        val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)

        requestPermissions(permissions, PermissionRequests.FineLocation.value)
    }

    return root
}

override fun onMarkerClick(p0: Marker?) = false

override fun onMapReady(googleMap: GoogleMap) {
    map = googleMap

    map.setMapStyle(MapStyleOptions
        .loadRawResourceStyle(activity!!.applicationContext, preferencesUtils.mapMode))

    map.uiSettings.isZoomControlsEnabled = true

    if (canAccessLocation()){
        map.isMyLocationEnabled = true
        map.uiSettings.isMyLocationButtonEnabled = true
    }

    map.setOnMarkerClickListener(this)
}

override fun onRequestPermissionsResult(requestCode: Int,
                                        permissions: Array<String>, grantResults: IntArray) {
    when (requestCode) {

        PermissionRequests.FineLocation.value -> {
            val permissionGranted = grantResults.isNotEmpty()
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED

            initialiseMap(permissionGranted)
        }
    }
}

override fun onPause() {
    super.onPause()
    fusedLocationClient?.removeLocationUpdates(locationCallback)
}

override fun onResume() {
    super.onResume()

    requestLocationUpdates()
}

override fun onPlaceSelected(status: Place) {
    val toast = Toast.makeText(activity!!.applicationContext,""+ status!!.name + status!!.latLng, Toast.LENGTH_LONG)
    toast.setGravity(Gravity.TOP, 0, 0)
    toast.show()
}

override fun onError(status: Status) {
    Toast.makeText(activity!!.applicationContext,"" + status.toString(), Toast.LENGTH_LONG)
        .show()
}

private fun initialiseMap(withLocation: Boolean) {
    val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment

    mapFragment.getMapAsync(this)

    if (!withLocation) {
        return
    }

    requestLocationUpdates()
}

private fun requestLocationUpdates() {
    if (fusedLocationClient == null) {
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(activity!!.applicationContext)
    }

    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            val locationList = locationResult.locations

            if (locationList.size > 0) {
                val location = locationList[locationList.size - 1]
                val latLng = LatLng(location.latitude, location.longitude)

                map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, defaultZoom))
            }
        }
    }

    fusedLocationClient?.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())

    locationRequest = LocationRequest()
    locationRequest?.interval = 1800000
    locationRequest?.fastestInterval = 1800000
    locationRequest?.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY

    fusedLocationClient?.lastLocation?.addOnCompleteListener(Activity()) { task ->
            if (task.isSuccessful && task.result != null) {
                val latLong = LatLng(task.result!!.latitude, task.result!!.longitude)
                map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLong, defaultZoom))
            }
        }
}

private fun canAccessLocation(): Boolean {
    return permissionsUtils.hasPermission(activity!!.applicationContext, Manifest.permission.ACCESS_FINE_LOCATION)
}
}

【问题讨论】:

标签: android google-maps google-places-api


【解决方案1】:

因为您无法管理在 MapView (MapFragment) 上显示的地点,而且它的标记不可点击(和可自定义)恕我直言,更好的方法是通过 Google Maps styling 隐藏“默认”地点标记,就像在 this 中一样Jozef的回答:

  1. 像这样创建 JSON 文件 src\main\res\raw\map_style.json

[
  {
    featureType: "poi",
    elementType: "labels",
    stylers: [
      {
        visibility: "off"
      }
    ]
  }
]
  1. 将地图样式添加到您的GoogleMap

googleMap.setMapStyle(MapStyleOptions.loadRawResourceStyle(getContext(), R.raw.map_style));

然后 - 通过Place SearchGoogle Places API URL 请求获取附近的地点:

https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=<LAT_LNG>&types=point_of_interest&radius=<RADIUS_IN_METERS>&sensor=false&key=<YOUR_APP_KEY>

解析它并以编程方式在地图上显示所需位置,作为可自定义和可点击的 Google 地图标记。这种方法不仅允许您通过默认onMarkerClick() 处理标记点击,还可以管理地点的数量和类型、标记图标设计等。也无需在用户每次点击地图时创建请求并处理其响应.

注意!附近的 URL 请求仅返回 20 个位置,要加载更多数据,您应该使用来自响应的 next_page_token 标记的字符串值,并通过 pagetoken 参数将其传递给下一个请求:

https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=<LAT_LNG>&types=point_of_interest&radius=<RADIUS_IN_METERS>&sensor=false&key=<YOUR_APP_KEY>&pagetoken=<TOKEN_FOR_NEXT_PAGE_FROM_next_page_token_TAG_OF_RESPONSE>

【讨论】:

  • 这很有意义,谢谢。从来没有想过没有一种开箱即用的方式来点击所有 POI 并毫不费力地获取有关它们的详细信息
猜你喜欢
  • 1970-01-01
  • 2016-04-30
  • 2016-11-21
  • 2017-06-16
  • 1970-01-01
  • 2020-09-02
  • 1970-01-01
  • 1970-01-01
  • 2013-02-18
相关资源
最近更新 更多