[bus][shuttle][passenger]

[代码整理][地图抽取]
This commit is contained in:
yangyakun
2024-02-04 16:56:53 +08:00
parent 7d10603da6
commit c3c8bad874
42 changed files with 343 additions and 1928 deletions

View File

@@ -0,0 +1,23 @@
package com.mogo.och.common.module.wigets.mapdirectionview;
/**
* @author xiaoyuzhou
* @date 2021/6/24 11:33 上午
*/
public interface IMapDirectionView {
/**
* 绘制路径线
*/
void drawablePolyline();
/**
* 清除路径线
*/
void clearPolyline();
/**
* 设置路径中起终点marker
*/
void setLineMarker();
}

View File

@@ -0,0 +1,394 @@
package com.mogo.och.common.module.wigets.mapdirectionview
import android.content.Context
import android.os.Bundle
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.RelativeLayout
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import com.amap.api.maps.AMap
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.TextureMapView
import com.amap.api.maps.model.BitmapDescriptor
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.CameraPosition
import com.amap.api.maps.model.CustomMapStyleOptions
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.LatLngBounds
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.MarkerOptions
import com.amap.api.maps.model.Polyline
import com.amap.api.maps.model.PolylineOptions
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager
import com.mogo.eagle.core.utilcode.mogo.MapAssetStyleUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.common.module.R
import com.mogo.och.shuttle.passenger.ui.mapdirectionview.MapDirectionViewModel
import me.jessyan.autosize.utils.AutoSizeUtils
/**
* 乘客屏小地图
*/
class MapDirectionView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr), IMoGoChassisLocationGCJ02Listener,
IMapDirectionView, AMap.OnCameraChangeListener,
MapDirectionViewModel.ItineraryViewCallback {
companion object {
//小地图名称
const val TAG = "BusPassengerMapDirectionView"
}
private var mapStylePath: String? = null
private var mapStyleExtraPath: String? = null
private var carDrawable: Int = -1
private var compassDrawable: Int = -1
private var startPointDrawable: Int = -1
private var endPointDrawable: Int = -1
private var arrivedDrawable: Int = -1
private var unArrivedDrawable: Int = -1
private var resetDrawableMarginRight: Int = -1
private var resetDrawableMarginBottom: Int = -1
private var leftPadding: Int = 100
private var topPadding: Int = 100
private var rightPadding: Int = 100
private var bottomPadding: Int = 100
private lateinit var mAMapNaviView: TextureMapView
private lateinit var mAMap: AMap
private var mPolyline: Polyline? = null
private val mLineMarkers: MutableList<Marker> = ArrayList()
private lateinit var mCarMarker: Marker
// 除了开始站点和结束站点的中间站点 用来设置图标和地图范围圈定
private val mLineStationLatLng: MutableList<LatLng> = ArrayList() //站点坐标数据
var textureList: MutableList<BitmapDescriptor?> = ArrayList()
var texIndexList: MutableList<Int> = ArrayList()
private var mArrivedRes: BitmapDescriptor? = null
private var mUnArrivedRes: BitmapDescriptor? = null
private var mStartStationPoint: BitmapDescriptor? = null
private var mEndStationPoint: BitmapDescriptor? = null
private var mArrivedStationPoint: BitmapDescriptor? = null
private var mUArrivedStationPoint: BitmapDescriptor? = null
private val routeArrived: MutableList<LatLng> = ArrayList()
private val routeArriving: MutableList<LatLng> = ArrayList()
private var location: MogoLocation? = null
init {
try {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.MapDirectionView)
mapStylePath = typedArray.getString(R.styleable.MapDirectionView_mapStylePath)
mapStyleExtraPath = typedArray.getString(R.styleable.MapDirectionView_mapStyleExtraPath)
carDrawable = typedArray.getResourceId(R.styleable.MapDirectionView_carDrawable, -1)
compassDrawable = typedArray.getResourceId(R.styleable.MapDirectionView_compassDrawable, -1)
startPointDrawable =
typedArray.getResourceId(R.styleable.MapDirectionView_startPointDrawable, -1)
endPointDrawable =
typedArray.getResourceId(R.styleable.MapDirectionView_endPointDrawable, -1)
arrivedDrawable = typedArray.getResourceId(R.styleable.MapDirectionView_arrivedDrawable, -1)
unArrivedDrawable =
typedArray.getResourceId(R.styleable.MapDirectionView_unArrivedDrawable, -1)
resetDrawableMarginRight = typedArray.getResourceId(
R.styleable.MapDirectionView_resetDrawableMarginRight,
AutoSizeUtils.dp2px(context, 40f)
)
resetDrawableMarginBottom = typedArray.getResourceId(
R.styleable.MapDirectionView_resetDrawableMarginBottom,
AutoSizeUtils.dp2px(context, 40f)
)
leftPadding = typedArray.getInt(R.styleable.MapDirectionView_leftPadding, 100)
topPadding = typedArray.getInt(R.styleable.MapDirectionView_topPadding, 100)
rightPadding = typedArray.getInt(R.styleable.MapDirectionView_rightPadding, 100)
bottomPadding = typedArray.getInt(R.styleable.MapDirectionView_bottomPadding, 100)
typedArray.recycle()
initView(context)
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun initView(context: Context) {
d(SceneConstant.M_BUS_P + TAG, "initView")
val smpView = LayoutInflater.from(context).inflate(R.layout.shuttle_p_jl_map_view, this)
mAMapNaviView = smpView.findViewById<View>(R.id.bus_p_line_amap_view) as TextureMapView
initAMapView()
// 注册定位监听
CallerChassisLocationGCJ02ListenerManager.addListener(TAG, 1, this)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
// 注册定位监听
CallerChassisLocationGCJ02ListenerManager.removeListener(TAG)
}
private fun initAMapView() {
mAMap = mAMapNaviView.map
// 设置导航地图模式aMap是地图控制器对象。
mAMap.mapType = AMap.MAP_TYPE_NIGHT
// 关闭显示实时路况图层aMap是地图控制器对象。
mAMap.isTrafficEnabled = false
// 设置 锚点 图标
mCarMarker = mAMap.addMarker(
MarkerOptions().icon(
BitmapDescriptorFactory.fromResource(if (carDrawable != -1) carDrawable else R.drawable.common_map_car))
.anchor(0.5f, 0.5f)
)
mArrivedRes = BitmapDescriptorFactory.fromResource(if (arrivedDrawable != -1) arrivedDrawable else R.drawable.taxi_map_arrow_arrived)
mUnArrivedRes = BitmapDescriptorFactory.fromResource(if (unArrivedDrawable != -1) unArrivedDrawable else R.drawable.taxi_map_arrow_un_arrive)
mStartStationPoint = BitmapDescriptorFactory.fromResource(if (startPointDrawable != -1) startPointDrawable else R.drawable.common_map_start_point)
mEndStationPoint = BitmapDescriptorFactory.fromResource(if (endPointDrawable != -1) endPointDrawable else R.drawable.common_map_end_point)
mArrivedStationPoint = BitmapDescriptorFactory.fromResource(if (endPointDrawable != -1) endPointDrawable else R.drawable.common_map_arrived_point)
mUArrivedStationPoint = BitmapDescriptorFactory.fromResource(if (endPointDrawable != -1) endPointDrawable else R.drawable.common_map_unarrived_point)
// 加载自定义样式
val customMapStyleOptions = CustomMapStyleOptions().setEnable(true)
if (!mapStylePath.isNullOrEmpty() && !mapStyleExtraPath.isNullOrEmpty()) {
customMapStyleOptions.styleData =
MapAssetStyleUtils.getAssetsStyle(context, mapStylePath)
customMapStyleOptions.styleExtraData =
MapAssetStyleUtils.getAssetsExtraStyle(context, mapStyleExtraPath)
}
// 设置自定义样式
mAMap.setCustomMapStyle(customMapStyleOptions)
// 设置地图的样式
mAMap.uiSettings.apply {
isZoomControlsEnabled = false // 地图缩放级别的交换按钮
setAllGesturesEnabled(true) // 所有手势
isMyLocationButtonEnabled = false // 显示默认的定位按钮
setLogoBottomMargin(-150) //设置Logo下边界距离屏幕底部的边距,设置为负值即可
}
mAMap.setOnMapLoadedListener {
d(SceneConstant.M_BUS_P + TAG, "smp---onMapLoaded")
// 加载自定义样式
val options = CustomMapStyleOptions().setEnable(true)
if (!mapStylePath.isNullOrEmpty() && !mapStyleExtraPath.isNullOrEmpty()) {
options.styleData =
MapAssetStyleUtils.getAssetsStyle(context, mapStylePath)
options.styleExtraData =
MapAssetStyleUtils.getAssetsExtraStyle(context, mapStyleExtraPath)
}
// 设置自定义样式
mAMap.setCustomMapStyle(options)
mAMapNaviView.map.setPointToCenter(
mAMapNaviView.width / 2,
mAMapNaviView.height / 2
)
}
//设置地图状态的监听接口
mAMap.setOnCameraChangeListener(this)
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
val viewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(MapDirectionViewModel::class.java)
}
viewModel?.setDistanceCallback(this)
}
fun clearMapView() {
UiThreadHandler.post( {
clearPolyline()
clearCoordinatesLatLng()
}, UiThreadHandler.MODE.QUEUE)
}
override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) {
if (mogoLocation == null) {
return
}
val currentLatLng = LatLng(mogoLocation.latitude, mogoLocation.longitude)
//更新车辆位置
mCarMarker.rotateAngle = (360 - mogoLocation.heading).toFloat()
mCarMarker.position = currentLatLng
mCarMarker.setToTop()
try {
//圈定地图显示范围
val boundsBuilder = LatLngBounds.Builder()
routeArrived.forEach {
boundsBuilder.include(it)
}
routeArriving.forEach {
boundsBuilder.include(it)
}
mLineStationLatLng.forEach {
boundsBuilder.include(it)
}
boundsBuilder.include(currentLatLng)
mAMap.moveCamera(
CameraUpdateFactory.newLatLngBoundsRect(
boundsBuilder.build(),
100,
100,
100,
100
)
)
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun drawablePolyline() {
if (routeArrived.isEmpty() && routeArriving.isEmpty()) {
d(SceneConstant.M_TAXI + TAG, "没有点")
return
}
try {
texIndexList.clear()
val allPoints = ArrayList(routeArrived)
for (i in routeArrived.indices) {
if (routeArrived.size > 1 && i < routeArrived.size - 1) {
texIndexList.add(0)
}
}
texIndexList.add(0)
location?.let {
allPoints.add(LatLng(it.latitude, it.longitude))
}
allPoints.addAll(routeArriving)
for (ignored in routeArrived) {
texIndexList.add(1)
}
mPolyline?.let {
it.points = allPoints
it.options.customTextureIndex = texIndexList
return
}
if (textureList.isEmpty()) {
textureList.add(mArrivedRes)
textureList.add(mUnArrivedRes)
}
//设置线段纹理
val polylineOptions = PolylineOptions().apply {
addAll(allPoints)
isUseTexture = true
width(15f)
lineCapType(PolylineOptions.LineCapType.LineCapRound)
customTextureList = textureList
customTextureIndex = texIndexList
}
// 绘制线
mPolyline = mAMap.addPolyline(polylineOptions)
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun clearPolyline() {
mPolyline?.remove()
mPolyline = null
}
override fun setLineMarker() {}
fun clearCoordinatesLatLng() {
textureList.clear()
texIndexList.clear()
routeArrived.clear()
routeArriving.clear()
mLineStationLatLng.clear()
d(SceneConstant.M_BUS_P + TAG, " mCoordinatesLatLng.clear ")
}
fun onCreateView(savedInstanceState: Bundle?) {
mAMapNaviView.onCreate(savedInstanceState)
}
fun onResume() {
mAMapNaviView.onResume()
}
fun onPause() {
mAMapNaviView.onPause()
}
fun onDestroy() {
mAMapNaviView.onDestroy()
}
override fun setCoordinatesLatLng(
routeArrived: List<LatLng>,
routeArriving: List<LatLng>,
location: MogoLocation?
) {
this.routeArrived.clear()
this.routeArrived.addAll(routeArrived)
this.routeArriving.clear()
this.routeArriving.addAll(routeArriving)
this.location = location
UiThreadHandler.post({
drawablePolyline()
}, UiThreadHandler.MODE.QUEUE)
}
fun clearLineMarkers() {
for (i in mLineMarkers.indices) {
mLineMarkers[i].isVisible = false
mLineMarkers[i].remove()
}
mLineMarkers.clear()
}
// 设置站点
fun setLinePointMarkerAndDraw(mLineStationsList: List<LatLng>, currentIndex: Int) {
clearLineMarkers()
mLineStationLatLng.clear()
mLineStationLatLng.addAll(mLineStationsList)
if (mLineStationsList.isNotEmpty()) {
// 起点marker, 终点marker, 过站marker, 未过站marker
val size = mLineStationsList.size
val mStartMarker = mAMap.addMarker(
MarkerOptions()
.icon(mStartStationPoint)
)
val mEndMarker = mAMap.addMarker(MarkerOptions().icon(mEndStationPoint))
mStartMarker.position = mLineStationsList[0]
mLineMarkers.add(0, mStartMarker)
for (i in mLineStationsList.indices) {
if (currentIndex <= i && i < size - 1 && i > 0) { //未到达
val unArrivedMarker = mAMap.addMarker(MarkerOptions().icon(mUArrivedStationPoint))
unArrivedMarker.position = mLineStationsList[i]
mLineMarkers.add(i, unArrivedMarker)
} else if (i in 1 until currentIndex) {
val arrivedMarker = mAMap.addMarker(MarkerOptions().icon(mArrivedStationPoint))
arrivedMarker.position = mLineStationsList[i]
mLineMarkers.add(i, arrivedMarker)
}
}
mEndMarker.position = mLineStationsList[size - 1]
mLineMarkers.add(size - 1, mEndMarker)
}
}
override fun onCameraChange(cameraPosition: CameraPosition) {
}
override fun onCameraChangeFinish(cameraPosition: CameraPosition) {}
}

View File

@@ -0,0 +1,60 @@
package com.mogo.och.shuttle.passenger.ui.mapdirectionview
import androidx.lifecycle.ViewModel
import com.amap.api.maps.model.LatLng
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.common.module.manager.distancemamager.ITrajectoryListener
import com.mogo.och.common.module.manager.distancemamager.TrajectoryAndDistanceManager
class MapDirectionViewModel: ViewModel(), ITrajectoryListener {
private val TAG = MapDirectionViewModel::class.java.simpleName
private var viewCallback: ItineraryViewCallback?=null
init {
TrajectoryAndDistanceManager.addTrajectoryListener(TAG,this)
}
fun setDistanceCallback(viewCallback: ItineraryViewCallback){
this.viewCallback = viewCallback
}
override fun onCleared() {
super.onCleared()
this.viewCallback = null
TrajectoryAndDistanceManager.removeListener(TAG)
}
interface ItineraryViewCallback{
fun setCoordinatesLatLng(routeArrived: List<LatLng>, routeArriving: List<LatLng>, location: MogoLocation?)
}
override fun trajectoryCallback(
routeArrivied: MutableList<MogoLocation>,
routeArriving: MutableList<MogoLocation>,
location: MogoLocation
) {
val routeArrivedTemp: MutableList<LatLng> = ArrayList()
val routeArrivingTemp: MutableList<LatLng> = ArrayList()
var temp: LatLng
for (mogoLocation in routeArrivied) {
temp = LatLng(mogoLocation.latitude, mogoLocation.longitude)
routeArrivedTemp.add(temp)
}
for (mogoLocation in routeArriving) {
temp = LatLng(mogoLocation.latitude, mogoLocation.longitude)
routeArrivingTemp.add(temp)
}
this.viewCallback?.setCoordinatesLatLng(
routeArrivedTemp,
routeArrivingTemp,
location
)
CallerLogger.d(TAG,"已经走过的点routeArrivied:${routeArrivied.size} 未走过的点routeArriving${routeArriving.size}")
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent">
<com.amap.api.maps.TextureMapView
android:id="@+id/bus_p_line_amap_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -61,4 +61,31 @@
<attr name="customGap" format="float" />
<attr name="useCustomGap" format="boolean"/>
</declare-styleable>
<declare-styleable name="MapDirectionView">
<!-- 地图样式asset目录下的路径 -->
<attr name="mapStylePath" format="string" />
<attr name="mapStyleExtraPath" format="string" />
<!-- 自车模型图片 -->
<attr name="carDrawable" format="reference" />
<!-- 罗盘图片 -->
<attr name="compassDrawable" format="reference" />
<!-- 起点图片 -->
<attr name="startPointDrawable" format="reference" />
<!-- 终点图片 -->
<attr name="endPointDrawable" format="reference" />
<!-- 已走过路线的图片 -->
<attr name="arrivedDrawable" format="reference" />
<!-- 未走过路线的图片 -->
<attr name="unArrivedDrawable" format="reference" />
<!-- 重置位置图片右面margin -->
<attr name="resetDrawableMarginRight" format="dimension" />
<!-- 重置位置图片下面margin -->
<attr name="resetDrawableMarginBottom" format="dimension" />
<!-- 规定屏幕范围的padding -->
<attr name="leftPadding" format="integer" />
<attr name="topPadding" format="integer" />
<attr name="rightPadding" format="integer" />
<attr name="bottomPadding" format="integer" />
</declare-styleable>
</resources>