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