2-4位置服务示例

下面的代码给出了位置服务的代码示例(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 停止时移除位置指示器位置变化的监听器。

整个代码段的主要功能是设置一个地图应用,显示用户位置并允许用户与地图进行交互,例如点击、长按和切换样式等功能。希望这个逐句解释能帮助你更好地理解代码的结构和功能!如果有任何具体部分需要进一步解释,请告诉我!

相关推荐
每次的天空1 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭2 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日3 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安3 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑3 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟7 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡9 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi009 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil10 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你10 小时前
Android View的绘制原理详解
android