Mapbox 地图 SDK for Android 的位置组件使您的应用能够观察、响应和显示用户的位置。
在您能够在地图上显示用户的位置之前,用户必须授权您的应用访问他们的位置。有关更多细节,请参见前面的权限处理部分。
位置组件
为了在地图上可视化用户的位置,您应该启用位置组件。有多种方法可以启用位置:
-
在您的 MapView XML 组件中直接使用属性
mapbox_locationComponentEnabled
:<com.mapbox.maps.MapView android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="match_parent" app:mapbox_locationComponentEnabled="true" app:mapbox_locationComponentPuckBearing="heading" />
-
通过调用位置组件的
enabled
方法进行编程:// Android View // Jetpack Compose setContentView(mapView) with(mapView) { location.locationPuck = createDefault2DPuck(withBearing = true) location.enabled = true location.puckBearing = PuckBearing.COURSE location.puckBearingEnabled = true viewport.transitionTo( targetState = viewport.makeFollowPuckViewportState(), transition = viewport.makeImmediateViewportTransition() ) }
位置组件利用 Maps SDK 中的两个专用图层来显示 2D 设备位置图标(使用图层 ID LOCATION_INDICATOR_LAYER
)或 3D 模型(使用图层 ID MODEL_LAYER
)。这些图层显示在地图内部,而不是作为 Android 视图覆盖在地图上。Mapbox 地图样式中的图层使您能够精确控制如何在地图上显示设备的位置。
默认情况下,Android 的 Maps SDK 提供一个带有蓝点和白圈的二维位置图标。
示例
显示用户在地图上的位置
使用默认位置图标在地图上显示用户的位置。
图标样式选项
有几种选项可以自定义位置图标的外观。您可以在 LocationComponentSettings
中查看完整列表。
您可以直接使用 LocationComponentPlugin
更改设置。例如,默认情况下脉冲效果是禁用的,但您可以通过将 true
传递给 pulsingEnabled
属性来启用该效果。
// Android View
class LocationComponentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val mapView = MapView(this)
setContentView(mapView)
with(mapView) {
location.enabled = true
location.pulsingEnabled = true
}
}
}
使用自定义图像
您还可以通过使用自定义图像 Drawable 来进一步自定义图标,以在地图上显示用户的位置。您可以通过 XML 属性或通过 LocationPuck
类以编程方式设置自定义位置图标样式。
以下是使用样式 XML 属性自定义位置图标外观的示例:
<com.mapbox.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:mapbox_locationComponentEnabled="true"
app:mapbox_locationComponentLocationPuck="location_puck_2_d"
app:mapbox_locationComponentLocationPuckLocationPuck2DTopImage="@drawable/custom_user_icon"
app:mapbox_locationComponentLocationPuckLocationPuck2DBearingImage="@drawable/custom_user_arrow"
app:mapbox_locationComponentLocationPuckLocationPuck2DShadowImage="@drawable/custom_user_puck_icon"
tools:context=".examples.LocationComponentActivity" />
以下是使用 LocationPuck
类以编程方式自定义位置图标外观的示例。创建一个 LocationPuck2D
或 LocationPuck3D
对象,并通过 LocationComponentPlugin#locationPuck
方法设置它。以下示例还根据地图的缩放级别使用 scaleExpression
指定图标的大小。
// Android View
mapView.location.locationPuck = LocationPuck2D(
topImage = ImageHolder.from(R.drawable.mapbox_user_icon), // ImageHolder 也接受 Bitmap
bearingImage = ImageHolder.from(R.drawable.mapbox_user_bearing_icon),
shadowImage = ImageHolder.from(R.drawable.mapbox_user_stroke_icon),
scaleExpression = interpolate {
linear()
zoom()
stop {
literal(0.0)
literal(0.6)
}
stop {
literal(20.0)
literal(1.0)
}
}.toJson()
)
您可以使用 createDefault2DPuck
函数恢复默认的二维图标。
设置图标朝向源
用户位置可以使用设备的朝向或设备的航向进行追踪。此选项在 LocationComponentSettings
中。
// 示例
mapView.location.puckBearing = PuckBearing.HEADING
mapView.location.puckBearing = PuckBearing.COURSE
位置跟踪
要使相机跟随位置图标,您可以使用 ViewportPlugin
,它在 mapView.viewport
可用。
ViewportPlugin
主要用于在地图上跟踪对象,但也可以通过自定义状态和过渡进行扩展。
视口状态
ViewportState
根据实现特定的规则生成相机更新(例如:跟踪动态位置数据源或显示预定义区域的静态概览)。
SDK 提供了两种 ViewportState
实现,均可以从 ViewportPlugin
实例化:
viewport.makeFollowPuckViewportState(options)
:此状态将地图相机与位置图标同步。viewport.makeOverviewViewportState(options)
:此状态使相机显示用户提供的几何形状。
除了使用这些内置实现,您还可以创建自己的实现并与 ViewportPlugin
一起使用。
视口过渡
ViewportTransition
定义如何过渡到目标 ViewportState
。
SDK 还提供了两种 ViewportTransition
实现,均可以从 ViewportPlugin
实例化:
viewport.makeDefaultViewportTransition(options)
:默认视口过渡使用动画将相机移动到目标状态。viewport.makeImmediateViewportTransition()
:立即视口过渡会将相机一次性移动到目标状态而不使用动画。
除了使用这些内置实现,您还可以创建自己的实现并与 ViewportPlugin
一起使用。
示例
// Android View
val viewportPlugin = mapView.viewport
// 过渡到 followPuckViewportState,使用默认过渡
val followPuckViewportState: FollowPuckViewportState = viewportPlugin.makeFollowPuckViewportState(
FollowPuckViewportStateOptions.Builder()
.bearing(FollowPuckViewportStateBearing.Constant(0.0))
.padding(EdgeInsets(200.0 * resources.displayMetrics.density, 0.0, 0.0, 0.0))
.build()
)
viewportPlugin.transitionTo(followPuckViewportState) { success ->
// 过渡完成,带有指示过渡是否成功的标志
}
// Android View
// 过渡到 overviewViewportState,使用立即过渡
val overviewViewportState: OverviewViewportState = viewportPlugin.makeOverviewViewportState(
OverviewViewportStateOptions.Builder()
.geometry(routePoints)
.padding(EdgeInsets(100.0, 100.0, 100.0, 100.0))
.build()
)
val immediateTransition = viewportPlugin.makeImmediateViewportTransition()
viewportPlugin.transitionTo(overviewViewportState, immediateTransition) { success ->
// 过渡完成,带有指示过渡是否成功的标志
}
位置提供者
LocationProvider
是 Mapbox Maps SDK 的一个接口,用于向 LocationComponentPlugin
提供位置更新。您可以通过调用 getLocationProvider()
访问位置组件中使用的当前位置提供者。
您可以注册自己的 LocationConsumer
来处理与地图上渲染位置图标相同的位置。如果您需要访问设备的原始位置,请参见“访问设备位置”。
使用 Google 的融合位置提供者
Maps SDK 还预先编译了对 Google 的融合位置提供者的支持。如果您的目标设备支持 Google Play 服务,请将 Google Play 位置服务依赖项添加到您的项目中,Maps SDK 将自动在您的应用中使用 Google 的融合位置提供者:
implementation("com.google.android.gms:play-services-location:21.0.1")
使用自定义位置提供者
您还可以提供自己的 LocationProvider
以与 LocationComponentPlugin
一起使用。使用 setLocationProvider(locationProvider: LocationProvider)
API 来替换默认实现。