diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 2e490c3..f93caaf 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -16,7 +16,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -25,6 +24,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { @@ -143,8 +143,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 2e490c3..f93caaf 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -16,7 +16,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -25,6 +24,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { @@ -143,8 +143,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index b393c0b..e9befb2 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView @@ -156,8 +156,8 @@ override fun observeRequestState() { groupViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 2e490c3..f93caaf 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -16,7 +16,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -25,6 +24,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { @@ -143,8 +143,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index b393c0b..e9befb2 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView @@ -156,8 +156,8 @@ override fun observeRequestState() { groupViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 47c0af6..a0025db 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -10,7 +10,6 @@ import com.casic.smarttube.extensions.getQuarterOfYear import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -51,8 +51,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 2e490c3..f93caaf 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -16,7 +16,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -25,6 +24,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { @@ -143,8 +143,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index b393c0b..e9befb2 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView @@ -156,8 +156,8 @@ override fun observeRequestState() { groupViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 47c0af6..a0025db 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -10,7 +10,6 @@ import com.casic.smarttube.extensions.getQuarterOfYear import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -51,8 +51,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt index f947b2c..7287bff 100644 --- a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.databinding.ActivityLoginBinding import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.vm.AuthenticateViewModel @@ -14,6 +13,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues class LoginActivity : KotlinBaseActivity() { @@ -45,11 +45,11 @@ override fun observeRequestState() { authenticateViewModel.loadState.observe(this) { - LoadingDialogHub.show(this, "登录中,请稍后") + LoadingDialog.show(this, "登录中,请稍后") } loginViewModel.loadState.observe(this) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 2e490c3..f93caaf 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -16,7 +16,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -25,6 +24,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { @@ -143,8 +143,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index b393c0b..e9befb2 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView @@ -156,8 +156,8 @@ override fun observeRequestState() { groupViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 47c0af6..a0025db 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -10,7 +10,6 @@ import com.casic.smarttube.extensions.getQuarterOfYear import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -51,8 +51,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt index f947b2c..7287bff 100644 --- a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.databinding.ActivityLoginBinding import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.vm.AuthenticateViewModel @@ -14,6 +13,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues class LoginActivity : KotlinBaseActivity() { @@ -45,11 +45,11 @@ override fun observeRequestState() { authenticateViewModel.loadState.observe(this) { - LoadingDialogHub.show(this, "登录中,请稍后") + LoadingDialog.show(this, "登录中,请稍后") } loginViewModel.loadState.observe(this) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() } } diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 00bd76e..b5be93b 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -17,13 +17,13 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -70,8 +70,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 2e490c3..f93caaf 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -16,7 +16,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -25,6 +24,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { @@ -143,8 +143,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index b393c0b..e9befb2 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView @@ -156,8 +156,8 @@ override fun observeRequestState() { groupViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 47c0af6..a0025db 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -10,7 +10,6 @@ import com.casic.smarttube.extensions.getQuarterOfYear import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -51,8 +51,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt index f947b2c..7287bff 100644 --- a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.databinding.ActivityLoginBinding import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.vm.AuthenticateViewModel @@ -14,6 +13,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues class LoginActivity : KotlinBaseActivity() { @@ -45,11 +45,11 @@ override fun observeRequestState() { authenticateViewModel.loadState.observe(this) { - LoadingDialogHub.show(this, "登录中,请稍后") + LoadingDialog.show(this, "登录中,请稍后") } loginViewModel.loadState.observe(this) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() } } diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 00bd76e..b5be93b 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -17,13 +17,13 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -70,8 +70,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index 4be4a14..c8a8b04 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -2,13 +2,11 @@ import android.content.Intent import android.graphics.Color -import android.location.Location import android.os.Bundle import com.amap.api.maps.AMap -import com.amap.api.maps.AMap.OnCameraChangeListener -import com.amap.api.maps.AMap.OnMapLoadedListener import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.UiSettings import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.MyLocationStyle @@ -20,7 +18,7 @@ class SelectLocationActivity : KotlinBaseActivity(), - AMap.OnMyLocationChangeListener, OnMapLoadedListener, OnCameraChangeListener { + AMap.OnMapLoadedListener, AMap.OnCameraChangeListener { private val kTag = "SelectLocationActivity" private lateinit var latLng: LatLng @@ -38,6 +36,8 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { + binding.mapView.onCreate(savedInstanceState) + aMap = binding.mapView.map aMap.mapType = AMap.MAP_TYPE_NORMAL val locationStyle = MyLocationStyle() @@ -50,7 +50,7 @@ locationStyle.radiusFillColor(Color.TRANSPARENT) aMap.myLocationStyle = locationStyle aMap.isMyLocationEnabled = true - val uiSettings = aMap.uiSettings + val uiSettings: UiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER //不许地图随手势倾斜角度 @@ -61,9 +61,10 @@ uiSettings.isMyLocationButtonEnabled = true //改变地图的缩放级别 aMap.moveCamera(CameraUpdateFactory.zoomTo(15f)) + centerMarkerView = CenterMarkerView(this, aMap) - centerMarkerView = CenterMarkerView(this) - centerMarkerView.initInfoWindowsView(aMap) + aMap.setOnMapLoadedListener(this) + aMap.setOnCameraChangeListener(this) } override fun observeRequestState() { @@ -71,10 +72,6 @@ } override fun initEvent() { - aMap.setOnMyLocationChangeListener(this) - aMap.setOnMapLoadedListener(this) - aMap.setOnCameraChangeListener(this) - binding.rightOperateView.setOnClickListener { val intent = Intent() intent.putExtra("longitude", latLng.longitude.toString()) @@ -84,15 +81,8 @@ } } - override fun onMyLocationChange(location: Location?) { - if (location == null) { - return - } - this.latLng = LatLng(location.latitude, location.longitude) - } - override fun onMapLoaded() { - centerMarkerView.addCenterMarker(aMap) + centerMarkerView.addCenterMarker() } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -101,17 +91,12 @@ } override fun onCameraChangeFinish(cameraPosition: CameraPosition) { - this.latLng = cameraPosition.target + latLng = cameraPosition.target //显示infoWindow centerMarkerView.showInfoWindow(latLng) } /**地图相关*********/ - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding.mapView.onCreate(savedInstanceState) - } - override fun onResume() { super.onResume() binding.mapView.onResume() diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 2e490c3..f93caaf 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -16,7 +16,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -25,6 +24,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { @@ -143,8 +143,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index b393c0b..e9befb2 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView @@ -156,8 +156,8 @@ override fun observeRequestState() { groupViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 47c0af6..a0025db 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -10,7 +10,6 @@ import com.casic.smarttube.extensions.getQuarterOfYear import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -51,8 +51,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt index f947b2c..7287bff 100644 --- a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.databinding.ActivityLoginBinding import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.vm.AuthenticateViewModel @@ -14,6 +13,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues class LoginActivity : KotlinBaseActivity() { @@ -45,11 +45,11 @@ override fun observeRequestState() { authenticateViewModel.loadState.observe(this) { - LoadingDialogHub.show(this, "登录中,请稍后") + LoadingDialog.show(this, "登录中,请稍后") } loginViewModel.loadState.observe(this) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() } } diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 00bd76e..b5be93b 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -17,13 +17,13 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -70,8 +70,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index 4be4a14..c8a8b04 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -2,13 +2,11 @@ import android.content.Intent import android.graphics.Color -import android.location.Location import android.os.Bundle import com.amap.api.maps.AMap -import com.amap.api.maps.AMap.OnCameraChangeListener -import com.amap.api.maps.AMap.OnMapLoadedListener import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.UiSettings import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.MyLocationStyle @@ -20,7 +18,7 @@ class SelectLocationActivity : KotlinBaseActivity(), - AMap.OnMyLocationChangeListener, OnMapLoadedListener, OnCameraChangeListener { + AMap.OnMapLoadedListener, AMap.OnCameraChangeListener { private val kTag = "SelectLocationActivity" private lateinit var latLng: LatLng @@ -38,6 +36,8 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { + binding.mapView.onCreate(savedInstanceState) + aMap = binding.mapView.map aMap.mapType = AMap.MAP_TYPE_NORMAL val locationStyle = MyLocationStyle() @@ -50,7 +50,7 @@ locationStyle.radiusFillColor(Color.TRANSPARENT) aMap.myLocationStyle = locationStyle aMap.isMyLocationEnabled = true - val uiSettings = aMap.uiSettings + val uiSettings: UiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER //不许地图随手势倾斜角度 @@ -61,9 +61,10 @@ uiSettings.isMyLocationButtonEnabled = true //改变地图的缩放级别 aMap.moveCamera(CameraUpdateFactory.zoomTo(15f)) + centerMarkerView = CenterMarkerView(this, aMap) - centerMarkerView = CenterMarkerView(this) - centerMarkerView.initInfoWindowsView(aMap) + aMap.setOnMapLoadedListener(this) + aMap.setOnCameraChangeListener(this) } override fun observeRequestState() { @@ -71,10 +72,6 @@ } override fun initEvent() { - aMap.setOnMyLocationChangeListener(this) - aMap.setOnMapLoadedListener(this) - aMap.setOnCameraChangeListener(this) - binding.rightOperateView.setOnClickListener { val intent = Intent() intent.putExtra("longitude", latLng.longitude.toString()) @@ -84,15 +81,8 @@ } } - override fun onMyLocationChange(location: Location?) { - if (location == null) { - return - } - this.latLng = LatLng(location.latitude, location.longitude) - } - override fun onMapLoaded() { - centerMarkerView.addCenterMarker(aMap) + centerMarkerView.addCenterMarker() } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -101,17 +91,12 @@ } override fun onCameraChangeFinish(cameraPosition: CameraPosition) { - this.latLng = cameraPosition.target + latLng = cameraPosition.target //显示infoWindow centerMarkerView.showInfoWindow(latLng) } /**地图相关*********/ - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding.mapView.onCreate(savedInstanceState) - } - override fun onResume() { super.onResume() binding.mapView.onResume() diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index f73d92b..6890e74 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -26,8 +26,8 @@ val lastDataModel = MutableLiveData() val deleteResult = MutableLiveData() - fun obtainMapDeviceList() = launch({ - val response = RetrofitServiceManager.obtainMapDeviceList() + fun getMapDeviceList() = launch({ + val response = RetrofitServiceManager.getMapDeviceList() val responseCode = response.separateResponseCode() if (responseCode == 200) { mapDeviceModel.value = gson.fromJson( diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 2e490c3..f93caaf 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -16,7 +16,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -25,6 +24,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { @@ -143,8 +143,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index b393c0b..e9befb2 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView @@ -156,8 +156,8 @@ override fun observeRequestState() { groupViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 47c0af6..a0025db 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -10,7 +10,6 @@ import com.casic.smarttube.extensions.getQuarterOfYear import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -51,8 +51,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt index f947b2c..7287bff 100644 --- a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.databinding.ActivityLoginBinding import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.vm.AuthenticateViewModel @@ -14,6 +13,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues class LoginActivity : KotlinBaseActivity() { @@ -45,11 +45,11 @@ override fun observeRequestState() { authenticateViewModel.loadState.observe(this) { - LoadingDialogHub.show(this, "登录中,请稍后") + LoadingDialog.show(this, "登录中,请稍后") } loginViewModel.loadState.observe(this) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() } } diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 00bd76e..b5be93b 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -17,13 +17,13 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -70,8 +70,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index 4be4a14..c8a8b04 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -2,13 +2,11 @@ import android.content.Intent import android.graphics.Color -import android.location.Location import android.os.Bundle import com.amap.api.maps.AMap -import com.amap.api.maps.AMap.OnCameraChangeListener -import com.amap.api.maps.AMap.OnMapLoadedListener import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.UiSettings import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.MyLocationStyle @@ -20,7 +18,7 @@ class SelectLocationActivity : KotlinBaseActivity(), - AMap.OnMyLocationChangeListener, OnMapLoadedListener, OnCameraChangeListener { + AMap.OnMapLoadedListener, AMap.OnCameraChangeListener { private val kTag = "SelectLocationActivity" private lateinit var latLng: LatLng @@ -38,6 +36,8 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { + binding.mapView.onCreate(savedInstanceState) + aMap = binding.mapView.map aMap.mapType = AMap.MAP_TYPE_NORMAL val locationStyle = MyLocationStyle() @@ -50,7 +50,7 @@ locationStyle.radiusFillColor(Color.TRANSPARENT) aMap.myLocationStyle = locationStyle aMap.isMyLocationEnabled = true - val uiSettings = aMap.uiSettings + val uiSettings: UiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER //不许地图随手势倾斜角度 @@ -61,9 +61,10 @@ uiSettings.isMyLocationButtonEnabled = true //改变地图的缩放级别 aMap.moveCamera(CameraUpdateFactory.zoomTo(15f)) + centerMarkerView = CenterMarkerView(this, aMap) - centerMarkerView = CenterMarkerView(this) - centerMarkerView.initInfoWindowsView(aMap) + aMap.setOnMapLoadedListener(this) + aMap.setOnCameraChangeListener(this) } override fun observeRequestState() { @@ -71,10 +72,6 @@ } override fun initEvent() { - aMap.setOnMyLocationChangeListener(this) - aMap.setOnMapLoadedListener(this) - aMap.setOnCameraChangeListener(this) - binding.rightOperateView.setOnClickListener { val intent = Intent() intent.putExtra("longitude", latLng.longitude.toString()) @@ -84,15 +81,8 @@ } } - override fun onMyLocationChange(location: Location?) { - if (location == null) { - return - } - this.latLng = LatLng(location.latitude, location.longitude) - } - override fun onMapLoaded() { - centerMarkerView.addCenterMarker(aMap) + centerMarkerView.addCenterMarker() } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -101,17 +91,12 @@ } override fun onCameraChangeFinish(cameraPosition: CameraPosition) { - this.latLng = cameraPosition.target + latLng = cameraPosition.target //显示infoWindow centerMarkerView.showInfoWindow(latLng) } /**地图相关*********/ - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding.mapView.onCreate(savedInstanceState) - } - override fun onResume() { super.onResume() binding.mapView.onResume() diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index f73d92b..6890e74 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -26,8 +26,8 @@ val lastDataModel = MutableLiveData() val deleteResult = MutableLiveData() - fun obtainMapDeviceList() = launch({ - val response = RetrofitServiceManager.obtainMapDeviceList() + fun getMapDeviceList() = launch({ + val response = RetrofitServiceManager.getMapDeviceList() val responseCode = response.separateResponseCode() if (responseCode == 200) { mapDeviceModel.value = gson.fromJson( diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index 3477a7f..b88476b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -27,7 +27,7 @@ val changeGroupResult = MutableLiveData() fun obtainProGroupList() = launch({ - val response = RetrofitServiceManager.obtainProGroupList() + val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { groupModel.value = gson.fromJson( @@ -40,9 +40,9 @@ it.printStackTrace() }) - fun obtainDeviceListByGroup(wellGroupId: String) = launch({ + fun getDeviceListByGroup(wellGroupId: String) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByGroup(wellGroupId) + val response = RetrofitServiceManager.getDeviceListByGroup(wellGroupId) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -74,8 +74,8 @@ it.printStackTrace() }) - fun obtainGroupList() = launch({ - val response = RetrofitServiceManager.obtainGroupList() + fun getGroupList() = launch({ + val response = RetrofitServiceManager.getGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { groupListModel.value = gson.fromJson( diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 2e490c3..f93caaf 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -16,7 +16,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -25,6 +24,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { @@ -143,8 +143,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index b393c0b..e9befb2 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView @@ -156,8 +156,8 @@ override fun observeRequestState() { groupViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 47c0af6..a0025db 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -10,7 +10,6 @@ import com.casic.smarttube.extensions.getQuarterOfYear import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -51,8 +51,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt index f947b2c..7287bff 100644 --- a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.databinding.ActivityLoginBinding import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.vm.AuthenticateViewModel @@ -14,6 +13,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues class LoginActivity : KotlinBaseActivity() { @@ -45,11 +45,11 @@ override fun observeRequestState() { authenticateViewModel.loadState.observe(this) { - LoadingDialogHub.show(this, "登录中,请稍后") + LoadingDialog.show(this, "登录中,请稍后") } loginViewModel.loadState.observe(this) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() } } diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 00bd76e..b5be93b 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -17,13 +17,13 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -70,8 +70,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index 4be4a14..c8a8b04 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -2,13 +2,11 @@ import android.content.Intent import android.graphics.Color -import android.location.Location import android.os.Bundle import com.amap.api.maps.AMap -import com.amap.api.maps.AMap.OnCameraChangeListener -import com.amap.api.maps.AMap.OnMapLoadedListener import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.UiSettings import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.MyLocationStyle @@ -20,7 +18,7 @@ class SelectLocationActivity : KotlinBaseActivity(), - AMap.OnMyLocationChangeListener, OnMapLoadedListener, OnCameraChangeListener { + AMap.OnMapLoadedListener, AMap.OnCameraChangeListener { private val kTag = "SelectLocationActivity" private lateinit var latLng: LatLng @@ -38,6 +36,8 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { + binding.mapView.onCreate(savedInstanceState) + aMap = binding.mapView.map aMap.mapType = AMap.MAP_TYPE_NORMAL val locationStyle = MyLocationStyle() @@ -50,7 +50,7 @@ locationStyle.radiusFillColor(Color.TRANSPARENT) aMap.myLocationStyle = locationStyle aMap.isMyLocationEnabled = true - val uiSettings = aMap.uiSettings + val uiSettings: UiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER //不许地图随手势倾斜角度 @@ -61,9 +61,10 @@ uiSettings.isMyLocationButtonEnabled = true //改变地图的缩放级别 aMap.moveCamera(CameraUpdateFactory.zoomTo(15f)) + centerMarkerView = CenterMarkerView(this, aMap) - centerMarkerView = CenterMarkerView(this) - centerMarkerView.initInfoWindowsView(aMap) + aMap.setOnMapLoadedListener(this) + aMap.setOnCameraChangeListener(this) } override fun observeRequestState() { @@ -71,10 +72,6 @@ } override fun initEvent() { - aMap.setOnMyLocationChangeListener(this) - aMap.setOnMapLoadedListener(this) - aMap.setOnCameraChangeListener(this) - binding.rightOperateView.setOnClickListener { val intent = Intent() intent.putExtra("longitude", latLng.longitude.toString()) @@ -84,15 +81,8 @@ } } - override fun onMyLocationChange(location: Location?) { - if (location == null) { - return - } - this.latLng = LatLng(location.latitude, location.longitude) - } - override fun onMapLoaded() { - centerMarkerView.addCenterMarker(aMap) + centerMarkerView.addCenterMarker() } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -101,17 +91,12 @@ } override fun onCameraChangeFinish(cameraPosition: CameraPosition) { - this.latLng = cameraPosition.target + latLng = cameraPosition.target //显示infoWindow centerMarkerView.showInfoWindow(latLng) } /**地图相关*********/ - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding.mapView.onCreate(savedInstanceState) - } - override fun onResume() { super.onResume() binding.mapView.onResume() diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index f73d92b..6890e74 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -26,8 +26,8 @@ val lastDataModel = MutableLiveData() val deleteResult = MutableLiveData() - fun obtainMapDeviceList() = launch({ - val response = RetrofitServiceManager.obtainMapDeviceList() + fun getMapDeviceList() = launch({ + val response = RetrofitServiceManager.getMapDeviceList() val responseCode = response.separateResponseCode() if (responseCode == 200) { mapDeviceModel.value = gson.fromJson( diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index 3477a7f..b88476b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -27,7 +27,7 @@ val changeGroupResult = MutableLiveData() fun obtainProGroupList() = launch({ - val response = RetrofitServiceManager.obtainProGroupList() + val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { groupModel.value = gson.fromJson( @@ -40,9 +40,9 @@ it.printStackTrace() }) - fun obtainDeviceListByGroup(wellGroupId: String) = launch({ + fun getDeviceListByGroup(wellGroupId: String) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByGroup(wellGroupId) + val response = RetrofitServiceManager.getDeviceListByGroup(wellGroupId) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -74,8 +74,8 @@ it.printStackTrace() }) - fun obtainGroupList() = launch({ - val response = RetrofitServiceManager.obtainGroupList() + fun getGroupList() = launch({ + val response = RetrofitServiceManager.getGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { groupListModel.value = gson.fromJson( diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 433fd65..13b3e39 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -6,29 +6,14 @@ android:background="@color/mainBackColor" android:orientation="vertical"> - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_show_left_image="false" + app:tbv_show_right_image="true" + app:tbv_text="@string/app_name" /> diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 2e490c3..f93caaf 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -16,7 +16,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -25,6 +24,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { @@ -143,8 +143,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index b393c0b..e9befb2 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView @@ -156,8 +156,8 @@ override fun observeRequestState() { groupViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 47c0af6..a0025db 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -10,7 +10,6 @@ import com.casic.smarttube.extensions.getQuarterOfYear import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -51,8 +51,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt index f947b2c..7287bff 100644 --- a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.databinding.ActivityLoginBinding import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.vm.AuthenticateViewModel @@ -14,6 +13,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues class LoginActivity : KotlinBaseActivity() { @@ -45,11 +45,11 @@ override fun observeRequestState() { authenticateViewModel.loadState.observe(this) { - LoadingDialogHub.show(this, "登录中,请稍后") + LoadingDialog.show(this, "登录中,请稍后") } loginViewModel.loadState.observe(this) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() } } diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 00bd76e..b5be93b 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -17,13 +17,13 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -70,8 +70,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index 4be4a14..c8a8b04 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -2,13 +2,11 @@ import android.content.Intent import android.graphics.Color -import android.location.Location import android.os.Bundle import com.amap.api.maps.AMap -import com.amap.api.maps.AMap.OnCameraChangeListener -import com.amap.api.maps.AMap.OnMapLoadedListener import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.UiSettings import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.MyLocationStyle @@ -20,7 +18,7 @@ class SelectLocationActivity : KotlinBaseActivity(), - AMap.OnMyLocationChangeListener, OnMapLoadedListener, OnCameraChangeListener { + AMap.OnMapLoadedListener, AMap.OnCameraChangeListener { private val kTag = "SelectLocationActivity" private lateinit var latLng: LatLng @@ -38,6 +36,8 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { + binding.mapView.onCreate(savedInstanceState) + aMap = binding.mapView.map aMap.mapType = AMap.MAP_TYPE_NORMAL val locationStyle = MyLocationStyle() @@ -50,7 +50,7 @@ locationStyle.radiusFillColor(Color.TRANSPARENT) aMap.myLocationStyle = locationStyle aMap.isMyLocationEnabled = true - val uiSettings = aMap.uiSettings + val uiSettings: UiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER //不许地图随手势倾斜角度 @@ -61,9 +61,10 @@ uiSettings.isMyLocationButtonEnabled = true //改变地图的缩放级别 aMap.moveCamera(CameraUpdateFactory.zoomTo(15f)) + centerMarkerView = CenterMarkerView(this, aMap) - centerMarkerView = CenterMarkerView(this) - centerMarkerView.initInfoWindowsView(aMap) + aMap.setOnMapLoadedListener(this) + aMap.setOnCameraChangeListener(this) } override fun observeRequestState() { @@ -71,10 +72,6 @@ } override fun initEvent() { - aMap.setOnMyLocationChangeListener(this) - aMap.setOnMapLoadedListener(this) - aMap.setOnCameraChangeListener(this) - binding.rightOperateView.setOnClickListener { val intent = Intent() intent.putExtra("longitude", latLng.longitude.toString()) @@ -84,15 +81,8 @@ } } - override fun onMyLocationChange(location: Location?) { - if (location == null) { - return - } - this.latLng = LatLng(location.latitude, location.longitude) - } - override fun onMapLoaded() { - centerMarkerView.addCenterMarker(aMap) + centerMarkerView.addCenterMarker() } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -101,17 +91,12 @@ } override fun onCameraChangeFinish(cameraPosition: CameraPosition) { - this.latLng = cameraPosition.target + latLng = cameraPosition.target //显示infoWindow centerMarkerView.showInfoWindow(latLng) } /**地图相关*********/ - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding.mapView.onCreate(savedInstanceState) - } - override fun onResume() { super.onResume() binding.mapView.onResume() diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index f73d92b..6890e74 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -26,8 +26,8 @@ val lastDataModel = MutableLiveData() val deleteResult = MutableLiveData() - fun obtainMapDeviceList() = launch({ - val response = RetrofitServiceManager.obtainMapDeviceList() + fun getMapDeviceList() = launch({ + val response = RetrofitServiceManager.getMapDeviceList() val responseCode = response.separateResponseCode() if (responseCode == 200) { mapDeviceModel.value = gson.fromJson( diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index 3477a7f..b88476b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -27,7 +27,7 @@ val changeGroupResult = MutableLiveData() fun obtainProGroupList() = launch({ - val response = RetrofitServiceManager.obtainProGroupList() + val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { groupModel.value = gson.fromJson( @@ -40,9 +40,9 @@ it.printStackTrace() }) - fun obtainDeviceListByGroup(wellGroupId: String) = launch({ + fun getDeviceListByGroup(wellGroupId: String) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByGroup(wellGroupId) + val response = RetrofitServiceManager.getDeviceListByGroup(wellGroupId) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -74,8 +74,8 @@ it.printStackTrace() }) - fun obtainGroupList() = launch({ - val response = RetrofitServiceManager.obtainGroupList() + fun getGroupList() = launch({ + val response = RetrofitServiceManager.getGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { groupListModel.value = gson.fromJson( diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 433fd65..13b3e39 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -6,29 +6,14 @@ android:background="@color/mainBackColor" android:orientation="vertical"> - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_show_left_image="false" + app:tbv_show_right_image="true" + app:tbv_text="@string/app_name" /> diff --git a/app/src/main/res/layout/item_group_rv.xml b/app/src/main/res/layout/item_group_rv.xml deleted file mode 100644 index e410627..0000000 --- a/app/src/main/res/layout/item_group_rv.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd9277c..0be8031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,10 +78,10 @@ android:resource="@xml/file_paths" /> - + + android:value="1b39fd3d87d88a637247e98f7739556a" /> -) : RecyclerView.Adapter() { - - private val geocoderSearch by lazy { GeocodeSearch(context) } - private val layoutInflater: LayoutInflater = LayoutInflater.from(context) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { - return ItemViewHolder( - layoutInflater.inflate(R.layout.item_group_rv, parent, false) - ) - } - - override fun getItemCount(): Int = dataRows.size - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - //绑定数据 - val rowsBean = dataRows[position] - - holder.groupNameView.text = String.format("项目编号:${rowsBean.groupId}") - if (rowsBean.latGaode.isBlank() || rowsBean.lngGaode.isBlank()) { - holder.groupLocationView.text = "经纬度异常,无法查看具体位置" - } else { - val queryParam = RegeocodeQuery( - LatLonPoint(rowsBean.latGaode.toDouble(), rowsBean.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) - geocoderSearch.getFromLocationAsyn(queryParam) - geocoderSearch.setOnGeocodeSearchListener(object : - GeocodeSearch.OnGeocodeSearchListener { - override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { - if (rCode == 1000) { - holder.groupLocationView.text = - String.format("项目位置:${result?.regeocodeAddress?.formatAddress}") - } - } - - override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { - - } - }) - } - holder.totalDeviceNumView.text = String.format("设备总数:${rowsBean.totalDevice}") - holder.inUseDeviceNumView.text = String.format("已激活:${rowsBean.alive}") - holder.notUseDeviceNumView.text = String.format("未激活:${rowsBean.unalive}") - - //绑定事件 - if (listener != null) { - holder.itemView.setOnClickListener { - listener!!.onClicked(position) - } - } - } - - inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { - var groupNameView: TextView = view.findViewById(R.id.groupNameView) - var groupLocationView: TextView = view.findViewById(R.id.groupLocationView) - var totalDeviceNumView: TextView = view.findViewById(R.id.totalDeviceNumView) - var inUseDeviceNumView: TextView = view.findViewById(R.id.inUseDeviceNumView) - var notUseDeviceNumView: TextView = view.findViewById(R.id.notUseDeviceNumView) - } - - private var listener: OnItemClickListener? = null - - interface OnItemClickListener { - fun onClicked(position: Int) - } - - fun setOnItemClickListener(onClickListener: OnItemClickListener?) { - this.listener = onClickListener - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index 0cb450f..1064978 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,10 +1,6 @@ package com.casic.smarttube.fragment -import android.graphics.Color -import android.graphics.Point import android.os.Bundle -import android.os.Handler -import android.os.Message import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,7 +9,6 @@ import androidx.recyclerview.widget.DividerItemDecoration import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions -import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.CameraPosition @@ -26,53 +21,38 @@ import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R -import com.casic.smarttube.adapter.GroupListAdapter import com.casic.smarttube.databinding.FragmentHomeBinding import com.casic.smarttube.model.MapDeviceModel import com.casic.smarttube.model.ProjectGroupModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity -import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel -import com.casic.smarttube.widgets.GaoDeClusterMarkerView +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.WeakReferenceHandler +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog -import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -class HomePageFragment : KotlinBaseFragment(), Handler.Callback, - AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, - AMap.OnInfoWindowClickListener { +class HomePageFragment : KotlinBaseFragment(), AMap.OnCameraChangeListener, + AMap.OnMarkerClickListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener, + AMap.OnMapClickListener { private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private lateinit var groupListAdapter: GroupListAdapter - private lateinit var multiDevice: ArrayList - private var dataBeans: MutableList = ArrayList() - private var isRefresh = false - - /** - * 所有的marker - */ - private var allMarkerOptions: MutableList = ArrayList() - - /** - * 视野内的marker - */ - private var markerOptionsInView: MutableList = ArrayList() + private lateinit var groupListAdapter: NormalRecyclerAdapter + private var clickedMarker: Marker? = null /** * 自定义Marker弹出框 @@ -84,11 +64,6 @@ * */ private var deviceModels: MutableList = ArrayList() - /** - * 保存地图缩放等级 - * */ - private var mapZooms = ArrayList() - override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { @@ -96,21 +71,27 @@ } override fun setupTopBarLayout() { + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + } + + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun observeRequestState() { groupViewModel.loadState.observe(this) { state -> when (state) { - LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(requireActivity(), "数据加载中...") + else -> LoadingDialog.dismiss() } } } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(this) - val menuItems = ArrayList().apply { add( EasyPopupWindow.MenuItem( @@ -132,28 +113,16 @@ } }) - //初始化vm - deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] - groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - - //默认数据 - groupViewModel.obtainProGroupList() - - //地图初始化,默认地图缩放13级 - mapZooms.add(13f) + //地图初始化 initMap(savedInstanceState) - //数据监听 + //默认显示所有设备 + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.mapDeviceModel.observe(this) { if (it.code == 200) { - if (allMarkerOptions.isNotEmpty()) { - allMarkerOptions.clear() - } - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() - if (deviceModels.isNotEmpty()) { - deviceModels.clear() - } + val allMarkerOptions = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -175,31 +144,31 @@ } } } - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 13f) + + 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) { - val dataRows = it.data - when { - isRefresh -> { - dataBeans.clear() - dataBeans = dataRows!! - isRefresh = false - } - - else -> { - dataBeans = dataRows!! - } - } - weakReferenceHandler.sendEmptyMessage(2022090201) + bindRecyclerView(it) } } + groupViewModel.obtainProGroupList() + groupViewModel.groupDeviceModel.observe(this) { if (it.code == 200) { - val latitudeList: MutableList = ArrayList() - val longitudeList: MutableList = ArrayList() + val latitudeList = ArrayList() + val longitudeList = ArrayList() it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -215,56 +184,67 @@ } } //计算所有点的中心点位置 - val centerLatLng = LatLng(latitudeList[0], longitudeList[0]) - moveToPosition(centerLatLng, 16f) + val latLng = LatLng(latitudeList[0], longitudeList[0]) + val cameraPosition = CameraPosition(latLng, 14f, 0f, 0f) + val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(cameraUpdate, 1500, null) } } } + private fun bindRecyclerView(it: ProjectGroupModel) { + groupListAdapter = object : + NormalRecyclerAdapter(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.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + binding.homeRecyclerView.adapter = groupListAdapter + groupListAdapter.setOnItemClickedListener(object : + NormalRecyclerAdapter.OnItemClickedListener { + override fun onItemClicked(position: Int, item: ProjectGroupModel.DataModel) { + // 根据groupId查询组下设备 + groupViewModel.getDeviceListByGroup(item.groupId) + } + }) + } + override fun initEvent() { - binding.rightOptionView.setOnClickListener { - easyPopupWindow.setBackgroundDrawable(null) - val x = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } - binding.addDeviceButton.setOnClickListener { requireContext().navigatePageTo() } } - override fun onResume() { - super.onResume() - binding.mapView.onResume() - //获取所有设备数据 - deviceViewModel.obtainMapDeviceList() - - //获取组 - groupViewModel.obtainProGroupList() - } - - override fun handleMessage(msg: Message): Boolean { - if (msg.what == 2022090201) { - if (isRefresh) { - groupListAdapter.notifyDataSetChanged() - } else { - groupListAdapter = GroupListAdapter(requireContext(), dataBeans) - binding.homeRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - binding.homeRecyclerView.adapter = groupListAdapter - groupListAdapter.setOnItemClickListener(object : - GroupListAdapter.OnItemClickListener { - override fun onClicked(position: Int) { - // 根据groupId查询组下设备 - groupViewModel.obtainDeviceListByGroup(dataBeans[position].groupId) - } - }) - } - } - return true - } - private fun initMap(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -273,7 +253,7 @@ uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 - uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + uiSettings.isRotateGesturesEnabled = false//不允许地图随手势改变方位 // 地图缩放监听 aMap.addOnCameraChangeListener(this) @@ -281,16 +261,10 @@ aMap.addOnMarkerClickListener(this) // 点击marker弹出自定义popup aMap.setInfoWindowAdapter(this) - // 点击popup - aMap.setOnInfoWindowClickListener(this) - } - - //移动到指定经纬度 - private fun moveToPosition(latLng: LatLng, scale: Float) { - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, scale, 0f, 0f) - val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) - aMap.animateCamera(cameraUpdate, 1500, null) + //信息窗点击事件 + aMap.addOnInfoWindowClickListener(this) + //地图点击事件,用于隐藏infoWindow + aMap.setOnMapClickListener(this) } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -299,94 +273,58 @@ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker override fun onCameraChangeFinish(cameraPosition: CameraPosition?) { - if (mapZooms.last() != cameraPosition?.zoom) { - aMap.clear() - mapZooms.add(cameraPosition?.zoom!!) - } - //地图缩放之后显示聚合点数据 - initClustersMarkers() - } - private fun initClustersMarkers() { - val proj = aMap.projection - val dm = resources.displayMetrics - var screenLocation: Point - markerOptionsInView.clear() - // 获取在当前视野内的marker - allMarkerOptions.forEach { - screenLocation = proj.toScreenLocation(it.position) - if (screenLocation.x >= 0 && screenLocation.y >= 0 && screenLocation.x <= dm.widthPixels && screenLocation.y <= dm.heightPixels) { - //在当前可观区域内 - markerOptionsInView.add(it) - } - } - // 自定义的聚合类MarkerCluster - val clustersMarkers: MutableList = ArrayList() - markerOptionsInView.forEach { - if (clustersMarkers.size == 0) { - //添加一个新的自定义marker - clustersMarkers.add( - GaoDeClusterMarkerView(requireContext(), it, proj, LocaleConstant.RADIUS_SIZE) - ) - } else { - var isInRange = false - //Kotlin foreach不能用break - for (view in clustersMarkers) { - //判断当前的marker是否在前面marker的聚合范围内 并且每个marker只会聚合一次。 - if (view.bounds.contains(it.position)) { - view.addMarker(it) - isInRange = true - break - } - } - //如果没在任何范围内,自己单独形成一个自定义marker。在和后面的marker进行比较 - if (!isInRange) { - clustersMarkers.add( - GaoDeClusterMarkerView( - requireContext(), it, proj, LocaleConstant.RADIUS_SIZE - ) - )//相距多少才聚合 - } - } - } - // 设置聚合点的位置和icon - clustersMarkers.forEach { - it.setPositionAndIcon() - } - // 重新添加 marker - clustersMarkers.forEach { - aMap.addMarker(it.options) - } } override fun onMarkerClick(marker: Marker?): Boolean { - //显示设备基本信息 - marker?.showInfoWindow() + 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) + infoView = LayoutInflater.from(requireContext()).inflate( + R.layout.popu_map_info, null + ) } - val v = infoView!! - //反射得到popup里面的控件对象 - val deviceCodeView = v.findViewById(R.id.deviceCodeView) - val deviceModelView = v.findViewById(R.id.deviceModelView) - val deviceValueView = v.findViewById(R.id.deviceValueView) - val updateTimeView = v.findViewById(R.id.updateTimeView) - val locationView = v.findViewById(R.id.locationView) + marker?.apply { + renderWindow(this, infoView!!) + } + return infoView + } - multiDevice = ArrayList() + private fun renderWindow(marker: Marker, view: View) { + //反射得到popup里面的控件对象 + val deviceCodeView = view.findViewById(R.id.deviceCodeView) + val deviceModelView = view.findViewById(R.id.deviceModelView) + val deviceValueView = view.findViewById(R.id.deviceValueView) + val updateTimeView = view.findViewById(R.id.updateTimeView) + val locationView = view.findViewById(R.id.locationView) + //绑定数据 - val clickedLatLng = marker?.position!! - for (device in deviceModels) { - if (clickedLatLng.latitude == device.latGaode!!.toDouble() && clickedLatLng.longitude == device.lngGaode!!.toDouble()) { + 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(), { + deviceViewModel.lastDataModel.observe(requireActivity()) { if (it.code == 200) { deviceValueView.text = String.format("最新浓度: ${it.data.strength}") updateTimeView.text = String.format("更新时间: ${it.data.uptime}") @@ -394,15 +332,12 @@ deviceValueView.text = String.format("最新浓度: 未知") updateTimeView.text = String.format("更新时间: 未知") } - }) + } if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { locationView.text = "经纬度异常,无法查看具体位置" } else { - val queryParam = RegeocodeQuery( - LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), - 200f, - GeocodeSearch.AMAP - ) + val point = LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()) + val queryParam = RegeocodeQuery(point, 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(queryParam) geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { @@ -425,40 +360,8 @@ } }) } - return infoView } } - - deviceModels.forEach { - val lat = it.latGaode.toString() - val lng = it.lngGaode.toString() - if (lat.isNotBlank() && lng.isNotBlank()) { - //返回true代表当前位置在大陆、港澳地区,反之不在 - val latitude = lat.toDouble() - val longitude = lng.toDouble() - val calculateLineDistance = AMapUtils.calculateLineDistance( - clickedLatLng, LatLng(latitude, longitude) - ) - if (calculateLineDistance < LocaleConstant.RADIUS_SIZE) { - multiDevice.add(it.devcode) - } - } - } - //查看聚合点,单独开页面导航过去 - BottomActionSheet.Builder().setContext(requireContext()).setActionItemTitle(multiDevice) - .setItemTextColor(Color.BLUE) - .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { - override fun onActionItemClick(position: Int) { - deviceModels.forEach { - if (it.devcode == multiDevice[position]) { - requireContext().navigatePageTo( - arrayListOf(it.groupId, it.devcode, it.modelName) - ) - } - } - } - }).build().show() - return null } /** @@ -466,27 +369,24 @@ * */ override fun getInfoContents(p0: Marker?): View? = null - override fun onInfoWindowClick(p0: Marker?) { - if (p0 != null) { + override fun onInfoWindowClick(marker: Marker?) { + marker?.apply { AlertControlDialog.Builder().setContext(requireContext()).setTitle("操作提示") .setMessage("确定要前往吗").setNegativeButton("取消").setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { - val latLng = p0.position - val lat = latLng.latitude.toString() - val lng = latLng.longitude.toString() + val lat = position.latitude.toString() + val lng = position.longitude.toString() if (lat.isBlank() || lng.isBlank()) { "窨井经纬度异常,无法开启导航".show(requireContext()) return } - RouteOnMap.startNavigation( - requireContext(), p0.snippet, LatLng(lat.toDouble(), lng.toDouble()) - ) + RouteOnMap.startNavigation(requireContext(), snippet, position) } override fun onCancelClick() { - p0.destroy() + } }).build().show() } @@ -494,6 +394,11 @@ /***以下是地图生命周期管理************************************************************************/ + override fun onResume() { + super.onResume() + binding.mapView.onResume() + } + override fun onPause() { super.onPause() binding.mapView.onPause() diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index f20cb4e..9be184e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper import com.casic.smarttube.utils.FileDownloadManager -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.view.AboutUsActivity @@ -32,6 +31,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog @@ -65,26 +65,26 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后") + is LoadState.Loading -> LoadingDialog.show(requireActivity(), "修改中,请稍后") is LoadState.Success -> { "修改成功,请重新登录".show(requireContext()) - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() ActivityStackManager.finishAllActivity() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } versionViewModel.loadState.observe(this) { when (it) { - is LoadState.Loading -> LoadingDialogHub.show( + is LoadState.Loading -> LoadingDialog.show( requireActivity(), "检查版本中,请稍后" ) - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -95,7 +95,7 @@ } binding.updateUserButton.setOnClickListener { - LoadingDialogHub.show(requireActivity(), "同步中,请稍后...") + LoadingDialog.show(requireActivity(), "同步中,请稍后...") userViewModel.obtainUserDetail() } @@ -130,7 +130,7 @@ binding.clearCacheLayout.setOnClickListener { //删除缓存之后在设置缓存大小 - LoadingDialogHub.show(requireActivity(), "清理中,请稍后") + LoadingDialog.show(requireActivity(), "清理中,请稍后") File(requireContext().cacheDir.path).deleteFile() object : CountDownTimer(1500, 500) { override fun onTick(millisUntilFinished: Long) { @@ -138,7 +138,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() binding.cacheSizeView.text = collectApplicationCache().formatFileSize() } }.start() @@ -166,7 +166,7 @@ private fun dataObserve() { userViewModel.userDetailModel.observe(this) { if (it.code == 200) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "同步完成".show(requireContext()) userData = it.data updateUserInfo() diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt index e13a15a..f501087 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -75,19 +75,19 @@ * 地图设备列表 */ @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String + suspend fun getMapDeviceList(@Header("token") token: String): String /** * 项目列表 */ @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String + suspend fun getProGroupList(@Header("token") token: String): String /** * 根据项目ID查询该项目下的设备列表 */ @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( + suspend fun getDeviceListByGroup( @Header("token") token: String, @Query("wellGroupId") wellGroupId: String ): String @@ -187,7 +187,7 @@ * 获取项目编号列表 */ @GET("/tube/groupdict") - suspend fun obtainGroupList( + suspend fun getGroupList( @Header("token") token: String ): String diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt index 132c9d4..7b74fff 100644 --- a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -67,22 +67,22 @@ /** * 地图设备列表 */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) + suspend fun getMapDeviceList(): String { + return api.getMapDeviceList(AuthenticationHelper.token!!) } /** * 项目列表 */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) + suspend fun getProGroupList(): String { + return api.getProGroupList(AuthenticationHelper.token!!) } /** * 根据项目ID查询该项目下的设备列表 */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + suspend fun getDeviceListByGroup(wellGroupId: String): String { + return api.getDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) } /** @@ -187,8 +187,8 @@ /** * 获取项目编号列表 */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) + suspend fun getGroupList(): String { + return api.getGroupList(AuthenticationHelper.token!!) } /** diff --git a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt index 7e110ed..69b7f0c 100644 --- a/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt +++ b/app/src/main/java/com/casic/smarttube/utils/CenterMarkerView.kt @@ -1,131 +1,98 @@ -package com.casic.smarttube.utils; +package com.casic.smarttube.utils -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import com.amap.api.maps.AMap +import com.amap.api.maps.model.BitmapDescriptorFactory +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.maps.model.animation.Animation +import com.amap.api.maps.model.animation.ScaleAnimation +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.pengxh.kt.lite.extensions.breakLine -import com.amap.api.maps.AMap; -import com.amap.api.maps.model.BitmapDescriptorFactory; -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.maps.model.animation.Animation; -import com.amap.api.maps.model.animation.ScaleAnimation; -import com.amap.api.services.core.AMapException; -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; +class CenterMarkerView(private val context: Context, private var aMap: AMap) { + private lateinit var centerMarker: Marker -public class CenterMarkerView { + //拿到地图中心点的坐标 + private var latLng = aMap.cameraPosition.target + private val geocoderSearch by lazy { GeocodeSearch(context) } - private final Context context; - private Marker centerMarker; - private LatLng latLng; - private GeocodeSearch geocoderSearch; - - public CenterMarkerView(Context context) { - this.context = context; - try { - geocoderSearch = new GeocodeSearch(context); - } catch (AMapException e) { - e.printStackTrace(); - } - } - - public void addCenterMarker(AMap aMap) { - MarkerOptions options = new MarkerOptions(); - //对应Marker.setIcon方法 设置Marker的图片 - options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)); - //设置infoWindow与锚点的相对位置 - options.anchor(0.5F, 1); - //拿到地图中心点的坐标。 - LatLng latLng = aMap.getCameraPosition().target; - //把中心点的坐标转换成屏幕像素位置 - Point screenPosition = aMap.getProjection().toScreenLocation(latLng); - //在地图上添加Marker并获取到Marker. - centerMarker = aMap.addMarker(options); - //给marker设置像素位置。 - centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y); - centerMarker.setAnchor(0.5F, 1); - } - - public void initInfoWindowsView(AMap aMap) { - aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() { - @Override - public View getInfoWindow(Marker marker) { - View infoWindow = LayoutInflater.from(context).inflate(R.layout.map_info_window, null); - TextView locationView = infoWindow.findViewById(R.id.locationView); - RegeocodeQuery queryParam = new RegeocodeQuery( - new LatLonPoint(latLng.latitude, latLng.longitude), - 200f, - GeocodeSearch.AMAP - ); - geocoderSearch.getFromLocationAsyn(queryParam); - geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { - @Override - public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int code) { + init { + aMap.setInfoWindowAdapter(object : AMap.InfoWindowAdapter { + override fun getInfoWindow(marker: Marker): View { + val infoWindow = + LayoutInflater.from(context).inflate(R.layout.map_info_window, null) + val locationView: TextView = infoWindow.findViewById(R.id.locationView) + val queryParam = RegeocodeQuery( + LatLonPoint(latLng.latitude, latLng.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { if (code == 1000) { //手动换行 - String address = regeocodeResult.getRegeocodeAddress().getFormatAddress(); - StringBuilder temp = new StringBuilder(); - if (address.length() > 20) { - temp.append(address.substring(0, 20)).append("\r\n").append(address.substring(20)); - } else { - temp.append(address); - } - locationView.setText(temp); + val address = regeocodeResult.regeocodeAddress.formatAddress + locationView.text = address.breakLine(22) } } - @Override - public void onGeocodeSearched(GeocodeResult geocodeResult, int i) { - - } - }); - return infoWindow; + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + return infoWindow } - @Override - public View getInfoContents(Marker marker) { - return null; + override fun getInfoContents(p0: Marker?): View? { + return null } - }); + }) } - public void showInfoWindow(LatLng latLng) { - this.latLng = latLng; - if (null != centerMarker) { - //缩放动画 - Animation scaleAnimation = new ScaleAnimation(1F, 1F, 0.75F, 1F); - //时间设置短点 - scaleAnimation.setDuration(500); - centerMarker.setAnimation(scaleAnimation); - centerMarker.startAnimation(); - - centerMarker.showInfoWindow(); - } + fun addCenterMarker() { + val options = MarkerOptions() + //对应Marker.setIcon方法 设置Marker的图片 + options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.map_pin)) + //设置infoWindow与锚点的相对位置 + options.anchor(0.5f, 1f) + //把中心点的坐标转换成屏幕像素位置 + val screenPosition: Point = aMap.projection.toScreenLocation(latLng) + //在地图上添加Marker并获取到Marker. + centerMarker = aMap.addMarker(options) + //给marker设置像素位置。 + centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y) + centerMarker.setAnchor(0.5f, 1f) } - - public void hideCenterMarkerInfoWindow() { - centerMarker.hideInfoWindow(); - if (null != centerMarker) { - Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.map_pin); - centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); - } + fun showInfoWindow(latLng: LatLng) { + this.latLng = latLng + //缩放动画 + val scaleAnimation: Animation = ScaleAnimation(1f, 1f, 0.75f, 1f) + //时间设置短点 + scaleAnimation.setDuration(500) + centerMarker.setAnimation(scaleAnimation) + centerMarker.startAnimation() + centerMarker.showInfoWindow() } - public void destroy() { - if (null != centerMarker) { - centerMarker.destroy(); - centerMarker.showInfoWindow(); - } + fun hideCenterMarkerInfoWindow() { + centerMarker.hideInfoWindow() + val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.map_pin) + centerMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)) } -} + + fun destroy() { + centerMarker.destroy() + centerMarker.showInfoWindow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt deleted file mode 100644 index 989a5d3..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.smarttube.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt index caf6683..9c9ad26 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smarttube.utils import android.Manifest +import android.os.Build import com.casic.smarttube.R @@ -10,15 +11,29 @@ * Array * ============================================================================================= * */ - val USER_PERMISSIONS = arrayOf( - Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, - Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.MANAGE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + val USER_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.MANAGE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } else { + arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + } val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") diff --git a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt index cd5410d..9fff4f3 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocationHelper.kt @@ -9,7 +9,7 @@ object LocationHelper { private const val kTag = "LocationHelper" - fun obtainCurrentLocation(context: Context, listener: ILocationListener) { + fun getCurrentLocation(context: Context, listener: ILocationListener) { val locationClient = AMapLocationClient(context) val locationOption = AMapLocationClientOption() //设置定位模式为高精度模式,AMapLocationMode.Battery_Saving为低功耗模式,AMapLocationMode.Device_Sensors是仅设备模式 diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index e523b36..fbab6e0 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -3,8 +3,6 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle -import android.os.CountDownTimer -import android.os.Handler import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -23,7 +21,6 @@ import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.GlideLoadEngine -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.LocationHelper import com.casic.smarttube.utils.QrConfigCreator @@ -39,30 +36,35 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File +import java.util.LinkedList +import java.util.Queue class AddDeviceActivity : KotlinBaseActivity() { private val kTag = "AddDeviceActivity" private lateinit var imageAdapter: EditableImageAdapter - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private val context = this + private val manager by lazy { QrManager.getInstance().init(QrConfigCreator.create(this)) } + private val uploadQueue: Queue = LinkedList() // 用于存储待上传的图片 + private var isUploading = false // 标记是否正在上传图片 private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") - private var selectedImages = ArrayList() private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -90,42 +92,22 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - weakReferenceHandler = WeakReferenceHandler(callback) uploadImageViewModel = ViewModelProvider(this)[UploadImageViewModel::class.java] + uploadImageViewModel.resultModel.observe(this) { + isUploading = false + if (it.code == 200) { + val url = it.data.toString() + imagePaths.add(url) + val oldSize = realPaths.size + realPaths.add(url.combineImagePath()) + imageAdapter.notifyItemRangeChanged(oldSize, 1) + startUploadNextImage() // 上传下一张图片 + } + } + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] - } - - override fun observeRequestState() { - deviceViewModel.loadState.observe(this) { - when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "处理中,请稍后") - LoadState.Success -> { - "添加设备成功".show(this) - LoadingDialogHub.dismiss() - this.finish() - } - - LoadState.Fail -> LoadingDialogHub.dismiss() - } - } - } - - override fun initEvent() { - val manager = QrManager.getInstance().init(QrConfigCreator.create(this)) - binding.scannerView.setOnClickListener { - manager.startScan(this) { - if (it.content.isNumber()) { - binding.deviceCodeView.setText(it.content) - } else { - "设备编号错误,请检查标签".show(context) - } - } - } - - binding.ownerShipView.setOnClickListener { - groupViewModel.obtainGroupList() - } groupViewModel.groupListModel.observe(this) { val groups = ArrayList() if (it.code == 200) { @@ -167,6 +149,39 @@ } } + val width = getScreenWidth() - 20.dp2px(this) + imageAdapter = EditableImageAdapter(this, realPaths, width, 3, 3) + binding.addImageRecyclerView.adapter = imageAdapter + } + + override fun observeRequestState() { + deviceViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> LoadingDialog.show(this, "处理中,请稍后") + LoadState.Success -> { + "添加设备成功".show(this) + LoadingDialog.dismiss() + finish() + } + + LoadState.Fail -> LoadingDialog.dismiss() + } + } + } + + override fun initEvent() { + binding.scannerView.setOnClickListener { + manager.startScan(this) { + if (it.content.isNumber()) { + binding.deviceCodeView.setText(it.content) + } else { + "设备编号错误,请检查标签".show(context) + } + } + } + + binding.ownerShipView.setOnClickListener { groupViewModel.getGroupList() } + //默认频率1min binding.collectIntervalView.text = frequency[0] binding.collectIntervalView.setOnClickListener { @@ -179,7 +194,6 @@ }).build().show() } - binding.locationImageView.setOnClickListener { BottomActionSheet.Builder().setContext(context).setItemTextColor(Color.BLUE) .setActionItemTitle(arrayListOf("自动定位", "手动选点")) @@ -187,11 +201,11 @@ override fun onActionItemClick(position: Int) { when (position) { 0 -> { - LoadingDialogHub.show(this@AddDeviceActivity, "定位中,请稍后...") - LocationHelper.obtainCurrentLocation(context, + LoadingDialog.show(this@AddDeviceActivity, "定位中,请稍后...") + LocationHelper.getCurrentLocation(context, object : LocationHelper.ILocationListener { override fun onAMapLocationGet(aMapLocation: AMapLocation?) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() if (aMapLocation == null) { binding.longitudeView.text = "定位失败" binding.latitudeView.text = "定位失败" @@ -227,8 +241,6 @@ }).build().show() } -// imageAdapter = EditableImageAdapter(this, 3, 13f) - binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { selectPicture() @@ -244,28 +256,12 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) -// imageAdapter.deleteImage(position) + realPaths.removeAt(position) + imageAdapter.notifyItemRemoved(position) + imageAdapter.notifyItemRangeChanged(position, realPaths.size - position) } }) - uploadImageViewModel.resultModel.observe(this) { - if (it.code == 200) { - if (imageAdapter.itemCount == selectedImages.size) { - LoadingDialogHub.dismiss() - } - if (imageAdapter.itemCount <= 3) { - val url = it.data.toString() - if (url.isNotBlank()) { - imagePaths.add(url) - realPaths.add(url.combineImagePath()) - } -// imageAdapter.setupImage(realPaths) - } else { - "最多只能上传3张图片".show(this) - } - } - } - binding.sceneEditView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -338,16 +334,9 @@ 0 -> { PictureSelector.create(context).openCamera(SelectMimeType.ofImage()) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "拍照保存失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - analyticalSelectResults(result[0]) + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -362,30 +351,9 @@ .setMaxSelectNum(3).isDisplayCamera(false) .setImageEngine(GlideLoadEngine.instance) .forResult(object : OnResultCallbackListener { - override fun onResult(result: ArrayList?) { - if (result == null) { - "选择照片失败,请重试".show(context) - return - } - LoadingDialogHub.show( - this@AddDeviceActivity, "图片上传中,请稍后..." - ) - selectedImages = result - // 线程控制图片压缩上传过程,防止速度过快导致压缩失败 - val sum = (result.size * 1000).toLong() - object : CountDownTimer(sum, 1000) { - override fun onTick(millisUntilFinished: Long) { - val i = millisUntilFinished / 1000 - val message = weakReferenceHandler.obtainMessage() - message.obj = result[i.toInt()] - message.what = 2022062501 - weakReferenceHandler.handleMessage(message) - } - - override fun onFinish() { - - } - }.start() + override fun onResult(result: ArrayList) { + uploadQueue.addAll(result) + startUploadNextImage() } override fun onCancel() { @@ -398,24 +366,26 @@ }).build().show() } - private val callback = Handler.Callback { - if (it.what == 2022062501) { - analyticalSelectResults(it.obj as LocalMedia) + private fun startUploadNextImage() { + if (isUploading || uploadQueue.isEmpty()) { + return } - true - } + isUploading = true + val media = uploadQueue.poll() + if (media != null) { + media.realPath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + Log.d(kTag, "onSuccess: " + file.absolutePath) + //上传图片 + uploadImageViewModel.uploadImage(file) + } - private fun analyticalSelectResults(result: LocalMedia) { - result.realPath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - Log.d(kTag, "onSuccess: " + file.absolutePath) - //上传图片 - uploadImageViewModel.uploadImage(file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + } else { + isUploading = false + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 2e490c3..f93caaf 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -16,7 +16,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -25,6 +24,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { @@ -143,8 +143,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index b393c0b..e9befb2 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -12,7 +12,6 @@ import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.TitleBarView @@ -156,8 +156,8 @@ override fun observeRequestState() { groupViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 47c0af6..a0025db 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -10,7 +10,6 @@ import com.casic.smarttube.extensions.getQuarterOfYear import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry @@ -22,6 +21,7 @@ import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -51,8 +51,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt index f947b2c..7287bff 100644 --- a/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/LoginActivity.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.databinding.ActivityLoginBinding import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils import com.casic.smarttube.vm.AuthenticateViewModel @@ -14,6 +13,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues class LoginActivity : KotlinBaseActivity() { @@ -45,11 +45,11 @@ override fun observeRequestState() { authenticateViewModel.loadState.observe(this) { - LoadingDialogHub.show(this, "登录中,请稍后") + LoadingDialog.show(this, "登录中,请稍后") } loginViewModel.loadState.observe(this) { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() } } diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 00bd76e..b5be93b 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -17,13 +17,13 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding import com.casic.smarttube.extensions.initImmersionBar -import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.LiteKitConstant import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -70,8 +70,8 @@ override fun observeRequestState() { deviceViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "数据加载中...") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index 4be4a14..c8a8b04 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -2,13 +2,11 @@ import android.content.Intent import android.graphics.Color -import android.location.Location import android.os.Bundle import com.amap.api.maps.AMap -import com.amap.api.maps.AMap.OnCameraChangeListener -import com.amap.api.maps.AMap.OnMapLoadedListener import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.UiSettings import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.MyLocationStyle @@ -20,7 +18,7 @@ class SelectLocationActivity : KotlinBaseActivity(), - AMap.OnMyLocationChangeListener, OnMapLoadedListener, OnCameraChangeListener { + AMap.OnMapLoadedListener, AMap.OnCameraChangeListener { private val kTag = "SelectLocationActivity" private lateinit var latLng: LatLng @@ -38,6 +36,8 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { + binding.mapView.onCreate(savedInstanceState) + aMap = binding.mapView.map aMap.mapType = AMap.MAP_TYPE_NORMAL val locationStyle = MyLocationStyle() @@ -50,7 +50,7 @@ locationStyle.radiusFillColor(Color.TRANSPARENT) aMap.myLocationStyle = locationStyle aMap.isMyLocationEnabled = true - val uiSettings = aMap.uiSettings + val uiSettings: UiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER //不许地图随手势倾斜角度 @@ -61,9 +61,10 @@ uiSettings.isMyLocationButtonEnabled = true //改变地图的缩放级别 aMap.moveCamera(CameraUpdateFactory.zoomTo(15f)) + centerMarkerView = CenterMarkerView(this, aMap) - centerMarkerView = CenterMarkerView(this) - centerMarkerView.initInfoWindowsView(aMap) + aMap.setOnMapLoadedListener(this) + aMap.setOnCameraChangeListener(this) } override fun observeRequestState() { @@ -71,10 +72,6 @@ } override fun initEvent() { - aMap.setOnMyLocationChangeListener(this) - aMap.setOnMapLoadedListener(this) - aMap.setOnCameraChangeListener(this) - binding.rightOperateView.setOnClickListener { val intent = Intent() intent.putExtra("longitude", latLng.longitude.toString()) @@ -84,15 +81,8 @@ } } - override fun onMyLocationChange(location: Location?) { - if (location == null) { - return - } - this.latLng = LatLng(location.latitude, location.longitude) - } - override fun onMapLoaded() { - centerMarkerView.addCenterMarker(aMap) + centerMarkerView.addCenterMarker() } override fun onCameraChange(cameraPosition: CameraPosition?) { @@ -101,17 +91,12 @@ } override fun onCameraChangeFinish(cameraPosition: CameraPosition) { - this.latLng = cameraPosition.target + latLng = cameraPosition.target //显示infoWindow centerMarkerView.showInfoWindow(latLng) } /**地图相关*********/ - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding.mapView.onCreate(savedInstanceState) - } - override fun onResume() { super.onResume() binding.mapView.onResume() diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index f73d92b..6890e74 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -26,8 +26,8 @@ val lastDataModel = MutableLiveData() val deleteResult = MutableLiveData() - fun obtainMapDeviceList() = launch({ - val response = RetrofitServiceManager.obtainMapDeviceList() + fun getMapDeviceList() = launch({ + val response = RetrofitServiceManager.getMapDeviceList() val responseCode = response.separateResponseCode() if (responseCode == 200) { mapDeviceModel.value = gson.fromJson( diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index 3477a7f..b88476b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -27,7 +27,7 @@ val changeGroupResult = MutableLiveData() fun obtainProGroupList() = launch({ - val response = RetrofitServiceManager.obtainProGroupList() + val response = RetrofitServiceManager.getProGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { groupModel.value = gson.fromJson( @@ -40,9 +40,9 @@ it.printStackTrace() }) - fun obtainDeviceListByGroup(wellGroupId: String) = launch({ + fun getDeviceListByGroup(wellGroupId: String) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.obtainDeviceListByGroup(wellGroupId) + val response = RetrofitServiceManager.getDeviceListByGroup(wellGroupId) val responseCode = response.separateResponseCode() if (responseCode == 200) { loadState.value = LoadState.Success @@ -74,8 +74,8 @@ it.printStackTrace() }) - fun obtainGroupList() = launch({ - val response = RetrofitServiceManager.obtainGroupList() + fun getGroupList() = launch({ + val response = RetrofitServiceManager.getGroupList() val responseCode = response.separateResponseCode() if (responseCode == 200) { groupListModel.value = gson.fromJson( diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 433fd65..13b3e39 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -6,29 +6,14 @@ android:background="@color/mainBackColor" android:orientation="vertical"> - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_show_left_image="false" + app:tbv_show_right_image="true" + app:tbv_text="@string/app_name" /> diff --git a/app/src/main/res/layout/item_group_rv.xml b/app/src/main/res/layout/item_group_rv.xml deleted file mode 100644 index e410627..0000000 --- a/app/src/main/res/layout/item_group_rv.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_group_rv_l.xml b/app/src/main/res/layout/item_group_rv_l.xml new file mode 100644 index 0000000..aae6bd1 --- /dev/null +++ b/app/src/main/res/layout/item_group_rv_l.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file