From efe80d9ea8aecd5c6f808368a26488b09f9bded5 Mon Sep 17 00:00:00 2001 From: chenfufeng Date: Fri, 3 Feb 2023 17:37:51 +0800 Subject: [PATCH] =?UTF-8?q?[Opt]=E9=AB=98=E5=BE=B7=E7=9A=84=E5=B0=8F?= =?UTF-8?q?=E5=9C=B0=E5=9B=BE=E5=B0=81=E8=A3=85=E5=88=B0View=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/function/smp/view/SmallMapView.kt | 350 ++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/view/SmallMapView.kt diff --git a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/view/SmallMapView.kt b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/view/SmallMapView.kt new file mode 100644 index 0000000000..de31b43cd3 --- /dev/null +++ b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/view/SmallMapView.kt @@ -0,0 +1,350 @@ +package com.mogo.eagle.core.function.smp.view + +import android.content.Context +import android.graphics.Color +import android.os.Bundle +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.RelativeLayout +import androidx.annotation.UiThread +import com.amap.api.maps.* +import com.amap.api.maps.model.* +import com.mogo.cloud.commons.utils.CoordinateUtils +import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo +import com.mogo.eagle.core.data.config.FunctionBuildConfig +import com.mogo.eagle.core.data.map.MogoLatLng +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener +import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager.getGlobalPath +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ20ListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager +import com.mogo.eagle.core.function.map.R +import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils +import com.mogo.eagle.core.utilcode.mogo.MapAssetStyleUtils +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.UiThreadHandler +import mogo.telematics.pad.MessagePad +import java.util.* +import kotlin.math.floor + +class SmallMapView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : RelativeLayout(context, attrs, defStyleAttr), IMoGoChassisLocationGCJ02Listener, + IMoGoPlanningRottingListener, + IMoGoAutopilotStatusListener { + + private var mAMapNaviView: TextureMapView? = null + private var mAMap: AMap? = null + private var mCarMarker: Marker? = null + private var mStartMarker: Marker? = null + private var mEndMarker: Marker? = null + private val zoomLevel = 15 + private val mCoordinatesLatLng: MutableList = ArrayList() + private var mPolyline: Polyline? = null + private var mCameraUpdate: CameraUpdate? = null + private var mContext: Context? = null + private var mLocation: MogoLocation? = null + + private var autoPilotStatus = 0 + + companion object { + const val TAG = "SmallMapView" + } + + init { + try { + initView(context) + } catch (e: Exception) { + e.printStackTrace() + } + } + + // =================必须通知高德地图生命周期的变化================= + fun onCreateView(savedInstanceState: Bundle?) { + if (mAMapNaviView != null) { + mAMapNaviView!!.onCreate(savedInstanceState) + } + } + + fun onResume() { + if (mAMapNaviView != null) { + mAMapNaviView!!.onResume() + } + } + + fun onPause() { + if (mAMapNaviView != null) { + mAMapNaviView!!.onPause() + } + } + + fun onDestroy() { + if (mAMapNaviView != null) { + mAMapNaviView!!.onDestroy() + } + } + // =================必须通知高德地图生命周期的变化================= + + fun convert(coordinates: List) { + mCoordinatesLatLng.clear() + val latLngs = coordinateConverterFrom84ForList(mContext, coordinates) + mCoordinatesLatLng.addAll(latLngs) + } + + @UiThread + fun drawablePolyline() { + clearPolyline() + if (mAMap != null) { + if (mCoordinatesLatLng.size > 2) { + // 设置开始结束Marker位置 + mStartMarker!!.position = mCoordinatesLatLng[0] + mEndMarker!!.position = mCoordinatesLatLng[mCoordinatesLatLng.size - 1] + mStartMarker!!.setToTop() + mStartMarker!!.isVisible = true + mEndMarker!!.isVisible = true + mEndMarker!!.setToTop() + + + //存放所有点的经纬度 + val boundsBuilder = LatLngBounds.Builder() + for (i in mCoordinatesLatLng.indices) { + //把所有点都include进去(LatLng类型) + boundsBuilder.include(mCoordinatesLatLng[i]) + } + //第二个参数为四周留空宽度 + mAMap!!.animateCamera( + CameraUpdateFactory.newLatLngBounds( + boundsBuilder.build(), + 30 + ) + ) + // 绘制线 + mPolyline = mAMap!!.addPolyline( + PolylineOptions() + .addAll(mCoordinatesLatLng) + .color(Color.argb(255, 31, 127, 255)) + .width(12f) + ) + } + } + } + + @UiThread + fun clearPolyline() { + if (mPolyline != null) { + mPolyline!!.remove() + } + if (mStartMarker != null) { + mStartMarker!!.isVisible = false + } + if (mEndMarker != null) { + mEndMarker!!.isVisible = false + } + } + + private fun initView(context: Context) { + mContext = context + val smpView = LayoutInflater.from(context).inflate(R.layout.module_small_map_view, this) + mAMapNaviView = smpView.findViewById(R.id.aMapNaviView) + initAMapView() + + // 注册定位监听 + CallerChassisLocationGCJ20ListenerManager.addListener(TAG, this) + CallerPlanningRottingListenerManager.addListener(TAG, this) + CallerAutoPilotStatusListenerManager.addListener(TAG, this) + startTask() + } + + private fun initAMapView() { + mCameraUpdate = CameraUpdateFactory.zoomTo(zoomLevel.toFloat()) + mAMap = mAMapNaviView!!.map + // 关闭地图文字标注 + mAMap?.showMapText(false) + // 设置导航地图模式,aMap是地图控制器对象。 + mAMap?.mapType = AMap.MAP_TYPE_NIGHT + // 关闭显示实时路况图层,aMap是地图控制器对象。 + mAMap?.isTrafficEnabled = false + // 设置 锚点 图标 + mCarMarker = if (AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)) { + mAMap?.addMarker( + MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.map_bus_icon)) + .anchor(0.5f, 0.5f) + ) + } else { + mAMap?.addMarker( + MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.map_car_icon)) + .anchor(0.5f, 0.5f) + ) + } + mStartMarker = mAMap?.addMarker( + MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_dir_start)) + ) + mEndMarker = mAMap?.addMarker( + MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_dir_end)) + ) + // 加载自定义样式 + val customMapStyleOptions = CustomMapStyleOptions() + .setEnable(true) + .setStyleData(MapAssetStyleUtils.getAssetsStyle(context, "over_view_style.data")) + .setStyleExtraData( + MapAssetStyleUtils.getAssetsExtraStyle( + context, + "over_view_style_extra.data" + ) + ) + // 设置自定义样式 + mAMap?.setCustomMapStyle(customMapStyleOptions) + //设置希望展示的地图缩放级别 + mAMap?.moveCamera(mCameraUpdate) + // 设置地图的样式 + val uiSettings = mAMap?.uiSettings + uiSettings?.isZoomControlsEnabled = false // 地图缩放级别的交换按钮 + uiSettings?.setAllGesturesEnabled(false) // 所有手势 + uiSettings?.isMyLocationButtonEnabled = false // 显示默认的定位按钮 + uiSettings?.setLogoBottomMargin(-150) //设置Logo下边界距离屏幕底部的边距,设置为负值即可 + mAMap?.setOnMapLoadedListener(AMap.OnMapLoadedListener { + CallerLogger.d( + SceneConstant.M_MAP + TAG, + "smp---onMapLoaded" + ) + // 加载自定义样式 + val customMapStyleOptions1 = CustomMapStyleOptions() + .setEnable(true) + .setStyleData(MapAssetStyleUtils.getAssetsStyle(context, "over_view_style.data")) + .setStyleExtraData( + MapAssetStyleUtils.getAssetsExtraStyle( + context, + "over_view_style_extra.data" + ) + ) + // 设置自定义样式 + mAMap?.setCustomMapStyle(customMapStyleOptions1) + mAMapNaviView!!.map.setPointToCenter( + mAMapNaviView!!.width / 2, + mAMapNaviView!!.height / 2 + ) + }) + } + + private fun startTask() { + val mTimer = Timer() + mTimer.schedule(UpdateLocationTask(), 1000, 200) + } + + private inner class UpdateLocationTask : TimerTask() { + override fun run() { + if (mLocation != null) { + if (mCarMarker == null) { + mCarMarker = mAMap!!.addMarker( + MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_my_location_logo)) + .anchor(0.5f, 0.5f) + ) + } + if (mCarMarker == null) { + return + } + val currentLatLng = LatLng(mLocation!!.latitude, mLocation!!.longitude) + val bearing = floor(mLocation!!.heading).toFloat() + //更新车辆位置 + mCarMarker!!.position = currentLatLng + if (mCoordinatesLatLng.size > 1) { + // 结束位置 + val endLatLng = mCoordinatesLatLng[mCoordinatesLatLng.size - 1] + val calculateDistance = CoordinateUtils.calculateLineDistance( + endLatLng.latitude, endLatLng.longitude, + currentLatLng.latitude, currentLatLng.longitude + ) + CallerLogger.d( + SceneConstant.M_MAP + TAG, + "calculateDistance=$calculateDistance" + ) + if (calculateDistance <= 5) { + clearPolyline() + mCoordinatesLatLng.clear() + } + } + val cameraPosition: CameraPosition = + CameraPosition.Builder().target(mCarMarker!!.position).tilt(0f).bearing(bearing) + .zoom(zoomLevel.toFloat()).build() + mAMap?.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)) + } + } + } + + private fun coordinateConverterFrom84(mContext: Context?, mogoLatLng: MogoLatLng): LatLng { + val mCoordinateConverter = CoordinateConverter(mContext) + mCoordinateConverter.from(CoordinateConverter.CoordType.GPS) + mCoordinateConverter.coord(LatLng(mogoLatLng.lat, mogoLatLng.lon)) + return mCoordinateConverter.convert() + } + + private fun coordinateConverterFrom84ForList( + mContext: Context?, + mogoLatLngList: List + ): List { + val list: MutableList = ArrayList() + for (m in mogoLatLngList) { + val mogoLatLng = coordinateConverterFrom84(mContext, m) + list.add(mogoLatLng) + } + return list + } + + override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) { + if (mogoLocation == null) { + return + } + mLocation = mogoLocation + } + + override fun onAutopilotStatusResponse(autoPilotStatusInfo: AutopilotStatusInfo) { + val tempStatus = autoPilotStatusInfo.pilotmode + if (tempStatus != 1) { + UiThreadHandler.post { + clearPolyline() + } + } else if (tempStatus == 1 && autoPilotStatus == 0) { + getGlobalPath() + } + autoPilotStatus = tempStatus + } + + override fun onAutopilotRotting(globalPathResp: MessagePad.GlobalPathResp?) { + if (globalPathResp == null || globalPathResp.wayPointsList.size == 0) { + return + } + val latLngList: MutableList = ArrayList() + for (routeModel in globalPathResp.wayPointsList) { + latLngList.add(MogoLatLng(routeModel.latitude, routeModel.longitude)) + } + if (latLngList.size > 0) { + UiThreadHandler.post { + convert(latLngList) + drawablePolyline() + } + } else { + UiThreadHandler.post { + clearPolyline() + } + } + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + // 注册定位监听 + CallerChassisLocationGCJ20ListenerManager.removeListener(TAG) + CallerPlanningRottingListenerManager.removeListener(TAG) + CallerAutoPilotStatusListenerManager.removeListener(TAG) + } +} \ No newline at end of file