Newer
Older
CasicSmartTube / app / src / main / java / com / casic / smarttube / fragment / HomePageFragment.kt
package com.casic.smarttube.fragment

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
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.FragmentHomeBinding
import com.casic.smarttube.model.MapDeviceModel
import com.casic.smarttube.model.ProjectGroupModel
import com.casic.smarttube.utils.RouteOnMap
import com.casic.smarttube.view.AddDeviceActivity
import com.casic.smarttube.vm.DeviceViewModel
import com.casic.smarttube.vm.ProjectGroupViewModel
import com.pengxh.kt.lite.adapter.NormalRecyclerAdapter
import com.pengxh.kt.lite.adapter.ViewHolder
import com.pengxh.kt.lite.base.KotlinBaseFragment
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog


class HomePageFragment : KotlinBaseFragment<FragmentHomeBinding>(), AMap.OnCameraChangeListener,
    AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener,
    AMap.OnMapClickListener {

    private val kTag = "HomePageFragment"
    private val geocoderSearch by lazy { GeocodeSearch(requireContext()) }
    private lateinit var aMap: AMap
    private lateinit var deviceViewModel: DeviceViewModel
    private lateinit var groupViewModel: ProjectGroupViewModel
    private lateinit var groupListAdapter: NormalRecyclerAdapter<ProjectGroupModel.DataModel>
    private var clickedMarker: Marker? = null

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

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

    override fun initViewBinding(
        inflater: LayoutInflater, container: ViewGroup?
    ): FragmentHomeBinding {
        return FragmentHomeBinding.inflate(inflater, container, false)
    }

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

            }

            override fun onRightClick() {
                requireContext().navigatePageTo<AddDeviceActivity>()
            }
        })
    }

    override fun observeRequestState() {
        groupViewModel.loadState.observe(this) { state ->
            when (state) {
                LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...")
                else -> LoadingDialog.dismiss()
            }
        }
    }

    override fun initOnCreate(savedInstanceState: Bundle?) {
        //地图初始化
        initMap(savedInstanceState)

        //默认显示所有设备
        deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
        deviceViewModel.mapDeviceModel.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()) {
                        //返回true代表当前位置在大陆、港澳地区,反之不在
                        val latitude = lat.toDouble()
                        val longitude = lng.toDouble()
                        if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
                            //缓存所有设备详情,点击Marker时候需要
                            deviceModels.add(device)
                            //分别缓存经、纬度
                            latitudeList.add(latitude)
                            longitudeList.add(longitude)
                            //将所有设备信息转化缓存为Marker点
                            allMarkerOptions.add(
                                MarkerOptions().position(LatLng(latitude, longitude))
                                    .title(device.devcode).snippet(device.modelName)
                            )
                        }
                    }
                }

                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)
            }
        }
        deviceViewModel.getMapDeviceList()

        groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java]
        groupViewModel.groupModel.observe(this) {
            if (it.code == 200) {
                bindRecyclerView(it)
            }
        }

        groupViewModel.groupDeviceModel.observe(this) {
            if (it.code == 200) {
                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()) {
                        //返回true代表当前位置在大陆、港澳地区,反之不在
                        val latitude = lat.toDouble()
                        val longitude = lng.toDouble()
                        if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
                            //分别缓存经、纬度
                            latitudeList.add(latitude)
                            longitudeList.add(longitude)
                        }
                    }
                }
                //计算所有点的中心点位置
                val latLng = LatLng(latitudeList[0], longitudeList[0])
                val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f)
                val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
                aMap.animateCamera(cameraUpdate)
            }
        }
    }

    private fun bindRecyclerView(it: ProjectGroupModel) {
        groupListAdapter = object : NormalRecyclerAdapter<ProjectGroupModel.DataModel>(
            R.layout.item_group_rv_l, it.data
        ) {
            override fun convertView(
                viewHolder: ViewHolder, position: Int, item: ProjectGroupModel.DataModel
            ) {
                viewHolder.setText(R.id.groupNameView, item.groupId)
                    .setText(R.id.totalDeviceNumView, item.totalDevice)
                    .setText(R.id.inUseDeviceNumView, item.alive)
                    .setText(R.id.notUseDeviceNumView, item.unalive)
                if (item.latGaode.isBlank() || item.lngGaode.isBlank()) {
                    viewHolder.setText(R.id.groupLocationView, "经纬度异常,无法查看具体位置")
                } else {
                    val point = LatLonPoint(item.latGaode.toDouble(), item.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) {
                                viewHolder.setText(
                                    R.id.groupLocationView,
                                    String.format("${result?.regeocodeAddress?.formatAddress}")
                                )
                            }
                        }

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

                        }
                    })
                }
            }
        }
        binding.homeRecyclerView.adapter = groupListAdapter
        groupListAdapter.setOnItemClickedListener(object :
            NormalRecyclerAdapter.OnItemClickedListener<ProjectGroupModel.DataModel> {
            override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) {
                // 根据groupId查询组下设备
                groupViewModel.getDeviceListByGroup(item.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?) {

    }

    //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
    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(requireContext()).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.obtainTubeLastData(device.groupId, device.devcode)
                deviceViewModel.lastDataModel.observe(requireActivity()) {
                    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("更新时间: 未知")
                    }
                }
                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
                                val temp = StringBuilder()
                                if (address!!.length > 16) {
                                    temp.append(address.substring(0, 14)).append("\r\n")
                                        .append(address.substring(16))
                                } else {
                                    temp.append(address)
                                }
                                locationView.text = String.format("详细位置: $temp")
                            }
                        }

                        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(requireContext()).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(requireContext())
                            return
                        }
                        RouteOnMap.startNavigation(requireContext(), snippet, position)
                    }

                    override fun onCancelClick() {

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

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

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

    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()
    }
}