Newer
Older
CasicSmartTube / app / src / main / java / com / casic / smarttube / view / GroupDeviceMapActivity.kt
package com.casic.smarttube.view

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import androidx.lifecycle.ViewModelProvider
import com.amap.api.maps.AMap
import com.amap.api.maps.AMapOptions
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.CoordinateConverter
import com.amap.api.maps.model.CameraPosition
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.MarkerOptions
import com.amap.api.services.core.LatLonPoint
import com.amap.api.services.geocoder.GeocodeResult
import com.amap.api.services.geocoder.GeocodeSearch
import com.amap.api.services.geocoder.RegeocodeQuery
import com.amap.api.services.geocoder.RegeocodeResult
import com.casic.smarttube.R
import com.casic.smarttube.databinding.ActivityGroupDeviceMapBinding
import com.casic.smarttube.extensions.initImmersionBar
import com.casic.smarttube.model.MapDeviceModel
import com.casic.smarttube.utils.RouteOnMap
import com.casic.smarttube.vm.DeviceViewModel
import com.casic.smarttube.vm.ProjectGroupViewModel
import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.extensions.wrapLine
import com.pengxh.kt.lite.utils.ActivityStackManager
import com.pengxh.kt.lite.utils.LiteKitConstant
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog

class GroupDeviceMapActivity : KotlinBaseActivity<ActivityGroupDeviceMapBinding>(),
    AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter,
    AMap.OnInfoWindowClickListener, AMap.OnMapClickListener {

    private val context = this
    private val geocoderSearch by lazy { GeocodeSearch(this) }
    private lateinit var aMap: AMap
    private lateinit var groupViewModel: ProjectGroupViewModel
    private lateinit var deviceViewModel: DeviceViewModel
    private var clickedMarker: Marker? = null

    /**
     * 自定义Marker弹出框
     * */
    private var infoView: View? = null

    /**
     * 所有设备列表信息集合
     * */
    private var deviceModels: MutableList<MapDeviceModel.DataModel> = ArrayList()

    override fun initViewBinding(): ActivityGroupDeviceMapBinding {
        return ActivityGroupDeviceMapBinding.inflate(layoutInflater)
    }

    override fun observeRequestState() {
        binding.rootView.initImmersionBar(this, false, R.color.mainThemeColor)
    }

    override fun setupTopBarLayout() {
        binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener {
            override fun onLeftClick() {
                finish()
            }

            override fun onRightClick() {

            }
        })
    }

    override fun initOnCreate(savedInstanceState: Bundle?) {
        ActivityStackManager.addActivity(this)
        val groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!!

        //地图初始化
        initMap(savedInstanceState)

        deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
        deviceViewModel.mapDeviceData.observe(this) {
            if (it.code == 200) {
                it.data.forEach { device ->
                    val lat = device.latGaode.toString()
                    val lng = device.lngGaode.toString()
                    if (lat.isNotBlank() && lng.isNotBlank()) {
                        val latitude = lat.toDouble()
                        val longitude = lng.toDouble()
                        if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
                            //缓存所有设备详情,点击Marker时候需要
                            deviceModels.add(device)
                        }
                    }
                }
            }
        }
        deviceViewModel.getMapDeviceList(this)

        groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java]
        groupViewModel.groupDeviceData.observe(this) {
            if (it.code == 200) {
                val allMarkerOptions = ArrayList<MarkerOptions>()
                val latitudeList = ArrayList<Double>()
                val longitudeList = ArrayList<Double>()
                it.data.forEach { device ->
                    val lat = device.latGaode.toString()
                    val lng = device.lngGaode.toString()
                    if (lat.isNotBlank() && lng.isNotBlank()) {
                        val latitude = lat.toDouble()
                        val longitude = lng.toDouble()
                        if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
                            //分别缓存经、纬度
                            latitudeList.add(latitude)
                            longitudeList.add(longitude)
                            //将所有设备信息转化缓存为Marker点
                            val latLng = LatLng(latitude, longitude)
                            allMarkerOptions.add(MarkerOptions().position(latLng))
                        }
                    }
                }

                allMarkerOptions.forEach { marker ->
                    aMap.addMarker(marker)
                }

                val latLng = LatLng(latitudeList[0], longitudeList[0])
                val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f)
                val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
                aMap.animateCamera(cameraUpdate, 1500, null)
            }
        }
        groupViewModel.getDeviceListByGroup(this, groupId)
    }

    override fun initEvent() {

    }

    private fun initMap(savedInstanceState: Bundle?) {
        binding.mapView.onCreate(savedInstanceState)
        aMap = binding.mapView.map
        aMap.mapType = AMap.MAP_TYPE_NORMAL
        val uiSettings = aMap.uiSettings
        uiSettings.isCompassEnabled = true
        uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER
        uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度
        uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位

        // 地图缩放监听
        aMap.addOnCameraChangeListener(this)
        // marker 点击事件监听
        aMap.addOnMarkerClickListener(this)
        // 点击marker弹出自定义popup
        aMap.setInfoWindowAdapter(this)
        //信息窗点击事件
        aMap.addOnInfoWindowClickListener(this)
        //地图点击事件,用于隐藏infoWindow
        aMap.setOnMapClickListener(this)
    }

    override fun onCameraChange(cameraPosition: CameraPosition?) {

    }

    override fun onCameraChangeFinish(cameraPosition: CameraPosition?) {

    }

    override fun onMarkerClick(marker: Marker?): Boolean {
        marker?.apply {
            clickedMarker = this
            if (isInfoWindowShown) {
                hideInfoWindow()
            } else {
                showInfoWindow()
            }
        }
        return true
    }

    override fun onMapClick(p0: LatLng?) {
        clickedMarker?.apply {
            if (isInfoWindowShown) {
                hideInfoWindow()
            }
        }
    }

    override fun getInfoWindow(marker: Marker?): View? {
        if (infoView == null) {
            infoView = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null)
        }
        marker?.apply {
            renderWindow(this, infoView!!)
        }
        return infoView
    }

    private fun renderWindow(marker: Marker, view: View) {
        //反射得到popup里面的控件对象
        val deviceCodeView = view.findViewById<TextView>(R.id.deviceCodeView)
        val deviceModelView = view.findViewById<TextView>(R.id.deviceModelView)
        val deviceValueView = view.findViewById<TextView>(R.id.deviceValueView)
        val updateTimeView = view.findViewById<TextView>(R.id.updateTimeView)
        val locationView = view.findViewById<TextView>(R.id.locationView)

        //绑定数据
        val clicked = marker.position
        deviceModels.forEach { device ->
            if (clicked.latitude == device.latGaode!!.toDouble() && clicked.longitude == device.lngGaode!!.toDouble()) {
                deviceCodeView.text = String.format("设备编号: ${device.devcode}")
                deviceModelView.text = String.format("设备模型: ${device.modelName}")

                deviceViewModel.lastDataData.observe(this) {
                    if (it.code == 200) {
                        deviceValueView.text = String.format("最新浓度: ${it.data.strength}")
                        updateTimeView.text = String.format("更新时间: ${it.data.uptime}")
                    } else {
                        deviceValueView.text = String.format("最新浓度: 未知")
                        updateTimeView.text = String.format("更新时间: 未知")
                    }
                }
                //获取设备最新浓度信息
                deviceViewModel.getTubeLastData(context, device.groupId, device.devcode)

                if (device.latGaode.isBlank() || device.lngGaode.isBlank()) {
                    locationView.text = "经纬度异常,无法查看具体位置"
                } else {
                    val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble())
                    val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP)
                    geocoderSearch.getFromLocationAsyn(queryParam)
                    geocoderSearch.setOnGeocodeSearchListener(object :
                        GeocodeSearch.OnGeocodeSearchListener {
                        override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) {
                            if (rCode == 1000) {
                                val address = result?.regeocodeAddress?.formatAddress
                                locationView.text =
                                    String.format("详细位置: ${address?.wrapLine(14)}")
                            }
                        }

                        override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) {

                        }
                    })
                }
            }
        }
    }

    /**
     * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
     * */
    override fun getInfoContents(p0: Marker?): View? = null

    override fun onInfoWindowClick(marker: Marker?) {
        marker?.apply {
            AlertControlDialog.Builder().setContext(context).setTitle("操作提示")
                .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定")
                .setOnDialogButtonClickListener(object :
                    AlertControlDialog.OnDialogButtonClickListener {
                    override fun onConfirmClick() {
                        val lat = position.latitude.toString()
                        val lng = position.longitude.toString()
                        if (lat.isBlank() || lng.isBlank()) {
                            "窨井经纬度异常,无法开启导航".show(context)
                            return
                        }
                        RouteOnMap.startNavigation(context, snippet, position)
                    }

                    override fun onCancelClick() {

                    }
                }).build().show()
        }
    }

    /***以下是地图生命周期管理************************************************************************/

    override fun onResume() {
        super.onResume()
        binding.mapView.onResume()
    }

    override fun onPause() {
        super.onPause()
        binding.mapView.onPause()
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        binding.mapView.onSaveInstanceState(outState)
    }

    override fun onDestroy() {
        super.onDestroy()
        binding.mapView.onDestroy()
    }
}