diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index fc2ad5d..23d1ac1 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -100,7 +100,7 @@ val textValue = if (type == Type.ALL) { millSeconds.timestampToTime() } else { - millSeconds.timestampToDate() + millSeconds.timestampToCompleteDate() } startDateView.setText(textValue) }.build().show(fragmentManager, "DateSelectDialog") diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index fc2ad5d..23d1ac1 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -100,7 +100,7 @@ val textValue = if (type == Type.ALL) { millSeconds.timestampToTime() } else { - millSeconds.timestampToDate() + millSeconds.timestampToCompleteDate() } startDateView.setText(textValue) }.build().show(fragmentManager, "DateSelectDialog") diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt new file mode 100644 index 0000000..7e3a63e --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -0,0 +1,104 @@ +package com.casic.smarttube.widgets + +import android.app.Activity +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.casic.smarttube.R +import com.casic.smarttube.adapter.DialogDeviceListAdapter +import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.resetParams +import kotlinx.android.synthetic.main.dialog_multi_select.* + +class MultiSelectDialog private constructor(builder: Builder) : Dialog( + builder.activity, R.style.UserDefinedDialogStyle +) { + + private val kTag = "MultiSelectDialog" + private val act: Activity = builder.activity + private val title: String = builder.title + private val dataModels: MutableList = builder.dataModels + private val negativeBtn: String = builder.negativeBtn + private val positiveBtn: String = builder.positiveBtn + private val listener: OnDialogButtonClickListener = builder.listener + + class Builder { + lateinit var activity: Activity + lateinit var title: String + lateinit var dataModels: MutableList + lateinit var negativeBtn: String + lateinit var positiveBtn: String + lateinit var listener: OnDialogButtonClickListener + + fun setContext(activity: Activity): Builder { + this.activity = activity + return this + } + + fun setTitle(title: String): Builder { + this.title = title + return this + } + + fun setDataSource(dataModels: MutableList): Builder { + this.dataModels = dataModels + return this + } + + fun setNegativeButton(name: String): Builder { + this.negativeBtn = name + return this + } + + fun setPositiveButton(name: String): Builder { + this.positiveBtn = name + return this + } + + fun setOnDialogButtonClickListener(listener: OnDialogButtonClickListener): Builder { + this.listener = listener + return this + } + + fun build(): MultiSelectDialog { + return MultiSelectDialog(this) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + setContentView(R.layout.dialog_multi_select) + setCancelable(false) + setCanceledOnTouchOutside(false) + + if (title.isNotBlank()) { + dialogTitleView.text = title + } + + val dialogDeviceListAdapter = DialogDeviceListAdapter(act, dataModels) + dataRecyclerView.addItemDecoration(DividerItemDecoration(act, RecyclerView.VERTICAL)) + dataRecyclerView.adapter = dialogDeviceListAdapter + + dialogCancelButton.text = negativeBtn + dialogCancelButton.setOnClickListener { + listener.onCancelClick() + this.dismiss() + } + + dialogConfirmButton.text = positiveBtn + dialogConfirmButton.setOnClickListener { + // 处理数据 + listener.onConfirmClick(dialogDeviceListAdapter.selectedModels) + this.dismiss() + } + } + + interface OnDialogButtonClickListener { + fun onConfirmClick(selectedModels: MutableList) + + fun onCancelClick() + } +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index fc2ad5d..23d1ac1 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -100,7 +100,7 @@ val textValue = if (type == Type.ALL) { millSeconds.timestampToTime() } else { - millSeconds.timestampToDate() + millSeconds.timestampToCompleteDate() } startDateView.setText(textValue) }.build().show(fragmentManager, "DateSelectDialog") diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt new file mode 100644 index 0000000..7e3a63e --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -0,0 +1,104 @@ +package com.casic.smarttube.widgets + +import android.app.Activity +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.casic.smarttube.R +import com.casic.smarttube.adapter.DialogDeviceListAdapter +import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.resetParams +import kotlinx.android.synthetic.main.dialog_multi_select.* + +class MultiSelectDialog private constructor(builder: Builder) : Dialog( + builder.activity, R.style.UserDefinedDialogStyle +) { + + private val kTag = "MultiSelectDialog" + private val act: Activity = builder.activity + private val title: String = builder.title + private val dataModels: MutableList = builder.dataModels + private val negativeBtn: String = builder.negativeBtn + private val positiveBtn: String = builder.positiveBtn + private val listener: OnDialogButtonClickListener = builder.listener + + class Builder { + lateinit var activity: Activity + lateinit var title: String + lateinit var dataModels: MutableList + lateinit var negativeBtn: String + lateinit var positiveBtn: String + lateinit var listener: OnDialogButtonClickListener + + fun setContext(activity: Activity): Builder { + this.activity = activity + return this + } + + fun setTitle(title: String): Builder { + this.title = title + return this + } + + fun setDataSource(dataModels: MutableList): Builder { + this.dataModels = dataModels + return this + } + + fun setNegativeButton(name: String): Builder { + this.negativeBtn = name + return this + } + + fun setPositiveButton(name: String): Builder { + this.positiveBtn = name + return this + } + + fun setOnDialogButtonClickListener(listener: OnDialogButtonClickListener): Builder { + this.listener = listener + return this + } + + fun build(): MultiSelectDialog { + return MultiSelectDialog(this) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + setContentView(R.layout.dialog_multi_select) + setCancelable(false) + setCanceledOnTouchOutside(false) + + if (title.isNotBlank()) { + dialogTitleView.text = title + } + + val dialogDeviceListAdapter = DialogDeviceListAdapter(act, dataModels) + dataRecyclerView.addItemDecoration(DividerItemDecoration(act, RecyclerView.VERTICAL)) + dataRecyclerView.adapter = dialogDeviceListAdapter + + dialogCancelButton.text = negativeBtn + dialogCancelButton.setOnClickListener { + listener.onCancelClick() + this.dismiss() + } + + dialogConfirmButton.text = positiveBtn + dialogConfirmButton.setOnClickListener { + // 处理数据 + listener.onConfirmClick(dialogDeviceListAdapter.selectedModels) + this.dismiss() + } + } + + interface OnDialogButtonClickListener { + fun onConfirmClick(selectedModels: MutableList) + + fun onCancelClick() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml new file mode 100644 index 0000000..900343f --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index fc2ad5d..23d1ac1 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -100,7 +100,7 @@ val textValue = if (type == Type.ALL) { millSeconds.timestampToTime() } else { - millSeconds.timestampToDate() + millSeconds.timestampToCompleteDate() } startDateView.setText(textValue) }.build().show(fragmentManager, "DateSelectDialog") diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt new file mode 100644 index 0000000..7e3a63e --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -0,0 +1,104 @@ +package com.casic.smarttube.widgets + +import android.app.Activity +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.casic.smarttube.R +import com.casic.smarttube.adapter.DialogDeviceListAdapter +import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.resetParams +import kotlinx.android.synthetic.main.dialog_multi_select.* + +class MultiSelectDialog private constructor(builder: Builder) : Dialog( + builder.activity, R.style.UserDefinedDialogStyle +) { + + private val kTag = "MultiSelectDialog" + private val act: Activity = builder.activity + private val title: String = builder.title + private val dataModels: MutableList = builder.dataModels + private val negativeBtn: String = builder.negativeBtn + private val positiveBtn: String = builder.positiveBtn + private val listener: OnDialogButtonClickListener = builder.listener + + class Builder { + lateinit var activity: Activity + lateinit var title: String + lateinit var dataModels: MutableList + lateinit var negativeBtn: String + lateinit var positiveBtn: String + lateinit var listener: OnDialogButtonClickListener + + fun setContext(activity: Activity): Builder { + this.activity = activity + return this + } + + fun setTitle(title: String): Builder { + this.title = title + return this + } + + fun setDataSource(dataModels: MutableList): Builder { + this.dataModels = dataModels + return this + } + + fun setNegativeButton(name: String): Builder { + this.negativeBtn = name + return this + } + + fun setPositiveButton(name: String): Builder { + this.positiveBtn = name + return this + } + + fun setOnDialogButtonClickListener(listener: OnDialogButtonClickListener): Builder { + this.listener = listener + return this + } + + fun build(): MultiSelectDialog { + return MultiSelectDialog(this) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + setContentView(R.layout.dialog_multi_select) + setCancelable(false) + setCanceledOnTouchOutside(false) + + if (title.isNotBlank()) { + dialogTitleView.text = title + } + + val dialogDeviceListAdapter = DialogDeviceListAdapter(act, dataModels) + dataRecyclerView.addItemDecoration(DividerItemDecoration(act, RecyclerView.VERTICAL)) + dataRecyclerView.adapter = dialogDeviceListAdapter + + dialogCancelButton.text = negativeBtn + dialogCancelButton.setOnClickListener { + listener.onCancelClick() + this.dismiss() + } + + dialogConfirmButton.text = positiveBtn + dialogConfirmButton.setOnClickListener { + // 处理数据 + listener.onConfirmClick(dialogDeviceListAdapter.selectedModels) + this.dismiss() + } + } + + interface OnDialogButtonClickListener { + fun onConfirmClick(selectedModels: MutableList) + + fun onCancelClick() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml new file mode 100644 index 0000000..900343f --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_down.xml b/app/src/main/res/drawable/ic_down.xml deleted file mode 100644 index c6d8b0d..0000000 --- a/app/src/main/res/drawable/ic_down.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index fc2ad5d..23d1ac1 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -100,7 +100,7 @@ val textValue = if (type == Type.ALL) { millSeconds.timestampToTime() } else { - millSeconds.timestampToDate() + millSeconds.timestampToCompleteDate() } startDateView.setText(textValue) }.build().show(fragmentManager, "DateSelectDialog") diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt new file mode 100644 index 0000000..7e3a63e --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -0,0 +1,104 @@ +package com.casic.smarttube.widgets + +import android.app.Activity +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.casic.smarttube.R +import com.casic.smarttube.adapter.DialogDeviceListAdapter +import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.resetParams +import kotlinx.android.synthetic.main.dialog_multi_select.* + +class MultiSelectDialog private constructor(builder: Builder) : Dialog( + builder.activity, R.style.UserDefinedDialogStyle +) { + + private val kTag = "MultiSelectDialog" + private val act: Activity = builder.activity + private val title: String = builder.title + private val dataModels: MutableList = builder.dataModels + private val negativeBtn: String = builder.negativeBtn + private val positiveBtn: String = builder.positiveBtn + private val listener: OnDialogButtonClickListener = builder.listener + + class Builder { + lateinit var activity: Activity + lateinit var title: String + lateinit var dataModels: MutableList + lateinit var negativeBtn: String + lateinit var positiveBtn: String + lateinit var listener: OnDialogButtonClickListener + + fun setContext(activity: Activity): Builder { + this.activity = activity + return this + } + + fun setTitle(title: String): Builder { + this.title = title + return this + } + + fun setDataSource(dataModels: MutableList): Builder { + this.dataModels = dataModels + return this + } + + fun setNegativeButton(name: String): Builder { + this.negativeBtn = name + return this + } + + fun setPositiveButton(name: String): Builder { + this.positiveBtn = name + return this + } + + fun setOnDialogButtonClickListener(listener: OnDialogButtonClickListener): Builder { + this.listener = listener + return this + } + + fun build(): MultiSelectDialog { + return MultiSelectDialog(this) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + setContentView(R.layout.dialog_multi_select) + setCancelable(false) + setCanceledOnTouchOutside(false) + + if (title.isNotBlank()) { + dialogTitleView.text = title + } + + val dialogDeviceListAdapter = DialogDeviceListAdapter(act, dataModels) + dataRecyclerView.addItemDecoration(DividerItemDecoration(act, RecyclerView.VERTICAL)) + dataRecyclerView.adapter = dialogDeviceListAdapter + + dialogCancelButton.text = negativeBtn + dialogCancelButton.setOnClickListener { + listener.onCancelClick() + this.dismiss() + } + + dialogConfirmButton.text = positiveBtn + dialogConfirmButton.setOnClickListener { + // 处理数据 + listener.onConfirmClick(dialogDeviceListAdapter.selectedModels) + this.dismiss() + } + } + + interface OnDialogButtonClickListener { + fun onConfirmClick(selectedModels: MutableList) + + fun onCancelClick() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml new file mode 100644 index 0000000..900343f --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_down.xml b/app/src/main/res/drawable/ic_down.xml deleted file mode 100644 index c6d8b0d..0000000 --- a/app/src/main/res/drawable/ic_down.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml deleted file mode 100644 index 6562ce3..0000000 --- a/app/src/main/res/drawable/ic_info.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index fc2ad5d..23d1ac1 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -100,7 +100,7 @@ val textValue = if (type == Type.ALL) { millSeconds.timestampToTime() } else { - millSeconds.timestampToDate() + millSeconds.timestampToCompleteDate() } startDateView.setText(textValue) }.build().show(fragmentManager, "DateSelectDialog") diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt new file mode 100644 index 0000000..7e3a63e --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -0,0 +1,104 @@ +package com.casic.smarttube.widgets + +import android.app.Activity +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.casic.smarttube.R +import com.casic.smarttube.adapter.DialogDeviceListAdapter +import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.resetParams +import kotlinx.android.synthetic.main.dialog_multi_select.* + +class MultiSelectDialog private constructor(builder: Builder) : Dialog( + builder.activity, R.style.UserDefinedDialogStyle +) { + + private val kTag = "MultiSelectDialog" + private val act: Activity = builder.activity + private val title: String = builder.title + private val dataModels: MutableList = builder.dataModels + private val negativeBtn: String = builder.negativeBtn + private val positiveBtn: String = builder.positiveBtn + private val listener: OnDialogButtonClickListener = builder.listener + + class Builder { + lateinit var activity: Activity + lateinit var title: String + lateinit var dataModels: MutableList + lateinit var negativeBtn: String + lateinit var positiveBtn: String + lateinit var listener: OnDialogButtonClickListener + + fun setContext(activity: Activity): Builder { + this.activity = activity + return this + } + + fun setTitle(title: String): Builder { + this.title = title + return this + } + + fun setDataSource(dataModels: MutableList): Builder { + this.dataModels = dataModels + return this + } + + fun setNegativeButton(name: String): Builder { + this.negativeBtn = name + return this + } + + fun setPositiveButton(name: String): Builder { + this.positiveBtn = name + return this + } + + fun setOnDialogButtonClickListener(listener: OnDialogButtonClickListener): Builder { + this.listener = listener + return this + } + + fun build(): MultiSelectDialog { + return MultiSelectDialog(this) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + setContentView(R.layout.dialog_multi_select) + setCancelable(false) + setCanceledOnTouchOutside(false) + + if (title.isNotBlank()) { + dialogTitleView.text = title + } + + val dialogDeviceListAdapter = DialogDeviceListAdapter(act, dataModels) + dataRecyclerView.addItemDecoration(DividerItemDecoration(act, RecyclerView.VERTICAL)) + dataRecyclerView.adapter = dialogDeviceListAdapter + + dialogCancelButton.text = negativeBtn + dialogCancelButton.setOnClickListener { + listener.onCancelClick() + this.dismiss() + } + + dialogConfirmButton.text = positiveBtn + dialogConfirmButton.setOnClickListener { + // 处理数据 + listener.onConfirmClick(dialogDeviceListAdapter.selectedModels) + this.dismiss() + } + } + + interface OnDialogButtonClickListener { + fun onConfirmClick(selectedModels: MutableList) + + fun onCancelClick() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml new file mode 100644 index 0000000..900343f --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_down.xml b/app/src/main/res/drawable/ic_down.xml deleted file mode 100644 index c6d8b0d..0000000 --- a/app/src/main/res/drawable/ic_down.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml deleted file mode 100644 index 6562ce3..0000000 --- a/app/src/main/res/drawable/ic_info.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/ic_navigation.xml b/app/src/main/res/drawable/ic_navigation.xml new file mode 100644 index 0000000..821528f --- /dev/null +++ b/app/src/main/res/drawable/ic_navigation.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index fc2ad5d..23d1ac1 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -100,7 +100,7 @@ val textValue = if (type == Type.ALL) { millSeconds.timestampToTime() } else { - millSeconds.timestampToDate() + millSeconds.timestampToCompleteDate() } startDateView.setText(textValue) }.build().show(fragmentManager, "DateSelectDialog") diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt new file mode 100644 index 0000000..7e3a63e --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -0,0 +1,104 @@ +package com.casic.smarttube.widgets + +import android.app.Activity +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.casic.smarttube.R +import com.casic.smarttube.adapter.DialogDeviceListAdapter +import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.resetParams +import kotlinx.android.synthetic.main.dialog_multi_select.* + +class MultiSelectDialog private constructor(builder: Builder) : Dialog( + builder.activity, R.style.UserDefinedDialogStyle +) { + + private val kTag = "MultiSelectDialog" + private val act: Activity = builder.activity + private val title: String = builder.title + private val dataModels: MutableList = builder.dataModels + private val negativeBtn: String = builder.negativeBtn + private val positiveBtn: String = builder.positiveBtn + private val listener: OnDialogButtonClickListener = builder.listener + + class Builder { + lateinit var activity: Activity + lateinit var title: String + lateinit var dataModels: MutableList + lateinit var negativeBtn: String + lateinit var positiveBtn: String + lateinit var listener: OnDialogButtonClickListener + + fun setContext(activity: Activity): Builder { + this.activity = activity + return this + } + + fun setTitle(title: String): Builder { + this.title = title + return this + } + + fun setDataSource(dataModels: MutableList): Builder { + this.dataModels = dataModels + return this + } + + fun setNegativeButton(name: String): Builder { + this.negativeBtn = name + return this + } + + fun setPositiveButton(name: String): Builder { + this.positiveBtn = name + return this + } + + fun setOnDialogButtonClickListener(listener: OnDialogButtonClickListener): Builder { + this.listener = listener + return this + } + + fun build(): MultiSelectDialog { + return MultiSelectDialog(this) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + setContentView(R.layout.dialog_multi_select) + setCancelable(false) + setCanceledOnTouchOutside(false) + + if (title.isNotBlank()) { + dialogTitleView.text = title + } + + val dialogDeviceListAdapter = DialogDeviceListAdapter(act, dataModels) + dataRecyclerView.addItemDecoration(DividerItemDecoration(act, RecyclerView.VERTICAL)) + dataRecyclerView.adapter = dialogDeviceListAdapter + + dialogCancelButton.text = negativeBtn + dialogCancelButton.setOnClickListener { + listener.onCancelClick() + this.dismiss() + } + + dialogConfirmButton.text = positiveBtn + dialogConfirmButton.setOnClickListener { + // 处理数据 + listener.onConfirmClick(dialogDeviceListAdapter.selectedModels) + this.dismiss() + } + } + + interface OnDialogButtonClickListener { + fun onConfirmClick(selectedModels: MutableList) + + fun onCancelClick() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml new file mode 100644 index 0000000..900343f --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_down.xml b/app/src/main/res/drawable/ic_down.xml deleted file mode 100644 index c6d8b0d..0000000 --- a/app/src/main/res/drawable/ic_down.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml deleted file mode 100644 index 6562ce3..0000000 --- a/app/src/main/res/drawable/ic_info.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/ic_navigation.xml b/app/src/main/res/drawable/ic_navigation.xml new file mode 100644 index 0000000..821528f --- /dev/null +++ b/app/src/main/res/drawable/ic_navigation.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml deleted file mode 100644 index 5d439e5..0000000 --- a/app/src/main/res/drawable/ic_search_white.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index fc2ad5d..23d1ac1 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -100,7 +100,7 @@ val textValue = if (type == Type.ALL) { millSeconds.timestampToTime() } else { - millSeconds.timestampToDate() + millSeconds.timestampToCompleteDate() } startDateView.setText(textValue) }.build().show(fragmentManager, "DateSelectDialog") diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt new file mode 100644 index 0000000..7e3a63e --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -0,0 +1,104 @@ +package com.casic.smarttube.widgets + +import android.app.Activity +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.casic.smarttube.R +import com.casic.smarttube.adapter.DialogDeviceListAdapter +import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.resetParams +import kotlinx.android.synthetic.main.dialog_multi_select.* + +class MultiSelectDialog private constructor(builder: Builder) : Dialog( + builder.activity, R.style.UserDefinedDialogStyle +) { + + private val kTag = "MultiSelectDialog" + private val act: Activity = builder.activity + private val title: String = builder.title + private val dataModels: MutableList = builder.dataModels + private val negativeBtn: String = builder.negativeBtn + private val positiveBtn: String = builder.positiveBtn + private val listener: OnDialogButtonClickListener = builder.listener + + class Builder { + lateinit var activity: Activity + lateinit var title: String + lateinit var dataModels: MutableList + lateinit var negativeBtn: String + lateinit var positiveBtn: String + lateinit var listener: OnDialogButtonClickListener + + fun setContext(activity: Activity): Builder { + this.activity = activity + return this + } + + fun setTitle(title: String): Builder { + this.title = title + return this + } + + fun setDataSource(dataModels: MutableList): Builder { + this.dataModels = dataModels + return this + } + + fun setNegativeButton(name: String): Builder { + this.negativeBtn = name + return this + } + + fun setPositiveButton(name: String): Builder { + this.positiveBtn = name + return this + } + + fun setOnDialogButtonClickListener(listener: OnDialogButtonClickListener): Builder { + this.listener = listener + return this + } + + fun build(): MultiSelectDialog { + return MultiSelectDialog(this) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + setContentView(R.layout.dialog_multi_select) + setCancelable(false) + setCanceledOnTouchOutside(false) + + if (title.isNotBlank()) { + dialogTitleView.text = title + } + + val dialogDeviceListAdapter = DialogDeviceListAdapter(act, dataModels) + dataRecyclerView.addItemDecoration(DividerItemDecoration(act, RecyclerView.VERTICAL)) + dataRecyclerView.adapter = dialogDeviceListAdapter + + dialogCancelButton.text = negativeBtn + dialogCancelButton.setOnClickListener { + listener.onCancelClick() + this.dismiss() + } + + dialogConfirmButton.text = positiveBtn + dialogConfirmButton.setOnClickListener { + // 处理数据 + listener.onConfirmClick(dialogDeviceListAdapter.selectedModels) + this.dismiss() + } + } + + interface OnDialogButtonClickListener { + fun onConfirmClick(selectedModels: MutableList) + + fun onCancelClick() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml new file mode 100644 index 0000000..900343f --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_down.xml b/app/src/main/res/drawable/ic_down.xml deleted file mode 100644 index c6d8b0d..0000000 --- a/app/src/main/res/drawable/ic_down.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml deleted file mode 100644 index 6562ce3..0000000 --- a/app/src/main/res/drawable/ic_info.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/ic_navigation.xml b/app/src/main/res/drawable/ic_navigation.xml new file mode 100644 index 0000000..821528f --- /dev/null +++ b/app/src/main/res/drawable/ic_navigation.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml deleted file mode 100644 index 5d439e5..0000000 --- a/app/src/main/res/drawable/ic_search_white.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layout/activity_device_detail.xml b/app/src/main/res/layout/activity_device_detail.xml index aec8e67..1af04b7 100644 --- a/app/src/main/res/layout/activity_device_detail.xml +++ b/app/src/main/res/layout/activity_device_detail.xml @@ -7,7 +7,38 @@ android:orientation="vertical" tools:context=".view.DeviceDetailActivity"> - + + + + + + + + + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index fc2ad5d..23d1ac1 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -100,7 +100,7 @@ val textValue = if (type == Type.ALL) { millSeconds.timestampToTime() } else { - millSeconds.timestampToDate() + millSeconds.timestampToCompleteDate() } startDateView.setText(textValue) }.build().show(fragmentManager, "DateSelectDialog") diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt new file mode 100644 index 0000000..7e3a63e --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -0,0 +1,104 @@ +package com.casic.smarttube.widgets + +import android.app.Activity +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.casic.smarttube.R +import com.casic.smarttube.adapter.DialogDeviceListAdapter +import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.resetParams +import kotlinx.android.synthetic.main.dialog_multi_select.* + +class MultiSelectDialog private constructor(builder: Builder) : Dialog( + builder.activity, R.style.UserDefinedDialogStyle +) { + + private val kTag = "MultiSelectDialog" + private val act: Activity = builder.activity + private val title: String = builder.title + private val dataModels: MutableList = builder.dataModels + private val negativeBtn: String = builder.negativeBtn + private val positiveBtn: String = builder.positiveBtn + private val listener: OnDialogButtonClickListener = builder.listener + + class Builder { + lateinit var activity: Activity + lateinit var title: String + lateinit var dataModels: MutableList + lateinit var negativeBtn: String + lateinit var positiveBtn: String + lateinit var listener: OnDialogButtonClickListener + + fun setContext(activity: Activity): Builder { + this.activity = activity + return this + } + + fun setTitle(title: String): Builder { + this.title = title + return this + } + + fun setDataSource(dataModels: MutableList): Builder { + this.dataModels = dataModels + return this + } + + fun setNegativeButton(name: String): Builder { + this.negativeBtn = name + return this + } + + fun setPositiveButton(name: String): Builder { + this.positiveBtn = name + return this + } + + fun setOnDialogButtonClickListener(listener: OnDialogButtonClickListener): Builder { + this.listener = listener + return this + } + + fun build(): MultiSelectDialog { + return MultiSelectDialog(this) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + setContentView(R.layout.dialog_multi_select) + setCancelable(false) + setCanceledOnTouchOutside(false) + + if (title.isNotBlank()) { + dialogTitleView.text = title + } + + val dialogDeviceListAdapter = DialogDeviceListAdapter(act, dataModels) + dataRecyclerView.addItemDecoration(DividerItemDecoration(act, RecyclerView.VERTICAL)) + dataRecyclerView.adapter = dialogDeviceListAdapter + + dialogCancelButton.text = negativeBtn + dialogCancelButton.setOnClickListener { + listener.onCancelClick() + this.dismiss() + } + + dialogConfirmButton.text = positiveBtn + dialogConfirmButton.setOnClickListener { + // 处理数据 + listener.onConfirmClick(dialogDeviceListAdapter.selectedModels) + this.dismiss() + } + } + + interface OnDialogButtonClickListener { + fun onConfirmClick(selectedModels: MutableList) + + fun onCancelClick() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml new file mode 100644 index 0000000..900343f --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_down.xml b/app/src/main/res/drawable/ic_down.xml deleted file mode 100644 index c6d8b0d..0000000 --- a/app/src/main/res/drawable/ic_down.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml deleted file mode 100644 index 6562ce3..0000000 --- a/app/src/main/res/drawable/ic_info.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/ic_navigation.xml b/app/src/main/res/drawable/ic_navigation.xml new file mode 100644 index 0000000..821528f --- /dev/null +++ b/app/src/main/res/drawable/ic_navigation.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml deleted file mode 100644 index 5d439e5..0000000 --- a/app/src/main/res/drawable/ic_search_white.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layout/activity_device_detail.xml b/app/src/main/res/layout/activity_device_detail.xml index aec8e67..1af04b7 100644 --- a/app/src/main/res/layout/activity_device_detail.xml +++ b/app/src/main/res/layout/activity_device_detail.xml @@ -7,7 +7,38 @@ android:orientation="vertical" tools:context=".view.DeviceDetailActivity"> - + + + + + + + + + android:paddingHorizontal="@dimen/dp_10" + android:src="@drawable/ic_left_white" /> + android:paddingHorizontal="@dimen/dp_10" + android:src="@drawable/ic_change_map" /> diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index fc2ad5d..23d1ac1 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -100,7 +100,7 @@ val textValue = if (type == Type.ALL) { millSeconds.timestampToTime() } else { - millSeconds.timestampToDate() + millSeconds.timestampToCompleteDate() } startDateView.setText(textValue) }.build().show(fragmentManager, "DateSelectDialog") diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt new file mode 100644 index 0000000..7e3a63e --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -0,0 +1,104 @@ +package com.casic.smarttube.widgets + +import android.app.Activity +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.casic.smarttube.R +import com.casic.smarttube.adapter.DialogDeviceListAdapter +import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.resetParams +import kotlinx.android.synthetic.main.dialog_multi_select.* + +class MultiSelectDialog private constructor(builder: Builder) : Dialog( + builder.activity, R.style.UserDefinedDialogStyle +) { + + private val kTag = "MultiSelectDialog" + private val act: Activity = builder.activity + private val title: String = builder.title + private val dataModels: MutableList = builder.dataModels + private val negativeBtn: String = builder.negativeBtn + private val positiveBtn: String = builder.positiveBtn + private val listener: OnDialogButtonClickListener = builder.listener + + class Builder { + lateinit var activity: Activity + lateinit var title: String + lateinit var dataModels: MutableList + lateinit var negativeBtn: String + lateinit var positiveBtn: String + lateinit var listener: OnDialogButtonClickListener + + fun setContext(activity: Activity): Builder { + this.activity = activity + return this + } + + fun setTitle(title: String): Builder { + this.title = title + return this + } + + fun setDataSource(dataModels: MutableList): Builder { + this.dataModels = dataModels + return this + } + + fun setNegativeButton(name: String): Builder { + this.negativeBtn = name + return this + } + + fun setPositiveButton(name: String): Builder { + this.positiveBtn = name + return this + } + + fun setOnDialogButtonClickListener(listener: OnDialogButtonClickListener): Builder { + this.listener = listener + return this + } + + fun build(): MultiSelectDialog { + return MultiSelectDialog(this) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + setContentView(R.layout.dialog_multi_select) + setCancelable(false) + setCanceledOnTouchOutside(false) + + if (title.isNotBlank()) { + dialogTitleView.text = title + } + + val dialogDeviceListAdapter = DialogDeviceListAdapter(act, dataModels) + dataRecyclerView.addItemDecoration(DividerItemDecoration(act, RecyclerView.VERTICAL)) + dataRecyclerView.adapter = dialogDeviceListAdapter + + dialogCancelButton.text = negativeBtn + dialogCancelButton.setOnClickListener { + listener.onCancelClick() + this.dismiss() + } + + dialogConfirmButton.text = positiveBtn + dialogConfirmButton.setOnClickListener { + // 处理数据 + listener.onConfirmClick(dialogDeviceListAdapter.selectedModels) + this.dismiss() + } + } + + interface OnDialogButtonClickListener { + fun onConfirmClick(selectedModels: MutableList) + + fun onCancelClick() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml new file mode 100644 index 0000000..900343f --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_down.xml b/app/src/main/res/drawable/ic_down.xml deleted file mode 100644 index c6d8b0d..0000000 --- a/app/src/main/res/drawable/ic_down.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml deleted file mode 100644 index 6562ce3..0000000 --- a/app/src/main/res/drawable/ic_info.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/ic_navigation.xml b/app/src/main/res/drawable/ic_navigation.xml new file mode 100644 index 0000000..821528f --- /dev/null +++ b/app/src/main/res/drawable/ic_navigation.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml deleted file mode 100644 index 5d439e5..0000000 --- a/app/src/main/res/drawable/ic_search_white.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layout/activity_device_detail.xml b/app/src/main/res/layout/activity_device_detail.xml index aec8e67..1af04b7 100644 --- a/app/src/main/res/layout/activity_device_detail.xml +++ b/app/src/main/res/layout/activity_device_detail.xml @@ -7,7 +7,38 @@ android:orientation="vertical" tools:context=".view.DeviceDetailActivity"> - + + + + + + + + + android:paddingHorizontal="@dimen/dp_10" + android:src="@drawable/ic_left_white" /> + android:paddingHorizontal="@dimen/dp_10" + android:src="@drawable/ic_change_map" /> diff --git a/app/src/main/res/layout/activity_map_device_brief.xml b/app/src/main/res/layout/activity_map_device_brief.xml new file mode 100644 index 0000000..f37e8aa --- /dev/null +++ b/app/src/main/res/layout/activity_map_device_brief.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 0313bd0..376b32b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,5 +106,4 @@ implementation 'com.jzxiang.pickerview:TimePickerDialog:1.0.1' //ZBar(综合Java和C++扫码),生成二维码 implementation 'cn.bertsir.zbarLibary:zbarlibary:1.4.2' - implementation 'com.github.goyourfly:MultiSelectAdapter:3.8' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e447cfa..06ee725 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ + +) : RecyclerView.Adapter() { + + private val layoutInflater: LayoutInflater = LayoutInflater.from(context) + var selectedModels = ArrayList() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder(layoutInflater.inflate(R.layout.item_dialog_rv, parent, false)) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.deviceCodeView.text = rowsBean.devcode + holder.deviceCodeView.setOnClickListener { + holder.deviceCodeView.toggle() + if (holder.deviceCodeView.isChecked) { + selectedModels.add(rowsBean) + } else { + selectedModels.remove(rowsBean) + } + } + } + + class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var deviceCodeView: AppCompatCheckedTextView = view.findViewById(R.id.deviceCodeView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt index 33786db..f549c63 100644 --- a/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt +++ b/app/src/main/java/com/casic/smarttube/extensions/ArrayList.kt @@ -17,12 +17,4 @@ } } return builder.toString() -} - -fun addAll(vararg args: String): ArrayList { - val result = ArrayList() - args.forEach { - result.add(it) - } - return result } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt b/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt deleted file mode 100644 index d185752..0000000 --- a/app/src/main/java/com/casic/smarttube/extensions/ImageView.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.casic.smarttube.extensions - -import android.view.animation.LinearInterpolator -import android.widget.ImageView - -fun ImageView.arrowAnimation(angle: Float) { - val animation = this.animate() - animation.duration = 300 - animation.interpolator = LinearInterpolator() - animation.rotation(angle) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index ccea467..981d706 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -1,5 +1,6 @@ package com.casic.smarttube.fragment +import android.graphics.Color import android.graphics.Point import android.os.Bundle import android.os.Handler @@ -31,6 +32,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.view.AddDeviceActivity +import com.casic.smarttube.view.MapDeviceBriefActivity import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.GaoDeClusterMarkerView @@ -43,6 +45,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import kotlinx.android.synthetic.main.activity_group_device.* import kotlinx.android.synthetic.main.fragment_home.view.* @@ -58,6 +61,7 @@ private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var groupListAdapter: GroupListAdapter + private lateinit var multiDevice: ArrayList private var dataBeans: MutableList = ArrayList() private var isRefresh = false @@ -138,6 +142,9 @@ } val latitudeList: MutableList = ArrayList() val longitudeList: MutableList = ArrayList() + if (deviceModels.size != 0) { + deviceModels.clear() + } it.data.forEach { device -> val lat = device.latGaode.toString() val lng = device.lngGaode.toString() @@ -365,6 +372,7 @@ val updateTimeView = v.findViewById(R.id.updateTimeView) val locationView = v.findViewById(R.id.locationView) + multiDevice = ArrayList() //绑定数据 val clickedLatLng = marker?.position!! for (device in deviceModels) { @@ -407,16 +415,28 @@ } }) } - //TODO 动态设置Popup宽度 -// val rootView = v.findViewById(R.id.rootView) -// val layoutParams = rootView.layoutParams -// layoutParams.width = (requireContext().obtainScreenWidth() * 0.8).toInt() -// rootView.layoutParams = layoutParams -// rootView.requestLayout() return infoView } } - "无法查看聚合点,请放大比例后再查看".show(requireContext()) + deviceModels.forEach { + multiDevice.add(it.devcode) + } + //查看聚合点,单独开页面导航过去 + BottomActionSheet.Builder() + .setContext(requireContext()) + .setActionItemTitle(multiDevice) + .setItemTextColor(Color.BLUE) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + deviceModels.forEach { + if (it.devcode == multiDevice[position]) { + requireContext().navigatePageTo( + arrayListOf(it.groupId, it.devcode, it.modelName) + ) + } + } + } + }).build().show() return null } 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 e006361..4f7ac0d 100644 --- a/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smarttube/utils/LocaleConstant.kt @@ -18,8 +18,10 @@ ) val POPUP_IMAGES = intArrayOf(R.drawable.ic_menu_map, R.drawable.ic_satellite) val POPUP_TITLES = arrayOf("标准地图", "卫星地图") - val DEVICE_OPERATE_IMAGES = intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white) - val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除") + + val DEVICE_OPERATE_IMAGES = + intArrayOf(R.drawable.ic_order, R.drawable.ic_delete_white, R.drawable.ic_delete_white) + val DEVICE_OPERATE_TITLES = arrayOf("浓度排序", "全部删除", "批量删除") /** * ============================================================================================= diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index 9065615..f6deb9d 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -4,6 +4,7 @@ import android.util.Log import android.view.View import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.model.LatLng import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch @@ -11,7 +12,9 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter @@ -23,12 +26,12 @@ import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil import com.pengxh.kt.lite.vm.LoadState import kotlinx.android.synthetic.main.activity_device_detail.* -import kotlinx.android.synthetic.main.include_base_title.* class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" private lateinit var deviceViewModel: DeviceViewModel + private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } override fun initLayoutView(): Int = R.layout.activity_device_detail @@ -48,6 +51,7 @@ deviceViewModel.deviceDetailModel.observe(this, { if (it.code == 200) { val device = it.data + this.deviceModel = device deviceCodeView.text = device.devcode deviceNameView.text = device.deviceName projectGroupView.text = String.format("项目${device.groupId}") @@ -125,6 +129,14 @@ } override fun initEvent() { - + rightOptionView.setOnClickListener { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(this) + return@setOnClickListener + } + RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index 845b57b..6b641a6 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -14,6 +14,7 @@ import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel +import com.casic.smarttube.widgets.MultiSelectDialog import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.convertColor @@ -99,7 +100,33 @@ } }).build().show() } - //TODO 批量删除待完善 + 2 -> { + //TODO 批量删除待完善 + MultiSelectDialog.Builder() + .setContext(this@GroupDeviceActivity) + .setTitle("选择设备") + .setDataSource(dataBeans) + .setNegativeButton("取消") + .setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }) + .build().show() + } } } }) diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt new file mode 100644 index 0000000..bf8d310 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -0,0 +1,162 @@ +package com.casic.smarttube.view + +import android.os.Bundle +import androidx.lifecycle.ViewModelProvider +import com.amap.api.maps.AMap +import com.amap.api.maps.AMapOptions +import com.amap.api.maps.CameraUpdateFactory +import com.amap.api.maps.model.* +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.smarttube.R +import com.casic.smarttube.utils.LoadingDialogHub +import com.casic.smarttube.utils.RouteOnMap +import com.casic.smarttube.vm.DeviceViewModel +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.utils.Constant +import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.vm.LoadState +import kotlinx.android.synthetic.main.activity_map_device_brief.* +import kotlinx.android.synthetic.main.include_base_title.* + +class MapDeviceBriefActivity : KotlinBaseActivity() { + + private val kTag = "MapDeviceBriefActivity" + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private val geocoderSearch by lazy { GeocodeSearch(this) } + + + override fun initLayoutView(): Int = R.layout.activity_map_device_brief + + override fun setupTopBarLayout() { + ImmersionBar.with(this).statusBarDarkFont(false).init() + ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + titleView.text = "设备最新数据地图展示" + leftBackView.setOnClickListener { finish() } + } + + override fun initData() { + aMap = mapView.map + aMap.mapType = AMap.MAP_TYPE_NORMAL + val uiSettings = aMap.uiSettings + uiSettings.isCompassEnabled = true + uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 + uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 + + val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + + deviceViewModel = ViewModelProvider(this).get(DeviceViewModel::class.java) + deviceViewModel.obtainDeviceDetail(params[0], params[1]) + deviceViewModel.deviceDetailModel.observe(this, { + if (it.code == 200) { + val device = it.data + + deviceCodeView.text = String.format("设备编号: ${device.devcode}") + deviceModelView.text = String.format("设备模型: ${params[2]}") + + //获取设备最新浓度信息 + deviceViewModel.obtainTubeLastData(device.groupId, device.devcode) + deviceViewModel.lastDataModel.observe(this, { v -> + if (v.code == 200) { + deviceValueView.text = String.format("最新浓度: ${v.data.strength}") + updateTimeView.text = String.format("更新时间: ${v.data.uptime}") + } else { + deviceValueView.text = String.format("最新浓度: 未知") + updateTimeView.text = String.format("更新时间: 未知") + } + }) + if (device.latGaode.isBlank() || device.lngGaode.isBlank()) { + locationView.text = "经纬度异常,无法查看具体位置" + } else { + val queryParam = RegeocodeQuery( + LatLonPoint(device.latGaode.toDouble(), device.lngGaode.toDouble()), + 200f, + GeocodeSearch.AMAP + ) + val latLng = LatLng(device.latGaode.toDouble(), device.lngGaode.toDouble()) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) { + if (rCode == 1000) { + locationView.text = + String.format("详细位置: ${result?.regeocodeAddress?.formatAddress}") + } + } + + override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) { + + } + }) + + val cameraPosition = CameraPosition(latLng, 18f, 0f, 0f) + val newCameraPosition = CameraUpdateFactory.newCameraPosition(cameraPosition) + aMap.animateCamera(newCameraPosition, 1500, object : AMap.CancelableCallback { + override fun onFinish() { + //添加Marker + val markerOptions = MarkerOptions() + .position(latLng) + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.well_location)) + .draggable(false) + aMap.addMarker(markerOptions) + } + + override fun onCancel() { + + } + }) + aMap.setOnMarkerClickListener { + RouteOnMap.startNavigation( + this@MapDeviceBriefActivity, "", latLng + ) + true + } + } + } + }) + + deviceViewModel.loadState.observe(this, { + when (it) { + LoadState.Loading -> LoadingDialogHub.show(this, "数据加载中...") + else -> LoadingDialogHub.dismiss() + } + }) + } + + override fun initEvent() { + + } + + /**地图相关*********/ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onDestroy() { + mapView.onDestroy() + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index fc2ad5d..23d1ac1 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -100,7 +100,7 @@ val textValue = if (type == Type.ALL) { millSeconds.timestampToTime() } else { - millSeconds.timestampToDate() + millSeconds.timestampToCompleteDate() } startDateView.setText(textValue) }.build().show(fragmentManager, "DateSelectDialog") diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt new file mode 100644 index 0000000..7e3a63e --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -0,0 +1,104 @@ +package com.casic.smarttube.widgets + +import android.app.Activity +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.casic.smarttube.R +import com.casic.smarttube.adapter.DialogDeviceListAdapter +import com.casic.smarttube.model.DeviceListModel +import com.pengxh.kt.lite.extensions.resetParams +import kotlinx.android.synthetic.main.dialog_multi_select.* + +class MultiSelectDialog private constructor(builder: Builder) : Dialog( + builder.activity, R.style.UserDefinedDialogStyle +) { + + private val kTag = "MultiSelectDialog" + private val act: Activity = builder.activity + private val title: String = builder.title + private val dataModels: MutableList = builder.dataModels + private val negativeBtn: String = builder.negativeBtn + private val positiveBtn: String = builder.positiveBtn + private val listener: OnDialogButtonClickListener = builder.listener + + class Builder { + lateinit var activity: Activity + lateinit var title: String + lateinit var dataModels: MutableList + lateinit var negativeBtn: String + lateinit var positiveBtn: String + lateinit var listener: OnDialogButtonClickListener + + fun setContext(activity: Activity): Builder { + this.activity = activity + return this + } + + fun setTitle(title: String): Builder { + this.title = title + return this + } + + fun setDataSource(dataModels: MutableList): Builder { + this.dataModels = dataModels + return this + } + + fun setNegativeButton(name: String): Builder { + this.negativeBtn = name + return this + } + + fun setPositiveButton(name: String): Builder { + this.positiveBtn = name + return this + } + + fun setOnDialogButtonClickListener(listener: OnDialogButtonClickListener): Builder { + this.listener = listener + return this + } + + fun build(): MultiSelectDialog { + return MultiSelectDialog(this) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + setContentView(R.layout.dialog_multi_select) + setCancelable(false) + setCanceledOnTouchOutside(false) + + if (title.isNotBlank()) { + dialogTitleView.text = title + } + + val dialogDeviceListAdapter = DialogDeviceListAdapter(act, dataModels) + dataRecyclerView.addItemDecoration(DividerItemDecoration(act, RecyclerView.VERTICAL)) + dataRecyclerView.adapter = dialogDeviceListAdapter + + dialogCancelButton.text = negativeBtn + dialogCancelButton.setOnClickListener { + listener.onCancelClick() + this.dismiss() + } + + dialogConfirmButton.text = positiveBtn + dialogConfirmButton.setOnClickListener { + // 处理数据 + listener.onConfirmClick(dialogDeviceListAdapter.selectedModels) + this.dismiss() + } + } + + interface OnDialogButtonClickListener { + fun onConfirmClick(selectedModels: MutableList) + + fun onCancelClick() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml new file mode 100644 index 0000000..900343f --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_main_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_down.xml b/app/src/main/res/drawable/ic_down.xml deleted file mode 100644 index c6d8b0d..0000000 --- a/app/src/main/res/drawable/ic_down.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml deleted file mode 100644 index 6562ce3..0000000 --- a/app/src/main/res/drawable/ic_info.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/ic_navigation.xml b/app/src/main/res/drawable/ic_navigation.xml new file mode 100644 index 0000000..821528f --- /dev/null +++ b/app/src/main/res/drawable/ic_navigation.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml deleted file mode 100644 index 5d439e5..0000000 --- a/app/src/main/res/drawable/ic_search_white.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layout/activity_device_detail.xml b/app/src/main/res/layout/activity_device_detail.xml index aec8e67..1af04b7 100644 --- a/app/src/main/res/layout/activity_device_detail.xml +++ b/app/src/main/res/layout/activity_device_detail.xml @@ -7,7 +7,38 @@ android:orientation="vertical" tools:context=".view.DeviceDetailActivity"> - + + + + + + + + + android:paddingHorizontal="@dimen/dp_10" + android:src="@drawable/ic_left_white" /> + android:paddingHorizontal="@dimen/dp_10" + android:src="@drawable/ic_change_map" /> diff --git a/app/src/main/res/layout/activity_map_device_brief.xml b/app/src/main/res/layout/activity_map_device_brief.xml new file mode 100644 index 0000000..f37e8aa --- /dev/null +++ b/app/src/main/res/layout/activity_map_device_brief.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_permssion.xml b/app/src/main/res/layout/activity_permssion.xml index 40866ab..beba9ba 100644 --- a/app/src/main/res/layout/activity_permssion.xml +++ b/app/src/main/res/layout/activity_permssion.xml @@ -1,203 +1,208 @@ - + android:layout_height="wrap_content"> - - - - - - - - - - - - - - - - + android:layout_height="match_parent" + android:background="@color/white" + android:orientation="vertical"> + android:layout_marginVertical="@dimen/dp_40" + android:gravity="center"> - + + + android:layout_marginStart="@dimen/dp_5" + android:orientation="vertical"> - + + + + - - - - + android:paddingHorizontal="@dimen/dp_50" + android:text="为了提供及时有效的提供相关业务服务,本应用需向您申请以下权限:" + android:textColor="@color/mainTextColor" + android:textSize="@dimen/sp_16" /> + android:layout_marginTop="@dimen/dp_20" + android:gravity="center" + android:paddingHorizontal="@dimen/dp_50"> - + android:layout_marginEnd="@dimen/dp_10" + android:src="@drawable/ic_storage" /> - + android:orientation="vertical"> + + + + + - - - - - + android:layout_marginTop="@dimen/dp_20" + android:gravity="center" + android:paddingHorizontal="@dimen/dp_50"> - + android:layout_marginEnd="@dimen/dp_10" + android:src="@drawable/ic_camera" /> - + android:orientation="vertical"> + + + + + - - - - - + android:layout_marginTop="@dimen/dp_20" + android:gravity="center" + android:paddingHorizontal="@dimen/dp_50"> - + android:layout_marginEnd="@dimen/dp_10" + android:src="@drawable/ic_location" /> - + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + +