diff --git a/app/build.gradle b/app/build.gradle index 86ec1a2..b2284e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,17 +1,19 @@ +import java.text.SimpleDateFormat + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'org.greenrobot.greendao' android { -// signingConfigs { -// release { -// storeFile file('/Users/a203/Desktop/AndroidProjects/CasicSmartWell/app/CasicSmartWell.jks') -// storePassword '123456789' -// keyAlias 'key0' -// keyPassword '123456789' -// } -// } + signingConfigs { + release { + storeFile file('/Users/a203/Desktop/AndroidProjects/Sanxi/SmartTown/app/SmartTown.jks') + storePassword '123456789' + keyAlias 'key0' + keyPassword '123456789' + } + } compileSdkVersion 31 buildToolsVersion "30.0.3" @@ -28,7 +30,7 @@ buildTypes { release { minifyEnabled false -// signingConfig signingConfigs.release + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a", "arm64-v8a" } @@ -54,6 +56,17 @@ targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录 daoPackage 'com.casic.smart.town.sanxi.greendao'//设置DaoMaster、DaoSession、Dao包名 } + + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = getBuildDate() + "_" + defaultConfig.versionName + ".apk" + } + } +} + +static def getBuildDate() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHMM", Locale.CHINA) + return dateFormat.format(System.currentTimeMillis()) } dependencies { diff --git a/app/build.gradle b/app/build.gradle index 86ec1a2..b2284e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,17 +1,19 @@ +import java.text.SimpleDateFormat + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'org.greenrobot.greendao' android { -// signingConfigs { -// release { -// storeFile file('/Users/a203/Desktop/AndroidProjects/CasicSmartWell/app/CasicSmartWell.jks') -// storePassword '123456789' -// keyAlias 'key0' -// keyPassword '123456789' -// } -// } + signingConfigs { + release { + storeFile file('/Users/a203/Desktop/AndroidProjects/Sanxi/SmartTown/app/SmartTown.jks') + storePassword '123456789' + keyAlias 'key0' + keyPassword '123456789' + } + } compileSdkVersion 31 buildToolsVersion "30.0.3" @@ -28,7 +30,7 @@ buildTypes { release { minifyEnabled false -// signingConfig signingConfigs.release + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a", "arm64-v8a" } @@ -54,6 +56,17 @@ targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录 daoPackage 'com.casic.smart.town.sanxi.greendao'//设置DaoMaster、DaoSession、Dao包名 } + + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = getBuildDate() + "_" + defaultConfig.versionName + ".apk" + } + } +} + +static def getBuildDate() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHMM", Locale.CHINA) + return dateFormat.format(System.currentTimeMillis()) } dependencies { diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt index b1972c2..93548fc 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt @@ -30,4 +30,25 @@ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER ) as String return "$defaultValue/static/${this}" +} + +//窨井类型转换 +fun String.valueToType(): String { + return when (this) { + "" -> "全部" + "1" -> "雨水井" + "2" -> "污水井" + "3" -> "燃气井" + "4" -> "热力井" + "5" -> "电力井" + "6" -> "交通井" + "7" -> "路灯井" + "8" -> "通信井" + "9" -> "监控井" + "10" -> "给水井" + "11" -> "其他" + else -> { + "未知类型" + } + } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 86ec1a2..b2284e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,17 +1,19 @@ +import java.text.SimpleDateFormat + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'org.greenrobot.greendao' android { -// signingConfigs { -// release { -// storeFile file('/Users/a203/Desktop/AndroidProjects/CasicSmartWell/app/CasicSmartWell.jks') -// storePassword '123456789' -// keyAlias 'key0' -// keyPassword '123456789' -// } -// } + signingConfigs { + release { + storeFile file('/Users/a203/Desktop/AndroidProjects/Sanxi/SmartTown/app/SmartTown.jks') + storePassword '123456789' + keyAlias 'key0' + keyPassword '123456789' + } + } compileSdkVersion 31 buildToolsVersion "30.0.3" @@ -28,7 +30,7 @@ buildTypes { release { minifyEnabled false -// signingConfig signingConfigs.release + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a", "arm64-v8a" } @@ -54,6 +56,17 @@ targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录 daoPackage 'com.casic.smart.town.sanxi.greendao'//设置DaoMaster、DaoSession、Dao包名 } + + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = getBuildDate() + "_" + defaultConfig.versionName + ".apk" + } + } +} + +static def getBuildDate() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHMM", Locale.CHINA) + return dateFormat.format(System.currentTimeMillis()) } dependencies { diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt index b1972c2..93548fc 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt @@ -30,4 +30,25 @@ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER ) as String return "$defaultValue/static/${this}" +} + +//窨井类型转换 +fun String.valueToType(): String { + return when (this) { + "" -> "全部" + "1" -> "雨水井" + "2" -> "污水井" + "3" -> "燃气井" + "4" -> "热力井" + "5" -> "电力井" + "6" -> "交通井" + "7" -> "路灯井" + "8" -> "通信井" + "9" -> "监控井" + "10" -> "给水井" + "11" -> "其他" + else -> { + "未知类型" + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt index 950b107..3d7c91c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class AllWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_all_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "闸井分布" + titleView.text = "点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -73,30 +80,24 @@ if (lat.isNotBlank() && lng.isNotBlank()) { val latitude = lat.toDouble() val longitude = lng.toDouble() - - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + //缓存所有井详情,点击Marker时候需要 + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) } - //缓存所有井详情,点击Marker时候需要 - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -108,7 +109,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -118,6 +119,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -150,6 +155,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/build.gradle b/app/build.gradle index 86ec1a2..b2284e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,17 +1,19 @@ +import java.text.SimpleDateFormat + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'org.greenrobot.greendao' android { -// signingConfigs { -// release { -// storeFile file('/Users/a203/Desktop/AndroidProjects/CasicSmartWell/app/CasicSmartWell.jks') -// storePassword '123456789' -// keyAlias 'key0' -// keyPassword '123456789' -// } -// } + signingConfigs { + release { + storeFile file('/Users/a203/Desktop/AndroidProjects/Sanxi/SmartTown/app/SmartTown.jks') + storePassword '123456789' + keyAlias 'key0' + keyPassword '123456789' + } + } compileSdkVersion 31 buildToolsVersion "30.0.3" @@ -28,7 +30,7 @@ buildTypes { release { minifyEnabled false -// signingConfig signingConfigs.release + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a", "arm64-v8a" } @@ -54,6 +56,17 @@ targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录 daoPackage 'com.casic.smart.town.sanxi.greendao'//设置DaoMaster、DaoSession、Dao包名 } + + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = getBuildDate() + "_" + defaultConfig.versionName + ".apk" + } + } +} + +static def getBuildDate() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHMM", Locale.CHINA) + return dateFormat.format(System.currentTimeMillis()) } dependencies { diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt index b1972c2..93548fc 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt @@ -30,4 +30,25 @@ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER ) as String return "$defaultValue/static/${this}" +} + +//窨井类型转换 +fun String.valueToType(): String { + return when (this) { + "" -> "全部" + "1" -> "雨水井" + "2" -> "污水井" + "3" -> "燃气井" + "4" -> "热力井" + "5" -> "电力井" + "6" -> "交通井" + "7" -> "路灯井" + "8" -> "通信井" + "9" -> "监控井" + "10" -> "给水井" + "11" -> "其他" + else -> { + "未知类型" + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt index 950b107..3d7c91c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class AllWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_all_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "闸井分布" + titleView.text = "点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -73,30 +80,24 @@ if (lat.isNotBlank() && lng.isNotBlank()) { val latitude = lat.toDouble() val longitude = lng.toDouble() - - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + //缓存所有井详情,点击Marker时候需要 + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) } - //缓存所有井详情,点击Marker时候需要 - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -108,7 +109,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -118,6 +119,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -150,6 +155,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt index 35e8c0d..8084e2c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class BFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_bf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已布防闸井分布" + titleView.text = "已布防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -74,30 +81,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "1") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -110,7 +113,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -120,6 +123,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -152,6 +159,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/build.gradle b/app/build.gradle index 86ec1a2..b2284e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,17 +1,19 @@ +import java.text.SimpleDateFormat + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'org.greenrobot.greendao' android { -// signingConfigs { -// release { -// storeFile file('/Users/a203/Desktop/AndroidProjects/CasicSmartWell/app/CasicSmartWell.jks') -// storePassword '123456789' -// keyAlias 'key0' -// keyPassword '123456789' -// } -// } + signingConfigs { + release { + storeFile file('/Users/a203/Desktop/AndroidProjects/Sanxi/SmartTown/app/SmartTown.jks') + storePassword '123456789' + keyAlias 'key0' + keyPassword '123456789' + } + } compileSdkVersion 31 buildToolsVersion "30.0.3" @@ -28,7 +30,7 @@ buildTypes { release { minifyEnabled false -// signingConfig signingConfigs.release + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a", "arm64-v8a" } @@ -54,6 +56,17 @@ targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录 daoPackage 'com.casic.smart.town.sanxi.greendao'//设置DaoMaster、DaoSession、Dao包名 } + + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = getBuildDate() + "_" + defaultConfig.versionName + ".apk" + } + } +} + +static def getBuildDate() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHMM", Locale.CHINA) + return dateFormat.format(System.currentTimeMillis()) } dependencies { diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt index b1972c2..93548fc 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt @@ -30,4 +30,25 @@ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER ) as String return "$defaultValue/static/${this}" +} + +//窨井类型转换 +fun String.valueToType(): String { + return when (this) { + "" -> "全部" + "1" -> "雨水井" + "2" -> "污水井" + "3" -> "燃气井" + "4" -> "热力井" + "5" -> "电力井" + "6" -> "交通井" + "7" -> "路灯井" + "8" -> "通信井" + "9" -> "监控井" + "10" -> "给水井" + "11" -> "其他" + else -> { + "未知类型" + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt index 950b107..3d7c91c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class AllWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_all_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "闸井分布" + titleView.text = "点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -73,30 +80,24 @@ if (lat.isNotBlank() && lng.isNotBlank()) { val latitude = lat.toDouble() val longitude = lng.toDouble() - - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + //缓存所有井详情,点击Marker时候需要 + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) } - //缓存所有井详情,点击Marker时候需要 - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -108,7 +109,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -118,6 +119,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -150,6 +155,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt index 35e8c0d..8084e2c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class BFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_bf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已布防闸井分布" + titleView.text = "已布防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -74,30 +81,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "1") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -110,7 +113,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -120,6 +123,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -152,6 +159,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt index c34e35e..1924ed1 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -24,7 +26,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class CFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -44,13 +46,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_cf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已撤防闸井分布" + titleView.text = "已撤防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -75,30 +82,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "0") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -111,7 +114,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -121,6 +124,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -153,6 +160,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/build.gradle b/app/build.gradle index 86ec1a2..b2284e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,17 +1,19 @@ +import java.text.SimpleDateFormat + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'org.greenrobot.greendao' android { -// signingConfigs { -// release { -// storeFile file('/Users/a203/Desktop/AndroidProjects/CasicSmartWell/app/CasicSmartWell.jks') -// storePassword '123456789' -// keyAlias 'key0' -// keyPassword '123456789' -// } -// } + signingConfigs { + release { + storeFile file('/Users/a203/Desktop/AndroidProjects/Sanxi/SmartTown/app/SmartTown.jks') + storePassword '123456789' + keyAlias 'key0' + keyPassword '123456789' + } + } compileSdkVersion 31 buildToolsVersion "30.0.3" @@ -28,7 +30,7 @@ buildTypes { release { minifyEnabled false -// signingConfig signingConfigs.release + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a", "arm64-v8a" } @@ -54,6 +56,17 @@ targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录 daoPackage 'com.casic.smart.town.sanxi.greendao'//设置DaoMaster、DaoSession、Dao包名 } + + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = getBuildDate() + "_" + defaultConfig.versionName + ".apk" + } + } +} + +static def getBuildDate() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHMM", Locale.CHINA) + return dateFormat.format(System.currentTimeMillis()) } dependencies { diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt index b1972c2..93548fc 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt @@ -30,4 +30,25 @@ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER ) as String return "$defaultValue/static/${this}" +} + +//窨井类型转换 +fun String.valueToType(): String { + return when (this) { + "" -> "全部" + "1" -> "雨水井" + "2" -> "污水井" + "3" -> "燃气井" + "4" -> "热力井" + "5" -> "电力井" + "6" -> "交通井" + "7" -> "路灯井" + "8" -> "通信井" + "9" -> "监控井" + "10" -> "给水井" + "11" -> "其他" + else -> { + "未知类型" + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt index 950b107..3d7c91c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class AllWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_all_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "闸井分布" + titleView.text = "点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -73,30 +80,24 @@ if (lat.isNotBlank() && lng.isNotBlank()) { val latitude = lat.toDouble() val longitude = lng.toDouble() - - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + //缓存所有井详情,点击Marker时候需要 + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) } - //缓存所有井详情,点击Marker时候需要 - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -108,7 +109,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -118,6 +119,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -150,6 +155,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt index 35e8c0d..8084e2c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class BFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_bf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已布防闸井分布" + titleView.text = "已布防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -74,30 +81,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "1") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -110,7 +113,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -120,6 +123,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -152,6 +159,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt index c34e35e..1924ed1 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -24,7 +26,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class CFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -44,13 +46,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_cf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已撤防闸井分布" + titleView.text = "已撤防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -75,30 +82,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "0") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -111,7 +114,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -121,6 +124,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -153,6 +160,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..15e6a4b --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 86ec1a2..b2284e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,17 +1,19 @@ +import java.text.SimpleDateFormat + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'org.greenrobot.greendao' android { -// signingConfigs { -// release { -// storeFile file('/Users/a203/Desktop/AndroidProjects/CasicSmartWell/app/CasicSmartWell.jks') -// storePassword '123456789' -// keyAlias 'key0' -// keyPassword '123456789' -// } -// } + signingConfigs { + release { + storeFile file('/Users/a203/Desktop/AndroidProjects/Sanxi/SmartTown/app/SmartTown.jks') + storePassword '123456789' + keyAlias 'key0' + keyPassword '123456789' + } + } compileSdkVersion 31 buildToolsVersion "30.0.3" @@ -28,7 +30,7 @@ buildTypes { release { minifyEnabled false -// signingConfig signingConfigs.release + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a", "arm64-v8a" } @@ -54,6 +56,17 @@ targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录 daoPackage 'com.casic.smart.town.sanxi.greendao'//设置DaoMaster、DaoSession、Dao包名 } + + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = getBuildDate() + "_" + defaultConfig.versionName + ".apk" + } + } +} + +static def getBuildDate() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHMM", Locale.CHINA) + return dateFormat.format(System.currentTimeMillis()) } dependencies { diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt index b1972c2..93548fc 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt @@ -30,4 +30,25 @@ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER ) as String return "$defaultValue/static/${this}" +} + +//窨井类型转换 +fun String.valueToType(): String { + return when (this) { + "" -> "全部" + "1" -> "雨水井" + "2" -> "污水井" + "3" -> "燃气井" + "4" -> "热力井" + "5" -> "电力井" + "6" -> "交通井" + "7" -> "路灯井" + "8" -> "通信井" + "9" -> "监控井" + "10" -> "给水井" + "11" -> "其他" + else -> { + "未知类型" + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt index 950b107..3d7c91c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class AllWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_all_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "闸井分布" + titleView.text = "点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -73,30 +80,24 @@ if (lat.isNotBlank() && lng.isNotBlank()) { val latitude = lat.toDouble() val longitude = lng.toDouble() - - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + //缓存所有井详情,点击Marker时候需要 + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) } - //缓存所有井详情,点击Marker时候需要 - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -108,7 +109,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -118,6 +119,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -150,6 +155,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt index 35e8c0d..8084e2c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class BFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_bf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已布防闸井分布" + titleView.text = "已布防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -74,30 +81,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "1") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -110,7 +113,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -120,6 +123,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -152,6 +159,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt index c34e35e..1924ed1 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -24,7 +26,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class CFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -44,13 +46,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_cf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已撤防闸井分布" + titleView.text = "已撤防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -75,30 +82,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "0") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -111,7 +114,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -121,6 +124,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -153,6 +160,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..15e6a4b --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_map_info.xml b/app/src/main/res/layout/popu_map_info.xml new file mode 100644 index 0000000..bd6b147 --- /dev/null +++ b/app/src/main/res/layout/popu_map_info.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 86ec1a2..b2284e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,17 +1,19 @@ +import java.text.SimpleDateFormat + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'org.greenrobot.greendao' android { -// signingConfigs { -// release { -// storeFile file('/Users/a203/Desktop/AndroidProjects/CasicSmartWell/app/CasicSmartWell.jks') -// storePassword '123456789' -// keyAlias 'key0' -// keyPassword '123456789' -// } -// } + signingConfigs { + release { + storeFile file('/Users/a203/Desktop/AndroidProjects/Sanxi/SmartTown/app/SmartTown.jks') + storePassword '123456789' + keyAlias 'key0' + keyPassword '123456789' + } + } compileSdkVersion 31 buildToolsVersion "30.0.3" @@ -28,7 +30,7 @@ buildTypes { release { minifyEnabled false -// signingConfig signingConfigs.release + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a", "arm64-v8a" } @@ -54,6 +56,17 @@ targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录 daoPackage 'com.casic.smart.town.sanxi.greendao'//设置DaoMaster、DaoSession、Dao包名 } + + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = getBuildDate() + "_" + defaultConfig.versionName + ".apk" + } + } +} + +static def getBuildDate() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHMM", Locale.CHINA) + return dateFormat.format(System.currentTimeMillis()) } dependencies { diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt index b1972c2..93548fc 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt @@ -30,4 +30,25 @@ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER ) as String return "$defaultValue/static/${this}" +} + +//窨井类型转换 +fun String.valueToType(): String { + return when (this) { + "" -> "全部" + "1" -> "雨水井" + "2" -> "污水井" + "3" -> "燃气井" + "4" -> "热力井" + "5" -> "电力井" + "6" -> "交通井" + "7" -> "路灯井" + "8" -> "通信井" + "9" -> "监控井" + "10" -> "给水井" + "11" -> "其他" + else -> { + "未知类型" + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt index 950b107..3d7c91c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class AllWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_all_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "闸井分布" + titleView.text = "点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -73,30 +80,24 @@ if (lat.isNotBlank() && lng.isNotBlank()) { val latitude = lat.toDouble() val longitude = lng.toDouble() - - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + //缓存所有井详情,点击Marker时候需要 + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) } - //缓存所有井详情,点击Marker时候需要 - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -108,7 +109,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -118,6 +119,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -150,6 +155,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt index 35e8c0d..8084e2c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class BFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_bf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已布防闸井分布" + titleView.text = "已布防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -74,30 +81,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "1") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -110,7 +113,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -120,6 +123,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -152,6 +159,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt index c34e35e..1924ed1 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -24,7 +26,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class CFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -44,13 +46,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_cf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已撤防闸井分布" + titleView.text = "已撤防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -75,30 +82,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "0") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -111,7 +114,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -121,6 +124,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -153,6 +160,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..15e6a4b --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_map_info.xml b/app/src/main/res/layout/popu_map_info.xml new file mode 100644 index 0000000..bd6b147 --- /dev/null +++ b/app/src/main/res/layout/popu_map_info.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index e1fe112..3b0b4a2 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -27,4 +27,6 @@ #CCFF66 #37D4AE #feb5a2 + + #99000000 \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 86ec1a2..b2284e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,17 +1,19 @@ +import java.text.SimpleDateFormat + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'org.greenrobot.greendao' android { -// signingConfigs { -// release { -// storeFile file('/Users/a203/Desktop/AndroidProjects/CasicSmartWell/app/CasicSmartWell.jks') -// storePassword '123456789' -// keyAlias 'key0' -// keyPassword '123456789' -// } -// } + signingConfigs { + release { + storeFile file('/Users/a203/Desktop/AndroidProjects/Sanxi/SmartTown/app/SmartTown.jks') + storePassword '123456789' + keyAlias 'key0' + keyPassword '123456789' + } + } compileSdkVersion 31 buildToolsVersion "30.0.3" @@ -28,7 +30,7 @@ buildTypes { release { minifyEnabled false -// signingConfig signingConfigs.release + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a", "arm64-v8a" } @@ -54,6 +56,17 @@ targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录 daoPackage 'com.casic.smart.town.sanxi.greendao'//设置DaoMaster、DaoSession、Dao包名 } + + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = getBuildDate() + "_" + defaultConfig.versionName + ".apk" + } + } +} + +static def getBuildDate() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHMM", Locale.CHINA) + return dateFormat.format(System.currentTimeMillis()) } dependencies { diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt index b1972c2..93548fc 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt @@ -30,4 +30,25 @@ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER ) as String return "$defaultValue/static/${this}" +} + +//窨井类型转换 +fun String.valueToType(): String { + return when (this) { + "" -> "全部" + "1" -> "雨水井" + "2" -> "污水井" + "3" -> "燃气井" + "4" -> "热力井" + "5" -> "电力井" + "6" -> "交通井" + "7" -> "路灯井" + "8" -> "通信井" + "9" -> "监控井" + "10" -> "给水井" + "11" -> "其他" + else -> { + "未知类型" + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt index 950b107..3d7c91c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class AllWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_all_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "闸井分布" + titleView.text = "点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -73,30 +80,24 @@ if (lat.isNotBlank() && lng.isNotBlank()) { val latitude = lat.toDouble() val longitude = lng.toDouble() - - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + //缓存所有井详情,点击Marker时候需要 + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) } - //缓存所有井详情,点击Marker时候需要 - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -108,7 +109,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -118,6 +119,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -150,6 +155,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt index 35e8c0d..8084e2c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class BFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_bf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已布防闸井分布" + titleView.text = "已布防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -74,30 +81,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "1") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -110,7 +113,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -120,6 +123,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -152,6 +159,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt index c34e35e..1924ed1 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -24,7 +26,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class CFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -44,13 +46,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_cf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已撤防闸井分布" + titleView.text = "已撤防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -75,30 +82,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "0") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -111,7 +114,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -121,6 +124,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -153,6 +160,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..15e6a4b --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_map_info.xml b/app/src/main/res/layout/popu_map_info.xml new file mode 100644 index 0000000..bd6b147 --- /dev/null +++ b/app/src/main/res/layout/popu_map_info.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index e1fe112..3b0b4a2 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -27,4 +27,6 @@ #CCFF66 #37D4AE #feb5a2 + + #99000000 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 045c479..84ccbb1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,7 @@ SmartTown 中国航天科工集团 + 未知 runtimelite,1000,rud4449636536,none,NKMFA0PL4S0DRJE15166 AAPK93b60c1b1b064409aafaa03bc5bd3df1eM4wAH7Cxp9rfcD_AEmUqjuk3p2nq-P_tAiHCRh-iyuLIBqeDiKD0urjkJd42iCh \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 86ec1a2..b2284e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,17 +1,19 @@ +import java.text.SimpleDateFormat + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'org.greenrobot.greendao' android { -// signingConfigs { -// release { -// storeFile file('/Users/a203/Desktop/AndroidProjects/CasicSmartWell/app/CasicSmartWell.jks') -// storePassword '123456789' -// keyAlias 'key0' -// keyPassword '123456789' -// } -// } + signingConfigs { + release { + storeFile file('/Users/a203/Desktop/AndroidProjects/Sanxi/SmartTown/app/SmartTown.jks') + storePassword '123456789' + keyAlias 'key0' + keyPassword '123456789' + } + } compileSdkVersion 31 buildToolsVersion "30.0.3" @@ -28,7 +30,7 @@ buildTypes { release { minifyEnabled false -// signingConfig signingConfigs.release + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a", "arm64-v8a" } @@ -54,6 +56,17 @@ targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录 daoPackage 'com.casic.smart.town.sanxi.greendao'//设置DaoMaster、DaoSession、Dao包名 } + + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = getBuildDate() + "_" + defaultConfig.versionName + ".apk" + } + } +} + +static def getBuildDate() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHMM", Locale.CHINA) + return dateFormat.format(System.currentTimeMillis()) } dependencies { diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt index b1972c2..93548fc 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt @@ -30,4 +30,25 @@ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER ) as String return "$defaultValue/static/${this}" +} + +//窨井类型转换 +fun String.valueToType(): String { + return when (this) { + "" -> "全部" + "1" -> "雨水井" + "2" -> "污水井" + "3" -> "燃气井" + "4" -> "热力井" + "5" -> "电力井" + "6" -> "交通井" + "7" -> "路灯井" + "8" -> "通信井" + "9" -> "监控井" + "10" -> "给水井" + "11" -> "其他" + else -> { + "未知类型" + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt index 950b107..3d7c91c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/AllWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class AllWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_all_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "闸井分布" + titleView.text = "点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -73,30 +80,24 @@ if (lat.isNotBlank() && lng.isNotBlank()) { val latitude = lat.toDouble() val longitude = lng.toDouble() - - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + //缓存所有井详情,点击Marker时候需要 + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) } - //缓存所有井详情,点击Marker时候需要 - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - - //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -108,7 +109,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -118,6 +119,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -150,6 +155,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt index 35e8c0d..8084e2c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/BFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -23,7 +25,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class BFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -43,13 +45,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_bf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已布防闸井分布" + titleView.text = "已布防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -74,30 +81,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "1") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -110,7 +113,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -120,6 +123,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -152,6 +159,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt index c34e35e..1924ed1 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/view/CFWellActivity.kt @@ -2,16 +2,18 @@ import android.graphics.Point import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.BitmapDescriptorFactory -import com.amap.api.maps.model.CameraPosition -import com.amap.api.maps.model.LatLng -import com.amap.api.maps.model.MarkerOptions +import com.amap.api.maps.CoordinateConverter +import com.amap.api.maps.model.* import com.casic.smart.town.sanxi.R +import com.casic.smart.town.sanxi.extensions.valueToType import com.casic.smart.town.sanxi.model.WellListModel import com.casic.smart.town.sanxi.util.LoadingDialogHub import com.casic.smart.town.sanxi.vm.WellViewModel @@ -24,7 +26,7 @@ import kotlinx.android.synthetic.main.include_base_title.* class CFWellActivity : AppCompatActivity(), AMap.OnMapLoadedListener, - AMap.OnCameraChangeListener { + AMap.OnCameraChangeListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter { private lateinit var wellViewModel: WellViewModel private lateinit var aMap: AMap @@ -44,13 +46,18 @@ * */ private var wellInfoModels: MutableList = ArrayList() + /** + * 自定义Marker弹出框 + * */ + private var infoWindow: View? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_cf_well) ImmersionBar.with(this).statusBarDarkFont(false).init() ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - titleView.text = "已撤防闸井分布" + titleView.text = "已撤防点位分布" leftBackView.setOnClickListener { finish() } setMapConfig(savedInstanceState) @@ -75,30 +82,26 @@ val latitude = lat.toDouble() val longitude = lng.toDouble() - //有的数据经纬度是反的 - val latLng = if (latitude > longitude) { - LatLng(longitude, latitude) - } else { - LatLng(latitude, longitude) - } - //缓存所有井详情,点击Marker时候需要 if (wellInfo.bfzt == "0") { - wellInfoModels.add(wellInfo) - //分别缓存经、纬度 - latitudeList.add(latitude) - longitudeList.add(longitude) - //将所有设备信息转化缓存为Marker点 - allMarkerOptions.add( - MarkerOptions() - .position(latLng) - .title(wellInfo.wellTypeName) - .snippet(wellInfo.wellCode) - ) - + if (CoordinateConverter.isAMapDataAvailable(latitude, longitude)) { + wellInfoModels.add(wellInfo) + //分别缓存经、纬度 + latitudeList.add(latitude) + longitudeList.add(longitude) + //将所有设备信息转化缓存为Marker点 + allMarkerOptions.add( + MarkerOptions() + .position(LatLng(latitude, longitude)) + .title(wellInfo.wellTypeName) + .snippet(wellInfo.wellCode) + ) + } //移动到指定经纬度 - val cameraPosition = CameraPosition(latLng, 15f, 0f, 0f) + val centerLatLng = + LatLng(latitudeList.average(), longitudeList.average()) + val cameraPosition = CameraPosition(centerLatLng, 17f, 0f, 0f) val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 2000, null) } @@ -111,7 +114,7 @@ private fun setMapConfig(savedInstanceState: Bundle?) { mapView.onCreate(savedInstanceState) aMap = mapView.map - aMap.mapType = AMap.MAP_TYPE_NORMAL + aMap.mapType = AMap.MAP_TYPE_SATELLITE val uiSettings = aMap.uiSettings uiSettings.isCompassEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER @@ -121,6 +124,10 @@ aMap.addOnMapLoadedListener(this) // 地图缩放监听 aMap.addOnCameraChangeListener(this) + // marker 点击事件监听 + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) } override fun onMapLoaded() { @@ -153,6 +160,52 @@ } } + override fun onMarkerClick(marker: Marker?): Boolean { + //显示闸井信息 + marker?.showInfoWindow() + return true + } + + override fun getInfoWindow(marker: Marker?): View? { + if (infoWindow == null) { + infoWindow = LayoutInflater.from(this).inflate(R.layout.popu_map_info, null) + } + val v = infoWindow!! + //反射得到popup里面的控件对象 + val wellNameView = v.findViewById(R.id.wellNameView) + val wellCodeView = v.findViewById(R.id.wellCodeView) + val wellTypeView = v.findViewById(R.id.wellTypeView) + val wellStateView = v.findViewById(R.id.wellStateView) + val deepView = v.findViewById(R.id.deepView) + val locationView = v.findViewById(R.id.locationView) + + //绑定数据 + val clickedLatLng = marker?.position!! + + for (well in wellInfoModels) { + if (clickedLatLng.latitude == well.latGaode!!.toDouble() && clickedLatLng.longitude == well.lngGaode!!.toDouble() + ) { + wellNameView.text = String.format("点位名称: ${well.wellName}") + wellCodeView.text = String.format("点位编号: ${well.wellCode}") + wellTypeView.text = String.format("点位类型: ${well.wellType.valueToType()}") + val bfztName = if (well.bfzt == "1") { + "已布防" + } else { + "已撤防" + } + wellStateView.text = String.format("布/撤防状态: $bfztName") + deepView.text = String.format("点位深度: ${well.deep}m") + locationView.text = String.format("详细位置: ${well.position}") + } + } + return null + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + /***以下是地图生命周期管理************************************************************************/ override fun onResume() { super.onResume() diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..15e6a4b --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_map_info.xml b/app/src/main/res/layout/popu_map_info.xml new file mode 100644 index 0000000..bd6b147 --- /dev/null +++ b/app/src/main/res/layout/popu_map_info.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index e1fe112..3b0b4a2 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -27,4 +27,6 @@ #CCFF66 #37D4AE #feb5a2 + + #99000000 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 045c479..84ccbb1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,7 @@ SmartTown 中国航天科工集团 + 未知 runtimelite,1000,rud4449636536,none,NKMFA0PL4S0DRJE15166 AAPK93b60c1b1b064409aafaa03bc5bd3df1eM4wAH7Cxp9rfcD_AEmUqjuk3p2nq-P_tAiHCRh-iyuLIBqeDiKD0urjkJd42iCh \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 99b48d7..d9db17b 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -110,4 +110,13 @@ @dimen/dp_5 true + + \ No newline at end of file