diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
-
+
+
+
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
new file mode 100644
index 0000000..7e8a367
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
@@ -0,0 +1,190 @@
+package com.casic.smarttube.model;
+
+import java.util.List;
+
+public class MapDeviceModel {
+
+ private int code;
+ private List data;
+ private String message;
+ private String success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(String success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String area;
+ private int deep;
+ private String responsibleDept;
+ private String wellCode;
+ private String groupId;
+ private String deptid;
+ private String staff;
+ private String photos;
+ private String wellType;
+ private String valid;
+ private String bfzt;
+ private String lngGaode;
+ private String latGaode;
+ private String wellName;
+ private String tel;
+ private String position;
+
+ public String getArea() {
+ return area;
+ }
+
+ public void setArea(String area) {
+ this.area = area;
+ }
+
+ public int getDeep() {
+ return deep;
+ }
+
+ public void setDeep(int deep) {
+ this.deep = deep;
+ }
+
+ public String getResponsibleDept() {
+ return responsibleDept;
+ }
+
+ public void setResponsibleDept(String responsibleDept) {
+ this.responsibleDept = responsibleDept;
+ }
+
+ public String getWellCode() {
+ return wellCode;
+ }
+
+ public void setWellCode(String wellCode) {
+ this.wellCode = wellCode;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getDeptid() {
+ return deptid;
+ }
+
+ public void setDeptid(String deptid) {
+ this.deptid = deptid;
+ }
+
+ public String getStaff() {
+ return staff;
+ }
+
+ public void setStaff(String staff) {
+ this.staff = staff;
+ }
+
+ public String getPhotos() {
+ return photos;
+ }
+
+ public void setPhotos(String photos) {
+ this.photos = photos;
+ }
+
+ public String getWellType() {
+ return wellType;
+ }
+
+ public void setWellType(String wellType) {
+ this.wellType = wellType;
+ }
+
+ public String getValid() {
+ return valid;
+ }
+
+ public void setValid(String valid) {
+ this.valid = valid;
+ }
+
+ public String getBfzt() {
+ return bfzt;
+ }
+
+ public void setBfzt(String bfzt) {
+ this.bfzt = bfzt;
+ }
+
+ public String getLngGaode() {
+ return lngGaode;
+ }
+
+ public void setLngGaode(String lngGaode) {
+ this.lngGaode = lngGaode;
+ }
+
+ public String getLatGaode() {
+ return latGaode;
+ }
+
+ public void setLatGaode(String latGaode) {
+ this.latGaode = latGaode;
+ }
+
+ public String getWellName() {
+ return wellName;
+ }
+
+ public void setWellName(String wellName) {
+ this.wellName = wellName;
+ }
+
+ public String getTel() {
+ return tel;
+ }
+
+ public void setTel(String tel) {
+ this.tel = tel;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+ }
+}
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
new file mode 100644
index 0000000..7e8a367
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
@@ -0,0 +1,190 @@
+package com.casic.smarttube.model;
+
+import java.util.List;
+
+public class MapDeviceModel {
+
+ private int code;
+ private List data;
+ private String message;
+ private String success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(String success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String area;
+ private int deep;
+ private String responsibleDept;
+ private String wellCode;
+ private String groupId;
+ private String deptid;
+ private String staff;
+ private String photos;
+ private String wellType;
+ private String valid;
+ private String bfzt;
+ private String lngGaode;
+ private String latGaode;
+ private String wellName;
+ private String tel;
+ private String position;
+
+ public String getArea() {
+ return area;
+ }
+
+ public void setArea(String area) {
+ this.area = area;
+ }
+
+ public int getDeep() {
+ return deep;
+ }
+
+ public void setDeep(int deep) {
+ this.deep = deep;
+ }
+
+ public String getResponsibleDept() {
+ return responsibleDept;
+ }
+
+ public void setResponsibleDept(String responsibleDept) {
+ this.responsibleDept = responsibleDept;
+ }
+
+ public String getWellCode() {
+ return wellCode;
+ }
+
+ public void setWellCode(String wellCode) {
+ this.wellCode = wellCode;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getDeptid() {
+ return deptid;
+ }
+
+ public void setDeptid(String deptid) {
+ this.deptid = deptid;
+ }
+
+ public String getStaff() {
+ return staff;
+ }
+
+ public void setStaff(String staff) {
+ this.staff = staff;
+ }
+
+ public String getPhotos() {
+ return photos;
+ }
+
+ public void setPhotos(String photos) {
+ this.photos = photos;
+ }
+
+ public String getWellType() {
+ return wellType;
+ }
+
+ public void setWellType(String wellType) {
+ this.wellType = wellType;
+ }
+
+ public String getValid() {
+ return valid;
+ }
+
+ public void setValid(String valid) {
+ this.valid = valid;
+ }
+
+ public String getBfzt() {
+ return bfzt;
+ }
+
+ public void setBfzt(String bfzt) {
+ this.bfzt = bfzt;
+ }
+
+ public String getLngGaode() {
+ return lngGaode;
+ }
+
+ public void setLngGaode(String lngGaode) {
+ this.lngGaode = lngGaode;
+ }
+
+ public String getLatGaode() {
+ return latGaode;
+ }
+
+ public void setLatGaode(String latGaode) {
+ this.latGaode = latGaode;
+ }
+
+ public String getWellName() {
+ return wellName;
+ }
+
+ public void setWellName(String wellName) {
+ this.wellName = wellName;
+ }
+
+ public String getTel() {
+ return tel;
+ }
+
+ public void setTel(String tel) {
+ this.tel = tel;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+ }
+}
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 af85fc7..4908afb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
@@ -26,6 +26,7 @@
* */
const val PERMISSIONS_CODE = 999
const val PAGE_LIMIT = 20
+ const val RADIUS_SIZE = 50 //相距多少米才聚合,单位:米
/**
* =============================================================================================
@@ -40,6 +41,7 @@
* =============================================================================================
* */
const val USER_DETAIL_MODEL = "userDetailModel"
+// const val SERVER_BASE_URL = "http://192.168.43.19:11643"
const val SERVER_BASE_URL = "http://111.198.10.15:11304"
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
const val ACCOUNT = "account"
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
new file mode 100644
index 0000000..7e8a367
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
@@ -0,0 +1,190 @@
+package com.casic.smarttube.model;
+
+import java.util.List;
+
+public class MapDeviceModel {
+
+ private int code;
+ private List data;
+ private String message;
+ private String success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(String success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String area;
+ private int deep;
+ private String responsibleDept;
+ private String wellCode;
+ private String groupId;
+ private String deptid;
+ private String staff;
+ private String photos;
+ private String wellType;
+ private String valid;
+ private String bfzt;
+ private String lngGaode;
+ private String latGaode;
+ private String wellName;
+ private String tel;
+ private String position;
+
+ public String getArea() {
+ return area;
+ }
+
+ public void setArea(String area) {
+ this.area = area;
+ }
+
+ public int getDeep() {
+ return deep;
+ }
+
+ public void setDeep(int deep) {
+ this.deep = deep;
+ }
+
+ public String getResponsibleDept() {
+ return responsibleDept;
+ }
+
+ public void setResponsibleDept(String responsibleDept) {
+ this.responsibleDept = responsibleDept;
+ }
+
+ public String getWellCode() {
+ return wellCode;
+ }
+
+ public void setWellCode(String wellCode) {
+ this.wellCode = wellCode;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getDeptid() {
+ return deptid;
+ }
+
+ public void setDeptid(String deptid) {
+ this.deptid = deptid;
+ }
+
+ public String getStaff() {
+ return staff;
+ }
+
+ public void setStaff(String staff) {
+ this.staff = staff;
+ }
+
+ public String getPhotos() {
+ return photos;
+ }
+
+ public void setPhotos(String photos) {
+ this.photos = photos;
+ }
+
+ public String getWellType() {
+ return wellType;
+ }
+
+ public void setWellType(String wellType) {
+ this.wellType = wellType;
+ }
+
+ public String getValid() {
+ return valid;
+ }
+
+ public void setValid(String valid) {
+ this.valid = valid;
+ }
+
+ public String getBfzt() {
+ return bfzt;
+ }
+
+ public void setBfzt(String bfzt) {
+ this.bfzt = bfzt;
+ }
+
+ public String getLngGaode() {
+ return lngGaode;
+ }
+
+ public void setLngGaode(String lngGaode) {
+ this.lngGaode = lngGaode;
+ }
+
+ public String getLatGaode() {
+ return latGaode;
+ }
+
+ public void setLatGaode(String latGaode) {
+ this.latGaode = latGaode;
+ }
+
+ public String getWellName() {
+ return wellName;
+ }
+
+ public void setWellName(String wellName) {
+ this.wellName = wellName;
+ }
+
+ public String getTel() {
+ return tel;
+ }
+
+ public void setTel(String tel) {
+ this.tel = tel;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+ }
+}
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 af85fc7..4908afb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
@@ -26,6 +26,7 @@
* */
const val PERMISSIONS_CODE = 999
const val PAGE_LIMIT = 20
+ const val RADIUS_SIZE = 50 //相距多少米才聚合,单位:米
/**
* =============================================================================================
@@ -40,6 +41,7 @@
* =============================================================================================
* */
const val USER_DETAIL_MODEL = "userDetailModel"
+// const val SERVER_BASE_URL = "http://192.168.43.19:11643"
const val SERVER_BASE_URL = "http://111.198.10.15:11304"
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
const val ACCOUNT = "account"
diff --git a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
index 14e2f56..a2c1338 100644
--- a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
@@ -34,17 +34,14 @@
}
fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String {
- val resultBytes =
- processData(srcData, publicKey)
+ val resultBytes = processData(srcData, publicKey)
return Base64.encodeToString(resultBytes, Base64.DEFAULT)
}
fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? {
var publicKey: PublicKey? = null
- val keyBytes =
- Base64.decode(publicKeyStr, Base64.DEFAULT)
- val keySpec =
- X509EncodedKeySpec(keyBytes)
+ val keyBytes = Base64.decode(publicKeyStr, Base64.DEFAULT)
+ val keySpec = X509EncodedKeySpec(keyBytes)
try {
val keyFactory = KeyFactory.getInstance("RSA")
publicKey = keyFactory.generatePublic(keySpec)
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
new file mode 100644
index 0000000..7e8a367
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
@@ -0,0 +1,190 @@
+package com.casic.smarttube.model;
+
+import java.util.List;
+
+public class MapDeviceModel {
+
+ private int code;
+ private List data;
+ private String message;
+ private String success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(String success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String area;
+ private int deep;
+ private String responsibleDept;
+ private String wellCode;
+ private String groupId;
+ private String deptid;
+ private String staff;
+ private String photos;
+ private String wellType;
+ private String valid;
+ private String bfzt;
+ private String lngGaode;
+ private String latGaode;
+ private String wellName;
+ private String tel;
+ private String position;
+
+ public String getArea() {
+ return area;
+ }
+
+ public void setArea(String area) {
+ this.area = area;
+ }
+
+ public int getDeep() {
+ return deep;
+ }
+
+ public void setDeep(int deep) {
+ this.deep = deep;
+ }
+
+ public String getResponsibleDept() {
+ return responsibleDept;
+ }
+
+ public void setResponsibleDept(String responsibleDept) {
+ this.responsibleDept = responsibleDept;
+ }
+
+ public String getWellCode() {
+ return wellCode;
+ }
+
+ public void setWellCode(String wellCode) {
+ this.wellCode = wellCode;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getDeptid() {
+ return deptid;
+ }
+
+ public void setDeptid(String deptid) {
+ this.deptid = deptid;
+ }
+
+ public String getStaff() {
+ return staff;
+ }
+
+ public void setStaff(String staff) {
+ this.staff = staff;
+ }
+
+ public String getPhotos() {
+ return photos;
+ }
+
+ public void setPhotos(String photos) {
+ this.photos = photos;
+ }
+
+ public String getWellType() {
+ return wellType;
+ }
+
+ public void setWellType(String wellType) {
+ this.wellType = wellType;
+ }
+
+ public String getValid() {
+ return valid;
+ }
+
+ public void setValid(String valid) {
+ this.valid = valid;
+ }
+
+ public String getBfzt() {
+ return bfzt;
+ }
+
+ public void setBfzt(String bfzt) {
+ this.bfzt = bfzt;
+ }
+
+ public String getLngGaode() {
+ return lngGaode;
+ }
+
+ public void setLngGaode(String lngGaode) {
+ this.lngGaode = lngGaode;
+ }
+
+ public String getLatGaode() {
+ return latGaode;
+ }
+
+ public void setLatGaode(String latGaode) {
+ this.latGaode = latGaode;
+ }
+
+ public String getWellName() {
+ return wellName;
+ }
+
+ public void setWellName(String wellName) {
+ this.wellName = wellName;
+ }
+
+ public String getTel() {
+ return tel;
+ }
+
+ public void setTel(String tel) {
+ this.tel = tel;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+ }
+}
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 af85fc7..4908afb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
@@ -26,6 +26,7 @@
* */
const val PERMISSIONS_CODE = 999
const val PAGE_LIMIT = 20
+ const val RADIUS_SIZE = 50 //相距多少米才聚合,单位:米
/**
* =============================================================================================
@@ -40,6 +41,7 @@
* =============================================================================================
* */
const val USER_DETAIL_MODEL = "userDetailModel"
+// const val SERVER_BASE_URL = "http://192.168.43.19:11643"
const val SERVER_BASE_URL = "http://111.198.10.15:11304"
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
const val ACCOUNT = "account"
diff --git a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
index 14e2f56..a2c1338 100644
--- a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
@@ -34,17 +34,14 @@
}
fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String {
- val resultBytes =
- processData(srcData, publicKey)
+ val resultBytes = processData(srcData, publicKey)
return Base64.encodeToString(resultBytes, Base64.DEFAULT)
}
fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? {
var publicKey: PublicKey? = null
- val keyBytes =
- Base64.decode(publicKeyStr, Base64.DEFAULT)
- val keySpec =
- X509EncodedKeySpec(keyBytes)
+ val keyBytes = Base64.decode(publicKeyStr, Base64.DEFAULT)
+ val keySpec = X509EncodedKeySpec(keyBytes)
try {
val keyFactory = KeyFactory.getInstance("RSA")
publicKey = keyFactory.generatePublic(keySpec)
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
index 738cc78..83cacb9 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
@@ -19,7 +19,7 @@
* @param secretKey 加密后的密码
*/
@FormUrlEncoded
- @POST("/user/login")
+ @POST("/user/appLogin")
suspend fun obtainLoginResult(
@Field("sid") sid: String,
@Field("username") account: String,
@@ -71,6 +71,12 @@
suspend fun obtainVersionResult(@Header("token") token: String): String
/**
+ * 地图设备列表
+ */
+ @POST("/tube/well/list")
+ suspend fun obtainMapDeviceList(@Header("token") token: String): String
+
+ /**
* 获取管盯分页列表
* */
@GET("/device/list")
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
new file mode 100644
index 0000000..7e8a367
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
@@ -0,0 +1,190 @@
+package com.casic.smarttube.model;
+
+import java.util.List;
+
+public class MapDeviceModel {
+
+ private int code;
+ private List data;
+ private String message;
+ private String success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(String success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String area;
+ private int deep;
+ private String responsibleDept;
+ private String wellCode;
+ private String groupId;
+ private String deptid;
+ private String staff;
+ private String photos;
+ private String wellType;
+ private String valid;
+ private String bfzt;
+ private String lngGaode;
+ private String latGaode;
+ private String wellName;
+ private String tel;
+ private String position;
+
+ public String getArea() {
+ return area;
+ }
+
+ public void setArea(String area) {
+ this.area = area;
+ }
+
+ public int getDeep() {
+ return deep;
+ }
+
+ public void setDeep(int deep) {
+ this.deep = deep;
+ }
+
+ public String getResponsibleDept() {
+ return responsibleDept;
+ }
+
+ public void setResponsibleDept(String responsibleDept) {
+ this.responsibleDept = responsibleDept;
+ }
+
+ public String getWellCode() {
+ return wellCode;
+ }
+
+ public void setWellCode(String wellCode) {
+ this.wellCode = wellCode;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getDeptid() {
+ return deptid;
+ }
+
+ public void setDeptid(String deptid) {
+ this.deptid = deptid;
+ }
+
+ public String getStaff() {
+ return staff;
+ }
+
+ public void setStaff(String staff) {
+ this.staff = staff;
+ }
+
+ public String getPhotos() {
+ return photos;
+ }
+
+ public void setPhotos(String photos) {
+ this.photos = photos;
+ }
+
+ public String getWellType() {
+ return wellType;
+ }
+
+ public void setWellType(String wellType) {
+ this.wellType = wellType;
+ }
+
+ public String getValid() {
+ return valid;
+ }
+
+ public void setValid(String valid) {
+ this.valid = valid;
+ }
+
+ public String getBfzt() {
+ return bfzt;
+ }
+
+ public void setBfzt(String bfzt) {
+ this.bfzt = bfzt;
+ }
+
+ public String getLngGaode() {
+ return lngGaode;
+ }
+
+ public void setLngGaode(String lngGaode) {
+ this.lngGaode = lngGaode;
+ }
+
+ public String getLatGaode() {
+ return latGaode;
+ }
+
+ public void setLatGaode(String latGaode) {
+ this.latGaode = latGaode;
+ }
+
+ public String getWellName() {
+ return wellName;
+ }
+
+ public void setWellName(String wellName) {
+ this.wellName = wellName;
+ }
+
+ public String getTel() {
+ return tel;
+ }
+
+ public void setTel(String tel) {
+ this.tel = tel;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+ }
+}
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 af85fc7..4908afb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
@@ -26,6 +26,7 @@
* */
const val PERMISSIONS_CODE = 999
const val PAGE_LIMIT = 20
+ const val RADIUS_SIZE = 50 //相距多少米才聚合,单位:米
/**
* =============================================================================================
@@ -40,6 +41,7 @@
* =============================================================================================
* */
const val USER_DETAIL_MODEL = "userDetailModel"
+// const val SERVER_BASE_URL = "http://192.168.43.19:11643"
const val SERVER_BASE_URL = "http://111.198.10.15:11304"
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
const val ACCOUNT = "account"
diff --git a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
index 14e2f56..a2c1338 100644
--- a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
@@ -34,17 +34,14 @@
}
fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String {
- val resultBytes =
- processData(srcData, publicKey)
+ val resultBytes = processData(srcData, publicKey)
return Base64.encodeToString(resultBytes, Base64.DEFAULT)
}
fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? {
var publicKey: PublicKey? = null
- val keyBytes =
- Base64.decode(publicKeyStr, Base64.DEFAULT)
- val keySpec =
- X509EncodedKeySpec(keyBytes)
+ val keyBytes = Base64.decode(publicKeyStr, Base64.DEFAULT)
+ val keySpec = X509EncodedKeySpec(keyBytes)
try {
val keyFactory = KeyFactory.getInstance("RSA")
publicKey = keyFactory.generatePublic(keySpec)
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
index 738cc78..83cacb9 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
@@ -19,7 +19,7 @@
* @param secretKey 加密后的密码
*/
@FormUrlEncoded
- @POST("/user/login")
+ @POST("/user/appLogin")
suspend fun obtainLoginResult(
@Field("sid") sid: String,
@Field("username") account: String,
@@ -71,6 +71,12 @@
suspend fun obtainVersionResult(@Header("token") token: String): String
/**
+ * 地图设备列表
+ */
+ @POST("/tube/well/list")
+ suspend fun obtainMapDeviceList(@Header("token") token: String): String
+
+ /**
* 获取管盯分页列表
* */
@GET("/device/list")
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
index c51557a..1e04ceb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
@@ -62,6 +62,13 @@
}
/**
+ * 地图设备列表
+ */
+ suspend fun obtainMapDeviceList(): String {
+ return api.obtainMapDeviceList(AuthenticationHelper.token!!)
+ }
+
+ /**
* 根据设备类型获取设备分页列表
*/
suspend fun obtainDeviceListByType(
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
new file mode 100644
index 0000000..7e8a367
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
@@ -0,0 +1,190 @@
+package com.casic.smarttube.model;
+
+import java.util.List;
+
+public class MapDeviceModel {
+
+ private int code;
+ private List data;
+ private String message;
+ private String success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(String success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String area;
+ private int deep;
+ private String responsibleDept;
+ private String wellCode;
+ private String groupId;
+ private String deptid;
+ private String staff;
+ private String photos;
+ private String wellType;
+ private String valid;
+ private String bfzt;
+ private String lngGaode;
+ private String latGaode;
+ private String wellName;
+ private String tel;
+ private String position;
+
+ public String getArea() {
+ return area;
+ }
+
+ public void setArea(String area) {
+ this.area = area;
+ }
+
+ public int getDeep() {
+ return deep;
+ }
+
+ public void setDeep(int deep) {
+ this.deep = deep;
+ }
+
+ public String getResponsibleDept() {
+ return responsibleDept;
+ }
+
+ public void setResponsibleDept(String responsibleDept) {
+ this.responsibleDept = responsibleDept;
+ }
+
+ public String getWellCode() {
+ return wellCode;
+ }
+
+ public void setWellCode(String wellCode) {
+ this.wellCode = wellCode;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getDeptid() {
+ return deptid;
+ }
+
+ public void setDeptid(String deptid) {
+ this.deptid = deptid;
+ }
+
+ public String getStaff() {
+ return staff;
+ }
+
+ public void setStaff(String staff) {
+ this.staff = staff;
+ }
+
+ public String getPhotos() {
+ return photos;
+ }
+
+ public void setPhotos(String photos) {
+ this.photos = photos;
+ }
+
+ public String getWellType() {
+ return wellType;
+ }
+
+ public void setWellType(String wellType) {
+ this.wellType = wellType;
+ }
+
+ public String getValid() {
+ return valid;
+ }
+
+ public void setValid(String valid) {
+ this.valid = valid;
+ }
+
+ public String getBfzt() {
+ return bfzt;
+ }
+
+ public void setBfzt(String bfzt) {
+ this.bfzt = bfzt;
+ }
+
+ public String getLngGaode() {
+ return lngGaode;
+ }
+
+ public void setLngGaode(String lngGaode) {
+ this.lngGaode = lngGaode;
+ }
+
+ public String getLatGaode() {
+ return latGaode;
+ }
+
+ public void setLatGaode(String latGaode) {
+ this.latGaode = latGaode;
+ }
+
+ public String getWellName() {
+ return wellName;
+ }
+
+ public void setWellName(String wellName) {
+ this.wellName = wellName;
+ }
+
+ public String getTel() {
+ return tel;
+ }
+
+ public void setTel(String tel) {
+ this.tel = tel;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+ }
+}
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 af85fc7..4908afb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
@@ -26,6 +26,7 @@
* */
const val PERMISSIONS_CODE = 999
const val PAGE_LIMIT = 20
+ const val RADIUS_SIZE = 50 //相距多少米才聚合,单位:米
/**
* =============================================================================================
@@ -40,6 +41,7 @@
* =============================================================================================
* */
const val USER_DETAIL_MODEL = "userDetailModel"
+// const val SERVER_BASE_URL = "http://192.168.43.19:11643"
const val SERVER_BASE_URL = "http://111.198.10.15:11304"
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
const val ACCOUNT = "account"
diff --git a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
index 14e2f56..a2c1338 100644
--- a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
@@ -34,17 +34,14 @@
}
fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String {
- val resultBytes =
- processData(srcData, publicKey)
+ val resultBytes = processData(srcData, publicKey)
return Base64.encodeToString(resultBytes, Base64.DEFAULT)
}
fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? {
var publicKey: PublicKey? = null
- val keyBytes =
- Base64.decode(publicKeyStr, Base64.DEFAULT)
- val keySpec =
- X509EncodedKeySpec(keyBytes)
+ val keyBytes = Base64.decode(publicKeyStr, Base64.DEFAULT)
+ val keySpec = X509EncodedKeySpec(keyBytes)
try {
val keyFactory = KeyFactory.getInstance("RSA")
publicKey = keyFactory.generatePublic(keySpec)
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
index 738cc78..83cacb9 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
@@ -19,7 +19,7 @@
* @param secretKey 加密后的密码
*/
@FormUrlEncoded
- @POST("/user/login")
+ @POST("/user/appLogin")
suspend fun obtainLoginResult(
@Field("sid") sid: String,
@Field("username") account: String,
@@ -71,6 +71,12 @@
suspend fun obtainVersionResult(@Header("token") token: String): String
/**
+ * 地图设备列表
+ */
+ @POST("/tube/well/list")
+ suspend fun obtainMapDeviceList(@Header("token") token: String): String
+
+ /**
* 获取管盯分页列表
* */
@GET("/device/list")
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
index c51557a..1e04ceb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
@@ -62,6 +62,13 @@
}
/**
+ * 地图设备列表
+ */
+ suspend fun obtainMapDeviceList(): String {
+ return api.obtainMapDeviceList(AuthenticationHelper.token!!)
+ }
+
+ /**
* 根据设备类型获取设备分页列表
*/
suspend fun obtainDeviceListByType(
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 910c4a9..f10db67 100644
--- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt
+++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt
@@ -23,10 +23,8 @@
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.activity.BigImageActivity
import com.pengxh.kt.lite.adapter.EditableImageAdapter
import com.pengxh.kt.lite.base.KotlinBaseActivity
-import com.pengxh.kt.lite.callback.OnImageCompressListener
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil
import com.pengxh.kt.lite.utils.WeakReferenceHandler
@@ -161,7 +159,7 @@
if (realPaths[position].isEmpty()) {
"图片加载失败,无法查看大图".show(context)
} else {
- navigatePageTo(position, realPaths)
+// navigatePageTo(position, realPaths)
}
}
@@ -298,17 +296,17 @@
// Log.d(kTag, "绝对路径:" + result.realPath)
// Log.d(kTag, "原图路径:" + result.originalPath)
// Log.d(kTag, "沙盒路径:" + result.sandboxPath)
- 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()
- }
- })
+// 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()
+// }
+// })
}
private lateinit var loadingDialog: QMUITipDialog
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
new file mode 100644
index 0000000..7e8a367
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
@@ -0,0 +1,190 @@
+package com.casic.smarttube.model;
+
+import java.util.List;
+
+public class MapDeviceModel {
+
+ private int code;
+ private List data;
+ private String message;
+ private String success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(String success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String area;
+ private int deep;
+ private String responsibleDept;
+ private String wellCode;
+ private String groupId;
+ private String deptid;
+ private String staff;
+ private String photos;
+ private String wellType;
+ private String valid;
+ private String bfzt;
+ private String lngGaode;
+ private String latGaode;
+ private String wellName;
+ private String tel;
+ private String position;
+
+ public String getArea() {
+ return area;
+ }
+
+ public void setArea(String area) {
+ this.area = area;
+ }
+
+ public int getDeep() {
+ return deep;
+ }
+
+ public void setDeep(int deep) {
+ this.deep = deep;
+ }
+
+ public String getResponsibleDept() {
+ return responsibleDept;
+ }
+
+ public void setResponsibleDept(String responsibleDept) {
+ this.responsibleDept = responsibleDept;
+ }
+
+ public String getWellCode() {
+ return wellCode;
+ }
+
+ public void setWellCode(String wellCode) {
+ this.wellCode = wellCode;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getDeptid() {
+ return deptid;
+ }
+
+ public void setDeptid(String deptid) {
+ this.deptid = deptid;
+ }
+
+ public String getStaff() {
+ return staff;
+ }
+
+ public void setStaff(String staff) {
+ this.staff = staff;
+ }
+
+ public String getPhotos() {
+ return photos;
+ }
+
+ public void setPhotos(String photos) {
+ this.photos = photos;
+ }
+
+ public String getWellType() {
+ return wellType;
+ }
+
+ public void setWellType(String wellType) {
+ this.wellType = wellType;
+ }
+
+ public String getValid() {
+ return valid;
+ }
+
+ public void setValid(String valid) {
+ this.valid = valid;
+ }
+
+ public String getBfzt() {
+ return bfzt;
+ }
+
+ public void setBfzt(String bfzt) {
+ this.bfzt = bfzt;
+ }
+
+ public String getLngGaode() {
+ return lngGaode;
+ }
+
+ public void setLngGaode(String lngGaode) {
+ this.lngGaode = lngGaode;
+ }
+
+ public String getLatGaode() {
+ return latGaode;
+ }
+
+ public void setLatGaode(String latGaode) {
+ this.latGaode = latGaode;
+ }
+
+ public String getWellName() {
+ return wellName;
+ }
+
+ public void setWellName(String wellName) {
+ this.wellName = wellName;
+ }
+
+ public String getTel() {
+ return tel;
+ }
+
+ public void setTel(String tel) {
+ this.tel = tel;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+ }
+}
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 af85fc7..4908afb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
@@ -26,6 +26,7 @@
* */
const val PERMISSIONS_CODE = 999
const val PAGE_LIMIT = 20
+ const val RADIUS_SIZE = 50 //相距多少米才聚合,单位:米
/**
* =============================================================================================
@@ -40,6 +41,7 @@
* =============================================================================================
* */
const val USER_DETAIL_MODEL = "userDetailModel"
+// const val SERVER_BASE_URL = "http://192.168.43.19:11643"
const val SERVER_BASE_URL = "http://111.198.10.15:11304"
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
const val ACCOUNT = "account"
diff --git a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
index 14e2f56..a2c1338 100644
--- a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
@@ -34,17 +34,14 @@
}
fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String {
- val resultBytes =
- processData(srcData, publicKey)
+ val resultBytes = processData(srcData, publicKey)
return Base64.encodeToString(resultBytes, Base64.DEFAULT)
}
fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? {
var publicKey: PublicKey? = null
- val keyBytes =
- Base64.decode(publicKeyStr, Base64.DEFAULT)
- val keySpec =
- X509EncodedKeySpec(keyBytes)
+ val keyBytes = Base64.decode(publicKeyStr, Base64.DEFAULT)
+ val keySpec = X509EncodedKeySpec(keyBytes)
try {
val keyFactory = KeyFactory.getInstance("RSA")
publicKey = keyFactory.generatePublic(keySpec)
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
index 738cc78..83cacb9 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
@@ -19,7 +19,7 @@
* @param secretKey 加密后的密码
*/
@FormUrlEncoded
- @POST("/user/login")
+ @POST("/user/appLogin")
suspend fun obtainLoginResult(
@Field("sid") sid: String,
@Field("username") account: String,
@@ -71,6 +71,12 @@
suspend fun obtainVersionResult(@Header("token") token: String): String
/**
+ * 地图设备列表
+ */
+ @POST("/tube/well/list")
+ suspend fun obtainMapDeviceList(@Header("token") token: String): String
+
+ /**
* 获取管盯分页列表
* */
@GET("/device/list")
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
index c51557a..1e04ceb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
@@ -62,6 +62,13 @@
}
/**
+ * 地图设备列表
+ */
+ suspend fun obtainMapDeviceList(): String {
+ return api.obtainMapDeviceList(AuthenticationHelper.token!!)
+ }
+
+ /**
* 根据设备类型获取设备分页列表
*/
suspend fun obtainDeviceListByType(
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 910c4a9..f10db67 100644
--- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt
+++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt
@@ -23,10 +23,8 @@
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.activity.BigImageActivity
import com.pengxh.kt.lite.adapter.EditableImageAdapter
import com.pengxh.kt.lite.base.KotlinBaseActivity
-import com.pengxh.kt.lite.callback.OnImageCompressListener
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil
import com.pengxh.kt.lite.utils.WeakReferenceHandler
@@ -161,7 +159,7 @@
if (realPaths[position].isEmpty()) {
"图片加载失败,无法查看大图".show(context)
} else {
- navigatePageTo(position, realPaths)
+// navigatePageTo(position, realPaths)
}
}
@@ -298,17 +296,17 @@
// Log.d(kTag, "绝对路径:" + result.realPath)
// Log.d(kTag, "原图路径:" + result.originalPath)
// Log.d(kTag, "沙盒路径:" + result.sandboxPath)
- 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()
- }
- })
+// 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()
+// }
+// })
}
private lateinit var loadingDialog: QMUITipDialog
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 4d0b36f..5b2f97f 100644
--- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt
+++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt
@@ -6,6 +6,7 @@
import com.casic.smarttube.extensions.toErrorMessage
import com.casic.smarttube.model.DeviceHistoryDataModel
import com.casic.smarttube.model.DeviceListModel
+import com.casic.smarttube.model.MapDeviceModel
import com.casic.smarttube.utils.retrofit.RetrofitServiceManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
@@ -16,9 +17,23 @@
class DeviceViewModel : BaseViewModel() {
private val gson = Gson()
- val deviceListModel = MutableLiveData()
+ val mapDeviceModel = MutableLiveData()
val historyDataModel = MutableLiveData()
+ fun obtainMapDeviceList() = launch({
+ val response = RetrofitServiceManager.obtainMapDeviceList()
+ val responseCode = response.separateResponseCode()
+ if (responseCode == 200) {
+ mapDeviceModel.value = gson.fromJson(
+ response, object : TypeToken() {}.type
+ )
+ } else {
+ response.toErrorMessage().show(BaseApplication.obtainInstance())
+ }
+ }, {
+ it.printStackTrace()
+ })
+
fun obtainDeviceListByType(
deptid: String, keywords: String, isOnline: String, page: Int
) = launch({
@@ -26,9 +41,9 @@
RetrofitServiceManager.obtainDeviceListByType(deptid, keywords, isOnline, page)
val responseCode = response.separateResponseCode()
if (responseCode == 200) {
- deviceListModel.value = gson.fromJson(
- response, object : TypeToken() {}.type
- )
+// deviceListModel.value = gson.fromJson(
+// response, object : TypeToken() {}.type
+// )
} else {
response.toErrorMessage().show(BaseApplication.obtainInstance())
}
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
new file mode 100644
index 0000000..7e8a367
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
@@ -0,0 +1,190 @@
+package com.casic.smarttube.model;
+
+import java.util.List;
+
+public class MapDeviceModel {
+
+ private int code;
+ private List data;
+ private String message;
+ private String success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(String success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String area;
+ private int deep;
+ private String responsibleDept;
+ private String wellCode;
+ private String groupId;
+ private String deptid;
+ private String staff;
+ private String photos;
+ private String wellType;
+ private String valid;
+ private String bfzt;
+ private String lngGaode;
+ private String latGaode;
+ private String wellName;
+ private String tel;
+ private String position;
+
+ public String getArea() {
+ return area;
+ }
+
+ public void setArea(String area) {
+ this.area = area;
+ }
+
+ public int getDeep() {
+ return deep;
+ }
+
+ public void setDeep(int deep) {
+ this.deep = deep;
+ }
+
+ public String getResponsibleDept() {
+ return responsibleDept;
+ }
+
+ public void setResponsibleDept(String responsibleDept) {
+ this.responsibleDept = responsibleDept;
+ }
+
+ public String getWellCode() {
+ return wellCode;
+ }
+
+ public void setWellCode(String wellCode) {
+ this.wellCode = wellCode;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getDeptid() {
+ return deptid;
+ }
+
+ public void setDeptid(String deptid) {
+ this.deptid = deptid;
+ }
+
+ public String getStaff() {
+ return staff;
+ }
+
+ public void setStaff(String staff) {
+ this.staff = staff;
+ }
+
+ public String getPhotos() {
+ return photos;
+ }
+
+ public void setPhotos(String photos) {
+ this.photos = photos;
+ }
+
+ public String getWellType() {
+ return wellType;
+ }
+
+ public void setWellType(String wellType) {
+ this.wellType = wellType;
+ }
+
+ public String getValid() {
+ return valid;
+ }
+
+ public void setValid(String valid) {
+ this.valid = valid;
+ }
+
+ public String getBfzt() {
+ return bfzt;
+ }
+
+ public void setBfzt(String bfzt) {
+ this.bfzt = bfzt;
+ }
+
+ public String getLngGaode() {
+ return lngGaode;
+ }
+
+ public void setLngGaode(String lngGaode) {
+ this.lngGaode = lngGaode;
+ }
+
+ public String getLatGaode() {
+ return latGaode;
+ }
+
+ public void setLatGaode(String latGaode) {
+ this.latGaode = latGaode;
+ }
+
+ public String getWellName() {
+ return wellName;
+ }
+
+ public void setWellName(String wellName) {
+ this.wellName = wellName;
+ }
+
+ public String getTel() {
+ return tel;
+ }
+
+ public void setTel(String tel) {
+ this.tel = tel;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+ }
+}
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 af85fc7..4908afb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
@@ -26,6 +26,7 @@
* */
const val PERMISSIONS_CODE = 999
const val PAGE_LIMIT = 20
+ const val RADIUS_SIZE = 50 //相距多少米才聚合,单位:米
/**
* =============================================================================================
@@ -40,6 +41,7 @@
* =============================================================================================
* */
const val USER_DETAIL_MODEL = "userDetailModel"
+// const val SERVER_BASE_URL = "http://192.168.43.19:11643"
const val SERVER_BASE_URL = "http://111.198.10.15:11304"
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
const val ACCOUNT = "account"
diff --git a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
index 14e2f56..a2c1338 100644
--- a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
@@ -34,17 +34,14 @@
}
fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String {
- val resultBytes =
- processData(srcData, publicKey)
+ val resultBytes = processData(srcData, publicKey)
return Base64.encodeToString(resultBytes, Base64.DEFAULT)
}
fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? {
var publicKey: PublicKey? = null
- val keyBytes =
- Base64.decode(publicKeyStr, Base64.DEFAULT)
- val keySpec =
- X509EncodedKeySpec(keyBytes)
+ val keyBytes = Base64.decode(publicKeyStr, Base64.DEFAULT)
+ val keySpec = X509EncodedKeySpec(keyBytes)
try {
val keyFactory = KeyFactory.getInstance("RSA")
publicKey = keyFactory.generatePublic(keySpec)
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
index 738cc78..83cacb9 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
@@ -19,7 +19,7 @@
* @param secretKey 加密后的密码
*/
@FormUrlEncoded
- @POST("/user/login")
+ @POST("/user/appLogin")
suspend fun obtainLoginResult(
@Field("sid") sid: String,
@Field("username") account: String,
@@ -71,6 +71,12 @@
suspend fun obtainVersionResult(@Header("token") token: String): String
/**
+ * 地图设备列表
+ */
+ @POST("/tube/well/list")
+ suspend fun obtainMapDeviceList(@Header("token") token: String): String
+
+ /**
* 获取管盯分页列表
* */
@GET("/device/list")
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
index c51557a..1e04ceb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
@@ -62,6 +62,13 @@
}
/**
+ * 地图设备列表
+ */
+ suspend fun obtainMapDeviceList(): String {
+ return api.obtainMapDeviceList(AuthenticationHelper.token!!)
+ }
+
+ /**
* 根据设备类型获取设备分页列表
*/
suspend fun obtainDeviceListByType(
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 910c4a9..f10db67 100644
--- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt
+++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt
@@ -23,10 +23,8 @@
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.activity.BigImageActivity
import com.pengxh.kt.lite.adapter.EditableImageAdapter
import com.pengxh.kt.lite.base.KotlinBaseActivity
-import com.pengxh.kt.lite.callback.OnImageCompressListener
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil
import com.pengxh.kt.lite.utils.WeakReferenceHandler
@@ -161,7 +159,7 @@
if (realPaths[position].isEmpty()) {
"图片加载失败,无法查看大图".show(context)
} else {
- navigatePageTo(position, realPaths)
+// navigatePageTo(position, realPaths)
}
}
@@ -298,17 +296,17 @@
// Log.d(kTag, "绝对路径:" + result.realPath)
// Log.d(kTag, "原图路径:" + result.originalPath)
// Log.d(kTag, "沙盒路径:" + result.sandboxPath)
- 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()
- }
- })
+// 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()
+// }
+// })
}
private lateinit var loadingDialog: QMUITipDialog
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 4d0b36f..5b2f97f 100644
--- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt
+++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt
@@ -6,6 +6,7 @@
import com.casic.smarttube.extensions.toErrorMessage
import com.casic.smarttube.model.DeviceHistoryDataModel
import com.casic.smarttube.model.DeviceListModel
+import com.casic.smarttube.model.MapDeviceModel
import com.casic.smarttube.utils.retrofit.RetrofitServiceManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
@@ -16,9 +17,23 @@
class DeviceViewModel : BaseViewModel() {
private val gson = Gson()
- val deviceListModel = MutableLiveData()
+ val mapDeviceModel = MutableLiveData()
val historyDataModel = MutableLiveData()
+ fun obtainMapDeviceList() = launch({
+ val response = RetrofitServiceManager.obtainMapDeviceList()
+ val responseCode = response.separateResponseCode()
+ if (responseCode == 200) {
+ mapDeviceModel.value = gson.fromJson(
+ response, object : TypeToken() {}.type
+ )
+ } else {
+ response.toErrorMessage().show(BaseApplication.obtainInstance())
+ }
+ }, {
+ it.printStackTrace()
+ })
+
fun obtainDeviceListByType(
deptid: String, keywords: String, isOnline: String, page: Int
) = launch({
@@ -26,9 +41,9 @@
RetrofitServiceManager.obtainDeviceListByType(deptid, keywords, isOnline, page)
val responseCode = response.separateResponseCode()
if (responseCode == 200) {
- deviceListModel.value = gson.fromJson(
- response, object : TypeToken() {}.type
- )
+// deviceListModel.value = gson.fromJson(
+// response, object : TypeToken() {}.type
+// )
} else {
response.toErrorMessage().show(BaseApplication.obtainInstance())
}
diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt
new file mode 100644
index 0000000..cb14054
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt
@@ -0,0 +1,102 @@
+package com.casic.smarttube.widgets
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Point
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.TextView
+import com.amap.api.maps.Projection
+import com.amap.api.maps.model.BitmapDescriptorFactory
+import com.amap.api.maps.model.LatLng
+import com.amap.api.maps.model.LatLngBounds
+import com.amap.api.maps.model.MarkerOptions
+import com.casic.smarttube.R
+import com.pengxh.kt.lite.extensions.toBitmap
+import java.util.*
+
+class GaoDeClusterMarkerView(
+ private val context: Context, firstMarkers: MarkerOptions,
+ projection: Projection, gridSize: Int
+) {
+ //当前可观区域里的 聚合过之后的集合
+ private val includeMarkers: ArrayList
+
+ // 创建区域
+ val bounds: LatLngBounds
+ var options: MarkerOptions = MarkerOptions()
+
+ init {
+ val screenLocation = projection.toScreenLocation(firstMarkers.position)
+ //范围类
+ val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize)
+ //范围类
+ val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize)
+ bounds = LatLngBounds(
+ projection.fromScreenLocation(southwestPoint),
+ projection.fromScreenLocation(northeastPoint)
+ )
+ //设置初始化marker属性
+ options.anchor(0.5f, 1.3f)
+ .title(firstMarkers.title)
+ .position(firstMarkers.position)
+ .icon(firstMarkers.icon)
+ .snippet(firstMarkers.snippet)
+ .draggable(false)
+ includeMarkers = ArrayList()
+ includeMarkers.add(firstMarkers)
+ }
+
+ /**
+ * 添加marker
+ */
+ fun addMarker(markerOptions: MarkerOptions) {
+ includeMarkers.add(markerOptions) // 添加到列表中
+ }
+
+ /**
+ * 设置聚合点的中心位置以及图标
+ */
+ fun setPositionAndIcon() {
+ val size = includeMarkers.size
+ var lat = 0.0
+ var lng = 0.0
+ // 一个的时候
+ if (size == 1) { //设置marker单个属性
+ // 设置marker位置
+ options.position(
+ LatLng(
+ includeMarkers[0].position.latitude,
+ includeMarkers[0].position.longitude
+ )
+ )
+ } else { // 聚合的时候
+ //设置marker聚合属性
+ for (op in includeMarkers) {
+ lat += op.position.latitude
+ lng += op.position.longitude
+ }
+ // 设置marker的位置为中心位置为聚集点的平均位置
+ options.position(LatLng(lat / size, lng / size))
+ }
+ options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size)))
+ }
+
+ /**
+ * marker视图
+ */
+ private fun getBitmap(num: Int): Bitmap? {
+ val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null)
+ val wellCountView = view.findViewById(R.id.wellCountView)
+ return if (num > 1) {
+ wellCountView.visibility = View.VISIBLE
+ wellCountView.text = String.format("${num}个")
+ wellCountView.gravity = Gravity.CENTER
+ view.toBitmap()
+ } else {
+ wellCountView.visibility = View.GONE
+ BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
new file mode 100644
index 0000000..7e8a367
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
@@ -0,0 +1,190 @@
+package com.casic.smarttube.model;
+
+import java.util.List;
+
+public class MapDeviceModel {
+
+ private int code;
+ private List data;
+ private String message;
+ private String success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(String success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String area;
+ private int deep;
+ private String responsibleDept;
+ private String wellCode;
+ private String groupId;
+ private String deptid;
+ private String staff;
+ private String photos;
+ private String wellType;
+ private String valid;
+ private String bfzt;
+ private String lngGaode;
+ private String latGaode;
+ private String wellName;
+ private String tel;
+ private String position;
+
+ public String getArea() {
+ return area;
+ }
+
+ public void setArea(String area) {
+ this.area = area;
+ }
+
+ public int getDeep() {
+ return deep;
+ }
+
+ public void setDeep(int deep) {
+ this.deep = deep;
+ }
+
+ public String getResponsibleDept() {
+ return responsibleDept;
+ }
+
+ public void setResponsibleDept(String responsibleDept) {
+ this.responsibleDept = responsibleDept;
+ }
+
+ public String getWellCode() {
+ return wellCode;
+ }
+
+ public void setWellCode(String wellCode) {
+ this.wellCode = wellCode;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getDeptid() {
+ return deptid;
+ }
+
+ public void setDeptid(String deptid) {
+ this.deptid = deptid;
+ }
+
+ public String getStaff() {
+ return staff;
+ }
+
+ public void setStaff(String staff) {
+ this.staff = staff;
+ }
+
+ public String getPhotos() {
+ return photos;
+ }
+
+ public void setPhotos(String photos) {
+ this.photos = photos;
+ }
+
+ public String getWellType() {
+ return wellType;
+ }
+
+ public void setWellType(String wellType) {
+ this.wellType = wellType;
+ }
+
+ public String getValid() {
+ return valid;
+ }
+
+ public void setValid(String valid) {
+ this.valid = valid;
+ }
+
+ public String getBfzt() {
+ return bfzt;
+ }
+
+ public void setBfzt(String bfzt) {
+ this.bfzt = bfzt;
+ }
+
+ public String getLngGaode() {
+ return lngGaode;
+ }
+
+ public void setLngGaode(String lngGaode) {
+ this.lngGaode = lngGaode;
+ }
+
+ public String getLatGaode() {
+ return latGaode;
+ }
+
+ public void setLatGaode(String latGaode) {
+ this.latGaode = latGaode;
+ }
+
+ public String getWellName() {
+ return wellName;
+ }
+
+ public void setWellName(String wellName) {
+ this.wellName = wellName;
+ }
+
+ public String getTel() {
+ return tel;
+ }
+
+ public void setTel(String tel) {
+ this.tel = tel;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+ }
+}
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 af85fc7..4908afb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
@@ -26,6 +26,7 @@
* */
const val PERMISSIONS_CODE = 999
const val PAGE_LIMIT = 20
+ const val RADIUS_SIZE = 50 //相距多少米才聚合,单位:米
/**
* =============================================================================================
@@ -40,6 +41,7 @@
* =============================================================================================
* */
const val USER_DETAIL_MODEL = "userDetailModel"
+// const val SERVER_BASE_URL = "http://192.168.43.19:11643"
const val SERVER_BASE_URL = "http://111.198.10.15:11304"
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
const val ACCOUNT = "account"
diff --git a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
index 14e2f56..a2c1338 100644
--- a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
@@ -34,17 +34,14 @@
}
fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String {
- val resultBytes =
- processData(srcData, publicKey)
+ val resultBytes = processData(srcData, publicKey)
return Base64.encodeToString(resultBytes, Base64.DEFAULT)
}
fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? {
var publicKey: PublicKey? = null
- val keyBytes =
- Base64.decode(publicKeyStr, Base64.DEFAULT)
- val keySpec =
- X509EncodedKeySpec(keyBytes)
+ val keyBytes = Base64.decode(publicKeyStr, Base64.DEFAULT)
+ val keySpec = X509EncodedKeySpec(keyBytes)
try {
val keyFactory = KeyFactory.getInstance("RSA")
publicKey = keyFactory.generatePublic(keySpec)
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
index 738cc78..83cacb9 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
@@ -19,7 +19,7 @@
* @param secretKey 加密后的密码
*/
@FormUrlEncoded
- @POST("/user/login")
+ @POST("/user/appLogin")
suspend fun obtainLoginResult(
@Field("sid") sid: String,
@Field("username") account: String,
@@ -71,6 +71,12 @@
suspend fun obtainVersionResult(@Header("token") token: String): String
/**
+ * 地图设备列表
+ */
+ @POST("/tube/well/list")
+ suspend fun obtainMapDeviceList(@Header("token") token: String): String
+
+ /**
* 获取管盯分页列表
* */
@GET("/device/list")
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
index c51557a..1e04ceb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
@@ -62,6 +62,13 @@
}
/**
+ * 地图设备列表
+ */
+ suspend fun obtainMapDeviceList(): String {
+ return api.obtainMapDeviceList(AuthenticationHelper.token!!)
+ }
+
+ /**
* 根据设备类型获取设备分页列表
*/
suspend fun obtainDeviceListByType(
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 910c4a9..f10db67 100644
--- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt
+++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt
@@ -23,10 +23,8 @@
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.activity.BigImageActivity
import com.pengxh.kt.lite.adapter.EditableImageAdapter
import com.pengxh.kt.lite.base.KotlinBaseActivity
-import com.pengxh.kt.lite.callback.OnImageCompressListener
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil
import com.pengxh.kt.lite.utils.WeakReferenceHandler
@@ -161,7 +159,7 @@
if (realPaths[position].isEmpty()) {
"图片加载失败,无法查看大图".show(context)
} else {
- navigatePageTo(position, realPaths)
+// navigatePageTo(position, realPaths)
}
}
@@ -298,17 +296,17 @@
// Log.d(kTag, "绝对路径:" + result.realPath)
// Log.d(kTag, "原图路径:" + result.originalPath)
// Log.d(kTag, "沙盒路径:" + result.sandboxPath)
- 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()
- }
- })
+// 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()
+// }
+// })
}
private lateinit var loadingDialog: QMUITipDialog
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 4d0b36f..5b2f97f 100644
--- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt
+++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt
@@ -6,6 +6,7 @@
import com.casic.smarttube.extensions.toErrorMessage
import com.casic.smarttube.model.DeviceHistoryDataModel
import com.casic.smarttube.model.DeviceListModel
+import com.casic.smarttube.model.MapDeviceModel
import com.casic.smarttube.utils.retrofit.RetrofitServiceManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
@@ -16,9 +17,23 @@
class DeviceViewModel : BaseViewModel() {
private val gson = Gson()
- val deviceListModel = MutableLiveData()
+ val mapDeviceModel = MutableLiveData()
val historyDataModel = MutableLiveData()
+ fun obtainMapDeviceList() = launch({
+ val response = RetrofitServiceManager.obtainMapDeviceList()
+ val responseCode = response.separateResponseCode()
+ if (responseCode == 200) {
+ mapDeviceModel.value = gson.fromJson(
+ response, object : TypeToken() {}.type
+ )
+ } else {
+ response.toErrorMessage().show(BaseApplication.obtainInstance())
+ }
+ }, {
+ it.printStackTrace()
+ })
+
fun obtainDeviceListByType(
deptid: String, keywords: String, isOnline: String, page: Int
) = launch({
@@ -26,9 +41,9 @@
RetrofitServiceManager.obtainDeviceListByType(deptid, keywords, isOnline, page)
val responseCode = response.separateResponseCode()
if (responseCode == 200) {
- deviceListModel.value = gson.fromJson(
- response, object : TypeToken() {}.type
- )
+// deviceListModel.value = gson.fromJson(
+// response, object : TypeToken() {}.type
+// )
} else {
response.toErrorMessage().show(BaseApplication.obtainInstance())
}
diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt
new file mode 100644
index 0000000..cb14054
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt
@@ -0,0 +1,102 @@
+package com.casic.smarttube.widgets
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Point
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.TextView
+import com.amap.api.maps.Projection
+import com.amap.api.maps.model.BitmapDescriptorFactory
+import com.amap.api.maps.model.LatLng
+import com.amap.api.maps.model.LatLngBounds
+import com.amap.api.maps.model.MarkerOptions
+import com.casic.smarttube.R
+import com.pengxh.kt.lite.extensions.toBitmap
+import java.util.*
+
+class GaoDeClusterMarkerView(
+ private val context: Context, firstMarkers: MarkerOptions,
+ projection: Projection, gridSize: Int
+) {
+ //当前可观区域里的 聚合过之后的集合
+ private val includeMarkers: ArrayList
+
+ // 创建区域
+ val bounds: LatLngBounds
+ var options: MarkerOptions = MarkerOptions()
+
+ init {
+ val screenLocation = projection.toScreenLocation(firstMarkers.position)
+ //范围类
+ val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize)
+ //范围类
+ val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize)
+ bounds = LatLngBounds(
+ projection.fromScreenLocation(southwestPoint),
+ projection.fromScreenLocation(northeastPoint)
+ )
+ //设置初始化marker属性
+ options.anchor(0.5f, 1.3f)
+ .title(firstMarkers.title)
+ .position(firstMarkers.position)
+ .icon(firstMarkers.icon)
+ .snippet(firstMarkers.snippet)
+ .draggable(false)
+ includeMarkers = ArrayList()
+ includeMarkers.add(firstMarkers)
+ }
+
+ /**
+ * 添加marker
+ */
+ fun addMarker(markerOptions: MarkerOptions) {
+ includeMarkers.add(markerOptions) // 添加到列表中
+ }
+
+ /**
+ * 设置聚合点的中心位置以及图标
+ */
+ fun setPositionAndIcon() {
+ val size = includeMarkers.size
+ var lat = 0.0
+ var lng = 0.0
+ // 一个的时候
+ if (size == 1) { //设置marker单个属性
+ // 设置marker位置
+ options.position(
+ LatLng(
+ includeMarkers[0].position.latitude,
+ includeMarkers[0].position.longitude
+ )
+ )
+ } else { // 聚合的时候
+ //设置marker聚合属性
+ for (op in includeMarkers) {
+ lat += op.position.latitude
+ lng += op.position.longitude
+ }
+ // 设置marker的位置为中心位置为聚集点的平均位置
+ options.position(LatLng(lat / size, lng / size))
+ }
+ options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size)))
+ }
+
+ /**
+ * marker视图
+ */
+ private fun getBitmap(num: Int): Bitmap? {
+ val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null)
+ val wellCountView = view.findViewById(R.id.wellCountView)
+ return if (num > 1) {
+ wellCountView.visibility = View.VISIBLE
+ wellCountView.text = String.format("${num}个")
+ wellCountView.gravity = Gravity.CENTER
+ view.toBitmap()
+ } else {
+ wellCountView.visibility = View.GONE
+ BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_solid_layout_main_radius_5.xml b/app/src/main/res/drawable/bg_solid_layout_main_radius_5.xml
new file mode 100644
index 0000000..e329b7d
--- /dev/null
+++ b/app/src/main/res/drawable/bg_solid_layout_main_radius_5.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
new file mode 100644
index 0000000..7e8a367
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
@@ -0,0 +1,190 @@
+package com.casic.smarttube.model;
+
+import java.util.List;
+
+public class MapDeviceModel {
+
+ private int code;
+ private List data;
+ private String message;
+ private String success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(String success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String area;
+ private int deep;
+ private String responsibleDept;
+ private String wellCode;
+ private String groupId;
+ private String deptid;
+ private String staff;
+ private String photos;
+ private String wellType;
+ private String valid;
+ private String bfzt;
+ private String lngGaode;
+ private String latGaode;
+ private String wellName;
+ private String tel;
+ private String position;
+
+ public String getArea() {
+ return area;
+ }
+
+ public void setArea(String area) {
+ this.area = area;
+ }
+
+ public int getDeep() {
+ return deep;
+ }
+
+ public void setDeep(int deep) {
+ this.deep = deep;
+ }
+
+ public String getResponsibleDept() {
+ return responsibleDept;
+ }
+
+ public void setResponsibleDept(String responsibleDept) {
+ this.responsibleDept = responsibleDept;
+ }
+
+ public String getWellCode() {
+ return wellCode;
+ }
+
+ public void setWellCode(String wellCode) {
+ this.wellCode = wellCode;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getDeptid() {
+ return deptid;
+ }
+
+ public void setDeptid(String deptid) {
+ this.deptid = deptid;
+ }
+
+ public String getStaff() {
+ return staff;
+ }
+
+ public void setStaff(String staff) {
+ this.staff = staff;
+ }
+
+ public String getPhotos() {
+ return photos;
+ }
+
+ public void setPhotos(String photos) {
+ this.photos = photos;
+ }
+
+ public String getWellType() {
+ return wellType;
+ }
+
+ public void setWellType(String wellType) {
+ this.wellType = wellType;
+ }
+
+ public String getValid() {
+ return valid;
+ }
+
+ public void setValid(String valid) {
+ this.valid = valid;
+ }
+
+ public String getBfzt() {
+ return bfzt;
+ }
+
+ public void setBfzt(String bfzt) {
+ this.bfzt = bfzt;
+ }
+
+ public String getLngGaode() {
+ return lngGaode;
+ }
+
+ public void setLngGaode(String lngGaode) {
+ this.lngGaode = lngGaode;
+ }
+
+ public String getLatGaode() {
+ return latGaode;
+ }
+
+ public void setLatGaode(String latGaode) {
+ this.latGaode = latGaode;
+ }
+
+ public String getWellName() {
+ return wellName;
+ }
+
+ public void setWellName(String wellName) {
+ this.wellName = wellName;
+ }
+
+ public String getTel() {
+ return tel;
+ }
+
+ public void setTel(String tel) {
+ this.tel = tel;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+ }
+}
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 af85fc7..4908afb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt
@@ -26,6 +26,7 @@
* */
const val PERMISSIONS_CODE = 999
const val PAGE_LIMIT = 20
+ const val RADIUS_SIZE = 50 //相距多少米才聚合,单位:米
/**
* =============================================================================================
@@ -40,6 +41,7 @@
* =============================================================================================
* */
const val USER_DETAIL_MODEL = "userDetailModel"
+// const val SERVER_BASE_URL = "http://192.168.43.19:11643"
const val SERVER_BASE_URL = "http://111.198.10.15:11304"
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
const val ACCOUNT = "account"
diff --git a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
index 14e2f56..a2c1338 100644
--- a/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/RSAUtils.kt
@@ -34,17 +34,14 @@
}
fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String {
- val resultBytes =
- processData(srcData, publicKey)
+ val resultBytes = processData(srcData, publicKey)
return Base64.encodeToString(resultBytes, Base64.DEFAULT)
}
fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? {
var publicKey: PublicKey? = null
- val keyBytes =
- Base64.decode(publicKeyStr, Base64.DEFAULT)
- val keySpec =
- X509EncodedKeySpec(keyBytes)
+ val keyBytes = Base64.decode(publicKeyStr, Base64.DEFAULT)
+ val keySpec = X509EncodedKeySpec(keyBytes)
try {
val keyFactory = KeyFactory.getInstance("RSA")
publicKey = keyFactory.generatePublic(keySpec)
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
index 738cc78..83cacb9 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt
@@ -19,7 +19,7 @@
* @param secretKey 加密后的密码
*/
@FormUrlEncoded
- @POST("/user/login")
+ @POST("/user/appLogin")
suspend fun obtainLoginResult(
@Field("sid") sid: String,
@Field("username") account: String,
@@ -71,6 +71,12 @@
suspend fun obtainVersionResult(@Header("token") token: String): String
/**
+ * 地图设备列表
+ */
+ @POST("/tube/well/list")
+ suspend fun obtainMapDeviceList(@Header("token") token: String): String
+
+ /**
* 获取管盯分页列表
* */
@GET("/device/list")
diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
index c51557a..1e04ceb 100644
--- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
+++ b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt
@@ -62,6 +62,13 @@
}
/**
+ * 地图设备列表
+ */
+ suspend fun obtainMapDeviceList(): String {
+ return api.obtainMapDeviceList(AuthenticationHelper.token!!)
+ }
+
+ /**
* 根据设备类型获取设备分页列表
*/
suspend fun obtainDeviceListByType(
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 910c4a9..f10db67 100644
--- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt
+++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt
@@ -23,10 +23,8 @@
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.activity.BigImageActivity
import com.pengxh.kt.lite.adapter.EditableImageAdapter
import com.pengxh.kt.lite.base.KotlinBaseActivity
-import com.pengxh.kt.lite.callback.OnImageCompressListener
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil
import com.pengxh.kt.lite.utils.WeakReferenceHandler
@@ -161,7 +159,7 @@
if (realPaths[position].isEmpty()) {
"图片加载失败,无法查看大图".show(context)
} else {
- navigatePageTo(position, realPaths)
+// navigatePageTo(position, realPaths)
}
}
@@ -298,17 +296,17 @@
// Log.d(kTag, "绝对路径:" + result.realPath)
// Log.d(kTag, "原图路径:" + result.originalPath)
// Log.d(kTag, "沙盒路径:" + result.sandboxPath)
- 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()
- }
- })
+// 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()
+// }
+// })
}
private lateinit var loadingDialog: QMUITipDialog
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 4d0b36f..5b2f97f 100644
--- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt
+++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt
@@ -6,6 +6,7 @@
import com.casic.smarttube.extensions.toErrorMessage
import com.casic.smarttube.model.DeviceHistoryDataModel
import com.casic.smarttube.model.DeviceListModel
+import com.casic.smarttube.model.MapDeviceModel
import com.casic.smarttube.utils.retrofit.RetrofitServiceManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
@@ -16,9 +17,23 @@
class DeviceViewModel : BaseViewModel() {
private val gson = Gson()
- val deviceListModel = MutableLiveData()
+ val mapDeviceModel = MutableLiveData()
val historyDataModel = MutableLiveData()
+ fun obtainMapDeviceList() = launch({
+ val response = RetrofitServiceManager.obtainMapDeviceList()
+ val responseCode = response.separateResponseCode()
+ if (responseCode == 200) {
+ mapDeviceModel.value = gson.fromJson(
+ response, object : TypeToken() {}.type
+ )
+ } else {
+ response.toErrorMessage().show(BaseApplication.obtainInstance())
+ }
+ }, {
+ it.printStackTrace()
+ })
+
fun obtainDeviceListByType(
deptid: String, keywords: String, isOnline: String, page: Int
) = launch({
@@ -26,9 +41,9 @@
RetrofitServiceManager.obtainDeviceListByType(deptid, keywords, isOnline, page)
val responseCode = response.separateResponseCode()
if (responseCode == 200) {
- deviceListModel.value = gson.fromJson(
- response, object : TypeToken() {}.type
- )
+// deviceListModel.value = gson.fromJson(
+// response, object : TypeToken() {}.type
+// )
} else {
response.toErrorMessage().show(BaseApplication.obtainInstance())
}
diff --git a/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt
new file mode 100644
index 0000000..cb14054
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/widgets/GaoDeClusterMarkerView.kt
@@ -0,0 +1,102 @@
+package com.casic.smarttube.widgets
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Point
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.TextView
+import com.amap.api.maps.Projection
+import com.amap.api.maps.model.BitmapDescriptorFactory
+import com.amap.api.maps.model.LatLng
+import com.amap.api.maps.model.LatLngBounds
+import com.amap.api.maps.model.MarkerOptions
+import com.casic.smarttube.R
+import com.pengxh.kt.lite.extensions.toBitmap
+import java.util.*
+
+class GaoDeClusterMarkerView(
+ private val context: Context, firstMarkers: MarkerOptions,
+ projection: Projection, gridSize: Int
+) {
+ //当前可观区域里的 聚合过之后的集合
+ private val includeMarkers: ArrayList
+
+ // 创建区域
+ val bounds: LatLngBounds
+ var options: MarkerOptions = MarkerOptions()
+
+ init {
+ val screenLocation = projection.toScreenLocation(firstMarkers.position)
+ //范围类
+ val southwestPoint = Point(screenLocation.x - gridSize, screenLocation.y + gridSize)
+ //范围类
+ val northeastPoint = Point(screenLocation.x + gridSize, screenLocation.y - gridSize)
+ bounds = LatLngBounds(
+ projection.fromScreenLocation(southwestPoint),
+ projection.fromScreenLocation(northeastPoint)
+ )
+ //设置初始化marker属性
+ options.anchor(0.5f, 1.3f)
+ .title(firstMarkers.title)
+ .position(firstMarkers.position)
+ .icon(firstMarkers.icon)
+ .snippet(firstMarkers.snippet)
+ .draggable(false)
+ includeMarkers = ArrayList()
+ includeMarkers.add(firstMarkers)
+ }
+
+ /**
+ * 添加marker
+ */
+ fun addMarker(markerOptions: MarkerOptions) {
+ includeMarkers.add(markerOptions) // 添加到列表中
+ }
+
+ /**
+ * 设置聚合点的中心位置以及图标
+ */
+ fun setPositionAndIcon() {
+ val size = includeMarkers.size
+ var lat = 0.0
+ var lng = 0.0
+ // 一个的时候
+ if (size == 1) { //设置marker单个属性
+ // 设置marker位置
+ options.position(
+ LatLng(
+ includeMarkers[0].position.latitude,
+ includeMarkers[0].position.longitude
+ )
+ )
+ } else { // 聚合的时候
+ //设置marker聚合属性
+ for (op in includeMarkers) {
+ lat += op.position.latitude
+ lng += op.position.longitude
+ }
+ // 设置marker的位置为中心位置为聚集点的平均位置
+ options.position(LatLng(lat / size, lng / size))
+ }
+ options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap(size)))
+ }
+
+ /**
+ * marker视图
+ */
+ private fun getBitmap(num: Int): Bitmap? {
+ val view = LayoutInflater.from(context).inflate(R.layout.marker_gaode, null)
+ val wellCountView = view.findViewById(R.id.wellCountView)
+ return if (num > 1) {
+ wellCountView.visibility = View.VISIBLE
+ wellCountView.text = String.format("${num}个")
+ wellCountView.gravity = Gravity.CENTER
+ view.toBitmap()
+ } else {
+ wellCountView.visibility = View.GONE
+ BitmapDescriptorFactory.fromResource(R.mipmap.well_location).bitmap
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_solid_layout_main_radius_5.xml b/app/src/main/res/drawable/bg_solid_layout_main_radius_5.xml
new file mode 100644
index 0000000..e329b7d
--- /dev/null
+++ b/app/src/main/res/drawable/bg_solid_layout_main_radius_5.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml
new file mode 100644
index 0000000..15e6a4b
--- /dev/null
+++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/libs/lite-release.aar b/app/libs/lite-release.aar
index d9d51ae..f4b81e1 100644
--- a/app/libs/lite-release.aar
+++ b/app/libs/lite-release.aar
Binary files differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 58bd05b..05d1d6e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
- android:theme="@style/QMUI.Compat.NoActionBar"
+ android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
-
+
+
+
= ArrayList()
+
+ /**
+ * 视野内的marker
+ */
+ private var markerOptionsInView: MutableList = ArrayList()
+
+ /**
+ * 自定义Marker弹出框
+ * */
+ private var infoWindow: View? = null
+
+ /**
+ * 所有设备列表信息集合
+ * */
+ private var deviceModels: MutableList = ArrayList()
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
homeView = inflater.inflate(R.layout.fragment_home, container, false)
@@ -43,6 +78,62 @@
easyPopupWindow.showAsDropDown(homeView.rightOptionView, x, 0)
}
+ //代码设置底部拉升距离
+ val bottomSheetBehavior = BottomSheetBehavior.from(homeView.bottomBehaviorLayout)
+ homeView.coordinatorLayout.post {
+ bottomSheetBehavior.isFitToContents = false
+ bottomSheetBehavior.peekHeight = 30f.dp2px(requireContext())
+ bottomSheetBehavior.isHideable = false
+ }
+
+ //初始化vm
+ deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java)
+
+ //获取所有窨井数据
+ httpCountDownTimer.start()
+ DialogHelper.showLoadingDialog(requireActivity(), "数据加载中,请稍后...")
+ //获取所有设备数据
+ deviceViewModel.obtainMapDeviceList()
+ deviceViewModel.mapDeviceModel.observe(this, {
+ if (it.code == 200) {
+ val latitudeList: MutableList = ArrayList()
+ val longitudeList: MutableList = ArrayList()
+ it.data.forEach { device ->
+ val lat = device.latGaode.toString()
+ val lng = device.lngGaode.toString()
+ if (lat.isNotBlank() && lng.isNotBlank()) {
+ //返回true代表当前位置在大陆、港澳地区,反之不在
+ val latitude = lat.toDouble()
+ val longitude = lng.toDouble()
+ if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) {
+ //缓存所有设备详情,点击Marker时候需要
+ deviceModels.add(device)
+ //分别缓存经、纬度
+ latitudeList.add(latitude)
+ longitudeList.add(longitude)
+ //将所有设备信息转化缓存为Marker点
+ allMarkerOptions.add(
+ MarkerOptions()
+ .position(LatLng(latitude, longitude))
+ .title(device.wellName)
+ .snippet(device.wellCode)
+ )
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度不在国内,异常经纬度 ===> [${lng},${lat}]")
+ }
+ } else {
+ Log.d(kTag, "${device.wellCode}闸井经纬度异常,异常经纬度 ===> [${lng},${lat}]")
+ }
+ }
+ //计算所有点的中心点位置
+ val centerLatLng = LatLng(latitudeList.average(), longitudeList.average())
+ //移动到指定经纬度
+ val cameraPosition = CameraPosition(centerLatLng, 12f, 0f, 0f)
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
+ aMap.animateCamera(cameraUpdate, 1500, null)
+ }
+ })
+
//地图初始化
initMap(savedInstanceState)
@@ -64,13 +155,173 @@
uiSettings.isRotateGesturesEnabled = false//不允许地图旋转
// 地图加载成功监听
-// aMap.addOnMapLoadedListener(this)
+ aMap.addOnMapLoadedListener(this)
// 地图缩放监听
-// aMap.addOnCameraChangeListener(this)
+ aMap.addOnCameraChangeListener(this)
// marker 点击事件监听
-// aMap.addOnMarkerClickListener(this)
+ aMap.addOnMarkerClickListener(this)
// 点击marker弹出自定义popup
-// aMap.setInfoWindowAdapter(this)
+ aMap.setInfoWindowAdapter(this)
+ }
+
+ override fun onMapLoaded() {
+ //地图加载成功之后显示聚合点数据
+ initClustersMarkers()
+ }
+
+ override fun onCameraChange(p0: CameraPosition?) {
+
+ }
+
+ /**
+ * http请求计时器
+ * */
+ private val httpCountDownTimer = object : CountDownTimer(15 * 1000, 1000) {
+ override fun onFinish() {
+ "请求服务器超时,请退出后重试".show(requireContext())
+ DialogHelper.dismissLoadingDialog()
+ }
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+ }
+
+ //获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker
+ override fun onCameraChangeFinish(p0: CameraPosition?) {
+ //地图缩放之后显示聚合点数据
+ DialogHelper.dismissLoadingDialog()
+ httpCountDownTimer.cancel()
+ 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()
+ }
+ aMap.clear()
+ // 重新添加 marker
+ clustersMarkers.forEach {
+ aMap.addMarker(it.options)
+ }
+ }
+
+ override fun onMarkerClick(marker: Marker?): Boolean {
+ //显示闸井信息
+ marker?.showInfoWindow()
+ return true
+ }
+
+ override fun getInfoWindow(marker: Marker?): View? {
+ if (infoWindow == null) {
+ infoWindow = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_info, null)
+ }
+ val v = infoWindow!!
+ //反射得到popup里面的控件对象
+ val wellNameView = v.findViewById(R.id.wellNameView)
+ val wellCodeView = v.findViewById(R.id.wellCodeView)
+ val wellTypeView = v.findViewById(R.id.wellTypeView)
+ val wellStateView = v.findViewById(R.id.wellStateView)
+ val deepView = v.findViewById(R.id.deepView)
+ val locationView = v.findViewById(R.id.locationView)
+
+ //绑定数据
+ val clickedLatLng = marker?.position!!
+ for (device in deviceModels) {
+ if (clickedLatLng.latitude == device.latGaode!!.toDouble()
+ && clickedLatLng.longitude == device.lngGaode!!.toDouble()
+ ) {
+ wellCodeView.text = String.format("闸井编号: ${device.wellCode}")
+ wellNameView.text = String.format("闸井名称: ${device.wellName}")
+ wellTypeView.text = String.format("闸井类型: ${device.wellType}")
+ wellStateView.text = String.format("布/撤防状态: ${device.bfzt}")
+ deepView.text = String.format("闸井深度: ${device.deep}m")
+ locationView.text = String.format("详细位置: ${device.position}")
+ return infoWindow
+ }
+ }
+ "无法查看聚合点,请放大比例后再查看".show(requireContext())
+ return null
+ }
+
+ /**
+ * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框
+ * */
+ override fun getInfoContents(p0: Marker?): View? = null
+
+ override fun onInfoWindowClick(p0: Marker?) {
+ if (p0 != null) {
+ 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()
+ if (lat.isBlank() || lng.isBlank()) {
+ "窨井经纬度异常,无法开启导航".show(requireContext())
+ return
+ }
+ Poi(p0.snippet, LatLng(lat.toDouble(), lng.toDouble()), "").showRouteOnMap(
+ requireContext()
+ )
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
}
/***以下是地图生命周期管理************************************************************************/
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 1618f24..73d1e4c 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt
@@ -139,6 +139,7 @@
DialogHelper.dismissLoadingDialog()
"同步完成".show(requireContext())
userData = it.data
+ updateUserInfo()
}
})
@@ -218,14 +219,14 @@
private fun updateUserInfo() {
//设置头像,圆形,暂时是默认的
- val roundDrawable =
- BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
- .createRoundDrawable(
- requireContext(),
- 3f.dp2px(requireContext()),
- R.color.mainThemeColor.convertColor(requireContext())
- )
- userImageView.setImageDrawable(roundDrawable)
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
userNameView.text = userData.name
userPhoneView.text = String.format("电话:${userData.phone}")
userDeptView.text = String.format("部门:${userData.deptName}")
diff --git a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
index 5b18ed5..d80e8ed 100644
--- a/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
+++ b/app/src/main/java/com/casic/smarttube/fragment/OverviewFragment.kt
@@ -61,31 +61,31 @@
obtainDeviceList()
}
- deviceViewModel.deviceListModel.observe(this, {
- if (it.code == 200) {
- val dataRows = it.data?.rows
- when {
- isRefresh -> {
- dataBeans.clear()
- dataBeans = dataRows!!
- overviewLayout.finishRefresh()
- isRefresh = false
- }
- isLoadMore -> {
- if (dataRows?.size == 0) {
- "到底了,别拉了".show(requireContext())
- }
- dataBeans.addAll(dataRows!!)
- overviewLayout.finishLoadMore()
- isLoadMore = false
- }
- else -> {
- dataBeans = dataRows!!
- }
- }
- weakReferenceHandler.sendEmptyMessage(2022062401)
- }
- })
+// deviceViewModel.deviceListModel.observe(this, {
+// if (it.code == 200) {
+// val dataRows = it.data?.rows
+// when {
+// isRefresh -> {
+// dataBeans.clear()
+// dataBeans = dataRows!!
+// overviewLayout.finishRefresh()
+// isRefresh = false
+// }
+// isLoadMore -> {
+// if (dataRows?.size == 0) {
+// "到底了,别拉了".show(requireContext())
+// }
+// dataBeans.addAll(dataRows!!)
+// overviewLayout.finishLoadMore()
+// isLoadMore = false
+// }
+// else -> {
+// dataBeans = dataRows!!
+// }
+// }
+// weakReferenceHandler.sendEmptyMessage(2022062401)
+// }
+// })
}
private fun obtainDeviceList() {
diff --git a/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
new file mode 100644
index 0000000..7e8a367
--- /dev/null
+++ b/app/src/main/java/com/casic/smarttube/model/MapDeviceModel.java
@@ -0,0 +1,190 @@
+package com.casic.smarttube.model;
+
+import java.util.List;
+
+public class MapDeviceModel {
+
+ private int code;
+ private List data;
+ private String message;
+ private String success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List