下面的代码给出了位置服务的代码示例(https://github.com/mapbox/mapbox-maps-android/blob/v11.7.1/app/src/main/java/com/mapbox/maps/testapp/examples/LocationComponentActivity.kt)
对代码进行一个详细的解析:
这段代码是一个 Android 应用程序的 Activity,主要用于展示如何使用 Mapbox 地图 SDK 显示用户的位置以及处理位置组件。下面逐句详细解释这段代码:
kotlin
package com.mapbox.maps.testapp.examples
- 指定该文件的包名为
com.mapbox.maps.testapp.examples
,这是一个 Kotlin 文件,通常是用于组织代码。
kotlin
import android.graphics.Color
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
- 导入所需的 Android 类和 Mapbox 相关库。这些类将用于设置 UI 组件、处理事件和显示消息等。
kotlin
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.ImageHolder
import com.mapbox.maps.MapboxExperimental
import com.mapbox.maps.Style
import com.mapbox.maps.extension.style.expressions.dsl.generated.interpolate
import com.mapbox.maps.extension.style.layers.properties.generated.Anchor
import com.mapbox.maps.extension.style.layers.properties.generated.ProjectionName
import com.mapbox.maps.extension.style.light.generated.flatLight
import com.mapbox.maps.extension.style.light.setLight
import com.mapbox.maps.extension.style.projection.generated.getProjection
import com.mapbox.maps.extension.style.projection.generated.projection
import com.mapbox.maps.extension.style.projection.generated.setProjection
import com.mapbox.maps.plugin.LocationPuck2D
import com.mapbox.maps.plugin.LocationPuck3D
import com.mapbox.maps.plugin.PuckBearing
import com.mapbox.maps.plugin.gestures.gestures
import com.mapbox.maps.plugin.locationcomponent.DefaultLocationProvider
import com.mapbox.maps.plugin.locationcomponent.OnIndicatorPositionChangedListener
import com.mapbox.maps.plugin.locationcomponent.createDefault2DPuck
import com.mapbox.maps.plugin.locationcomponent.location
import com.mapbox.maps.testapp.R
import com.mapbox.maps.testapp.databinding.ActivityLocationComponentBinding
import com.mapbox.maps.testapp.utils.LocationPermissionHelper
import java.lang.ref.WeakReference
- 导入 Mapbox SDK 的各个组件和扩展功能,包括样式、光照、投影、位置组件等。同时导入了数据绑定和权限处理工具。
kotlin
@OptIn(MapboxExperimental::class)
- 指示使用 Mapbox 的实验性功能。这通常用于在 SDK 中处于实验阶段的功能,以避免警告。
kotlin
class LocationComponentActivity : AppCompatActivity() {
- 定义
LocationComponentActivity
类,继承自AppCompatActivity
,表示这是一个 Activity。
kotlin
private var lastStyleUri = Style.DARK
- 声明一个变量
lastStyleUri
,用于存储最后使用的地图样式 URI,默认为Style.DARK
。
kotlin
private lateinit var locationPermissionHelper: LocationPermissionHelper
- 声明一个
LocationPermissionHelper
类型的变量locationPermissionHelper
,用于处理位置权限请求。
kotlin
private val onIndicatorPositionChangedListener = OnIndicatorPositionChangedListener {
- 创建一个
OnIndicatorPositionChangedListener
的匿名实现,用于响应位置指示器位置变化事件。
kotlin
// Jump to the current indicator position
binding.mapView.mapboxMap.setCamera(CameraOptions.Builder().center(it).build())
- 当位置指示器位置发生变化时,更新地图相机的位置以跟随指示器。
kotlin
// Set the gestures plugin's focal point to the current indicator location.
binding.mapView.gestures.focalPoint = binding.mapView.mapboxMap.pixelForCoordinate(it)
- 设置手势插件的焦点为当前位置,以便于地图手势交互。
kotlin
private lateinit var binding: ActivityLocationComponentBinding
- 声明一个
ActivityLocationComponentBinding
类型的变量binding
,用于绑定布局文件。
kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- 重写
onCreate
方法,这是 Activity 创建时调用的方法。
kotlin
binding = ActivityLocationComponentBinding.inflate(layoutInflater)
- 使用数据绑定将布局文件
activity_location_component
绑定到binding
变量。
kotlin
setContentView(binding.root)
- 将活动的内容视图设置为绑定的根视图。
kotlin
locationPermissionHelper = LocationPermissionHelper(WeakReference(this))
- 初始化
locationPermissionHelper
,并传入this
的弱引用,用于处理位置权限。
kotlin
locationPermissionHelper.checkPermissions {
- 调用
checkPermissions
方法检查位置权限。
kotlin
binding.mapView.apply {
- 在
mapView
上进行操作,以下所有操作将在mapView
内部进行。
kotlin
mapboxMap.loadStyle(Style.STANDARD) {
- 加载标准样式的地图。
kotlin
it.setLight(
flatLight {
- 设置地图的光照效果,使用
flatLight
方法配置。
kotlin
anchor(Anchor.MAP)
- 设置光照的锚点为地图本身。
kotlin
color(Color.YELLOW)
- 设置光照的颜色为黄色。
kotlin
position(
radialCoordinate = 10.0,
azimuthalAngle = 40.0,
polarAngle = 50.0
)
- 配置光照的位置,包括径向坐标、方位角和极角。
kotlin
}
)
- 关闭光照设置。
kotlin
// Disable scroll gesture, since we are updating the camera position based on the indicator location.
gestures.scrollEnabled = false
- 禁用地图的滚动手势,因为相机位置是根据指示器位置更新的。
kotlin
gestures.addOnMapClickListener { point ->
- 添加点击地图的监听器。
kotlin
location.isLocatedAt(point) { isPuckLocatedAtPoint ->
- 检查点击的点是否在位置指示器上。
kotlin
if (isPuckLocatedAtPoint) {
Toast.makeText(context, "Clicked on location puck", Toast.LENGTH_SHORT).show()
}
- 如果点击了位置指示器,显示提示信息。
kotlin
true
- 返回
true
表示事件已处理。
kotlin
}
- 结束点击监听器。
kotlin
gestures.addOnMapLongClickListener { point ->
- 添加长按地图的监听器。
kotlin
location.isLocatedAt(point) { isPuckLocatedAtPoint ->
- 检查长按的点是否在位置指示器上。
kotlin
if (isPuckLocatedAtPoint) {
Toast.makeText(context, "Long-clicked on location puck", Toast.LENGTH_SHORT)
.show()
}
- 如果长按了位置指示器,显示提示信息。
kotlin
true
- 返回
true
表示事件已处理。
kotlin
}
- 结束长按监听器。
kotlin
val locationProvider = location.getLocationProvider() as DefaultLocationProvider
- 获取位置提供者,并将其转换为
DefaultLocationProvider
类型。
kotlin
locationProvider.addOnCompassCalibrationListener {
Toast.makeText(context, "Compass needs to be calibrated", Toast.LENGTH_LONG).show()
}
- 添加指南针校准的监听器,若需要校准则显示提示信息。
kotlin
}
- 结束
mapView.apply
块。
kotlin
}
- 结束
checkPermissions
的 lambda。
kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_location_component, menu)
return true
}
- 创建选项菜单,加载菜单布局。
kotlin
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
- 处理菜单项的点击事件。
kotlin
R.id.action_customise_location_puck_change -> {
toggleCustomisedPuck()
return true
}
- 点击自定义位置指示器的菜单项时,调用
toggleCustomisedPuck()
方法。
kotlin
R.id.action_map_style_change -> {
toggleMapStyle()
return true
}
- 点击更改地图样式的菜单项时,调用
toggleMapStyle()
方法。
kotlin
R.id.action_map_projection_change -> {
toggleMapProjection()
return true
}
- 点击更改地图投影的菜单项时,调用
toggleMapProjection()
方法。
kotlin
R.id.action_component_disable -> {
binding.mapView.location.enabled = false
return true
}
- 点击禁用位置组件的菜单项时,禁用位置组件。
kotlin
R.id.action_component_enabled -> {
binding.mapView.location.enabled = true
return true
}
- 点击启用位置组件的菜单项时,启用位置组件。
kotlin
R.id.action_show_bearing -> {
binding.mapView.location.puckBearingEnabled = true
if (binding.mapView.location.locationPuck is LocationPuck2D) {
binding.mapView.location.locationPuck = createDefault2DPuck(withBearing
= true)
}
return true
}
- 点击显示方位的菜单项时,启用方位显示。
kotlin
R.id.action_hide_bearing -> {
binding.mapView.location.puckBearingEnabled = false
if (binding.mapView.location.locationPuck is LocationPuck2D) {
binding.mapView.location.locationPuck = createDefault2DPuck(withBearing = false)
}
return true
}
- 点击隐藏方位的菜单项时,禁用方位显示。
kotlin
R.id.heading -> {
binding.mapView.location.puckBearing = PuckBearing.HEADING
item.isChecked = true
return true
}
- 点击"指向"菜单项时,将方位设置为指向。
kotlin
R.id.course -> {
binding.mapView.location.puckBearing = PuckBearing.COURSE
item.isChecked = true
return true
}
- 点击"航向"菜单项时,将方位设置为航向。
kotlin
R.id.location_no_animation -> {
(binding.mapView.location.getLocationProvider() as DefaultLocationProvider).locationAnimatorOptions {
duration = 0
}
item.isChecked = true
return true
}
- 点击不带动画的菜单项时,设置位置动画持续时间为0。
kotlin
R.id.location_1s_animation -> {
(binding.mapView.location.getLocationProvider() as DefaultLocationProvider).locationAnimatorOptions {
duration = 1000
}
item.isChecked = true
return true
}
- 点击1秒动画的菜单项时,设置位置动画持续时间为1000毫秒。
kotlin
R.id.location_300ms_animation -> {
(binding.mapView.location.getLocationProvider() as DefaultLocationProvider).locationAnimatorOptions {
duration = 300
}
item.isChecked = true
return true
}
- 点击300毫秒动画的菜单项时,设置位置动画持续时间为300毫秒。
kotlin
R.id.action_accuracy_enabled -> {
binding.mapView.location.showAccuracyRing = true
item.isChecked = true
return true
}
- 点击启用准确度环的菜单项时,启用准确度显示。
kotlin
R.id.action_accuracy_disable -> {
binding.mapView.location.showAccuracyRing = false
item.isChecked = true
return true
}
- 点击禁用准确度环的菜单项时,禁用准确度显示。
kotlin
R.id.toggle_opacity -> {
val location = binding.mapView.location
location.locationPuck = location.locationPuck.run {
when (this) {
is LocationPuck3D -> copy(modelOpacity = if (modelOpacity == 1.0F) 0.5F else 1.0F)
is LocationPuck2D -> copy(opacity = if (opacity == 1.0F) 0.5F else 1.0F)
}
}
return true
}
- 点击切换不透明度的菜单项时,切换位置指示器的不透明度。
kotlin
R.id.move_to_bottom_slot -> {
val location = binding.mapView.location
location.slot = "bottom"
return true
}
- 点击移动到底部槽的菜单项时,将位置指示器移动到底部。
kotlin
R.id.reset_slot -> {
val location = binding.mapView.location
location.slot = null
return true
}
- 点击重置槽的菜单项时,将位置指示器的槽设置为
null
。
kotlin
else -> return super.onOptionsItemSelected(item)
- 如果未处理的菜单项,则调用父类的
onOptionsItemSelected
方法。
kotlin
private fun toggleCustomisedPuck() {
- 定义一个私有方法
toggleCustomisedPuck
,用于切换自定义位置指示器。
kotlin
binding.mapView.location.let {
when (it.locationPuck) {
- 使用
let
扩展函数在mapView.location
上执行操作。
kotlin
is LocationPuck3D -> it.locationPuck = LocationPuck2D(
- 如果当前位置指示器是 3D 类型,则将其切换为 2D 类型。
kotlin
topImage = ImageHolder.from(com.mapbox.maps.plugin.locationcomponent.R.drawable.mapbox_user_icon),
bearingImage = ImageHolder.from(com.mapbox.maps.plugin.locationcomponent.R.drawable.mapbox_user_bearing_icon),
shadowImage = ImageHolder.from(com.mapbox.maps.plugin.locationcomponent.R.drawable.mapbox_user_stroke_icon),
scaleExpression = interpolate {
linear()
zoom()
stop(0.0, 0.6) // 第一个 stop,值为 0.0,对应输出值 0.6
stop(20.0, 1.0) // 第二个 stop,值为 20.0,对应输出值 1.0
}.toJson()
- 为 2D 位置指示器设置图标和缩放表达式。
kotlin
is LocationPuck2D -> it.locationPuck = LocationPuck3D(
- 如果当前位置指示器是 2D 类型,则将其切换为 3D 类型。
kotlin
modelUri = "asset://sportcar.glb",
modelScale = listOf(10f, 10f, 10f),
modelTranslation = listOf(0.1f, 0.1f, 0.1f),
modelRotation = listOf(0.0f, 0.0f, 180.0f),
modelCastShadows = false,
modelReceiveShadows = false,
modelEmissiveStrength = 1.1f
- 为 3D 位置指示器设置模型的 URI、缩放、平移、旋转、阴影设置等属性。
kotlin
}
- 结束
let
块。
kotlin
private fun toggleMapStyle() {
- 定义一个私有方法
toggleMapStyle
,用于切换地图样式。
kotlin
val styleUrl = if (lastStyleUri == Style.DARK) Style.LIGHT else Style.DARK
- 检查当前样式,如果是黑暗模式,则切换到亮模式,反之亦然。
kotlin
binding.mapView.mapboxMap.loadStyle(styleUrl) {
lastStyleUri = styleUrl
}
- 加载新的样式并更新
lastStyleUri
。
kotlin
private fun toggleMapProjection() {
- 定义一个私有方法
toggleMapProjection
,用于切换地图投影。
kotlin
binding.mapView.mapboxMap.getStyle { style ->
- 获取当前地图样式。
kotlin
style.setProjection(
projection(
- 设置新的投影。
kotlin
when (style.getProjection()?.name) {
ProjectionName.MERCATOR -> ProjectionName.GLOBE
ProjectionName.GLOBE -> ProjectionName.MERCATOR
else -> ProjectionName.GLOBE
}
- 根据当前投影名称决定切换到哪种投影。
kotlin
)
)
- 结束投影设置。
kotlin
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
locationPermissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
- 重写权限请求结果处理方法,将结果传递给
locationPermissionHelper
。
kotlin
override fun onStart() {
super.onStart()
binding.mapView.location
.addOnIndicatorPositionChangedListener(onIndicatorPositionChangedListener)
}
- 在 Activity 启动时添加位置指示器位置变化的监听器。
kotlin
override fun onStop() {
super.onStop()
binding.mapView.location
.removeOnIndicatorPositionChangedListener(onIndicatorPositionChangedListener)
}
- 在 Activity 停止时移除位置指示器位置变化的监听器。
整个代码段的主要功能是设置一个地图应用,显示用户位置并允许用户与地图进行交互,例如点击、长按和切换样式等功能。希望这个逐句解释能帮助你更好地理解代码的结构和功能!如果有任何具体部分需要进一步解释,请告诉我!