Commit 30cfa78e authored by 马乐's avatar 马乐

1.修改UI层次结构

2.使用Hilt管理层级UI生命周期
parent ac412a6a
......@@ -6,11 +6,9 @@ import com.blankj.utilcode.util.SPStaticUtils
import com.blankj.utilcode.util.SPUtils
import com.blankj.utilcode.util.Utils
import dagger.hilt.android.HiltAndroidApp
import kotlin.properties.Delegates
@HiltAndroidApp
class AntiCollisionApp: Application(){
override fun onCreate() {
super.onCreate()
Utils.init(this)
......@@ -18,9 +16,4 @@ class AntiCollisionApp: Application(){
SPStaticUtils.setDefaultSPUtils(SPUtils.getInstance("settings"))
}
companion object {
//情况一:声明可空的属性
private var instance: AntiCollisionApp by Delegates.notNull()
fun instance() = instance
}
}
\ No newline at end of file
......@@ -2,22 +2,14 @@ package com.waytous.anticollision
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.viewModels
import com.blankj.utilcode.util.BarUtils
import com.blankj.utilcode.util.ColorUtils
import com.waytous.anticollision.databinding.ActivitySplashBinding
import com.waytous.anticollision.repository.MainRepository
import com.waytous.anticollision.ui.MainActivity
import com.waytous.anticollision.ui.MainViewModel
class SplashActivity : AppCompatActivity() {
private val mapModel: MainViewModel by viewModels{
MainViewModel.MainViewModelFactory(MainRepository(this))
}
private lateinit var binding:ActivitySplashBinding
override fun onCreate(savedInstanceState: Bundle?) {
......
package com.waytous.anticollision.api
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import com.waytous.anticollision.BuildConfig
import com.waytous.anticollision.bean.MapDataSource
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
interface MapSourceService {
/**
* 获取障碍物图层数据
* @param version
* */
@GET("api/map/obstaclesversion")
suspend fun obstaclesVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取电子围栏图层数据
* @param version
* */
@GET("api/map/electronicFenceversion")
suspend fun electronicFenceVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取湿滑区域图层数据
* @param version
* */
@GET("api/map/wetAreaversion")
suspend fun wetAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取车道节点图层数据
* @param version
* */
@GET("api/map/lanenodeversion")
suspend fun laneNodeVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取车道图层数据
* @param version
* */
@GET("api/map/laneversion")
suspend fun laneVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取可行使区域图层数据
* @param version
* */
@GET("api/map/runableareaversion")
suspend fun runnableAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取卸载区图层数据
* @param version
* */
@GET("api/map/dumpareaversion")
suspend fun dumpAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取装载区图层数据
* @param version
* */
@GET("api/map/diggingworkareaversion")
suspend fun diggingWorkAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取挡墙图层数据
* @param version
* */
@GET("api/map/barricadeversion")
suspend fun barricadeVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取静态区域图层数据
* @param version
* */
@GET("api/map/stationareaversion")
suspend fun stationAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取静态区域图层数据
* @param version
* */
@GET("api/map/staticobjsversion")
suspend fun staticObjectsVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取停车位图层数据
* @param version
* */
@GET("api/map/parkspotversion")
suspend fun parkSpotVersion(@Query("version") version:String = "-1"): MapDataSource?
companion object {
private val BASE_URL by lazy {
if (BuildConfig.DEBUG) BuildConfig.TEST_MAP_SOURCE_HOST else BuildConfig.DEV_MAP_SOURCE_HOST
}
private val moshi: Moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
fun create(): MapSourceService {
val logger = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC }
val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
.create(MapSourceService::class.java)
}
}
}
\ No newline at end of file
......@@ -24,5 +24,5 @@ data class MapDataSource(
/**地图geojson数据版本*/
@ColumnInfo(name = "version")
@Json(name = "version")
val version: Int = -1
val version: String = "-1"
)
\ No newline at end of file
package com.waytous.anticollision.bean
data class MapDataSourceWrapper(val mapDataSource: MapDataSource?, val abort:Boolean)
\ No newline at end of file
package com.waytous.anticollision.config
import com.blankj.utilcode.util.DeviceUtils
import com.waytous.anticollision.utils.PreferenceDelegate
import com.blankj.utilcode.util.SPUtils
import io.github.toggery.jt808.messagebody.B0100
/**
......@@ -12,27 +12,27 @@ object DeviceConfig {
/**
* 省份ID
* */
var province: Int by PreferenceDelegate("province", 11)
var province: Int = SPUtils.getInstance().getInt("province", 11)
/**
* 城市ID
* */
var city: Int by PreferenceDelegate("city", 0)
var city: Int = SPUtils.getInstance().getInt("city", 0)
/**
* 车牌颜色
* */
var plateColor: Int by PreferenceDelegate("plateColor", B0100.PLATE_COLOR_YELLOW)
var plateColor: Int = SPUtils.getInstance().getInt("plateColor", B0100.PLATE_COLOR_YELLOW)
/**
* 设备制造商
* */
var maker: String by PreferenceDelegate("maker", DeviceUtils.getManufacturer())
var maker: String = SPUtils.getInstance().getString("maker", DeviceUtils.getManufacturer())
/**
* 手机号码
* */
var phoneNumber: String by PreferenceDelegate("phone", "")
var phoneNumber: String = SPUtils.getInstance().getString("phone", "")
......@@ -40,11 +40,11 @@ object DeviceConfig {
/**
* 服务器地址
* */
var host: String by PreferenceDelegate("host", "")
var host: String = SPUtils.getInstance().getString("host", "")
/**
* 服务器端口
* */
var port: Int by PreferenceDelegate("port", 0)
var port: Int = SPUtils.getInstance().getInt("port", 0)
}
}
\ No newline at end of file
package com.waytous.anticollision.config
import com.waytous.anticollision.utils.PreferenceDelegate
import com.blankj.utilcode.util.SPUtils
/**
* 设置
......@@ -22,73 +22,73 @@ object Settings {
/**
* 设备唯一识别码
* */
var deviceId: String by PreferenceDelegate("deviceId", "")
var deviceId: String = SPUtils.getInstance().getString("deviceId", "")
/**
* 是否已注册
* */
var isRegistered: Boolean by PreferenceDelegate("isRegistered", false)
var isRegistered: Boolean = SPUtils.getInstance().getBoolean("isRegistered", false)
/**
* 设备注册鉴权码
* */
var token: String by PreferenceDelegate("token", "")
var token: String = SPUtils.getInstance().getString("token", "")
/**
* DWORD 终端心跳发送间隔,单位为秒(s),默认2分钟
* */
var x0001:Long by PreferenceDelegate("x0001", 120)
var x0001:Long = SPUtils.getInstance().getLong("x0001", 120)
/**
* DWORD 消息应答超时时间,单位为秒(s)
* */
var x0002:Long by PreferenceDelegate("x0002", 60)
var x0002:Long = SPUtils.getInstance().getLong("x0002", 60)
/**
* DWORD TCP 消息重传次数
* */
var x0003:Long by PreferenceDelegate("x0003", 3)
var x0003:Long = SPUtils.getInstance().getLong("x0003", 3)
/**
* STRING 主服务器 APN,无线通信拨号访问点,若网络制式为 CDMA,则该处为 PPP 拨号号码
* */
var x0010:String by PreferenceDelegate("x0010", "")
var x0010:String = SPUtils.getInstance().getString("x0010", "")
/**
* STRING 主服务器无线通信拨号用户名
* */
var x0011:String by PreferenceDelegate("x0011", "")
var x0011:String = SPUtils.getInstance().getString("x0011", "")
/**
* STRING 主服务器无线通信拨号密码
* */
var x0012:String by PreferenceDelegate("x0012", "")
var x0012:String = SPUtils.getInstance().getString("x0012", "")
/**
* STRING 主服务器地址,IP 或域名(2019 版以冒号分割主机和端口,多个服务器使用分号分隔)
* */
var x0013:String by PreferenceDelegate("x0013", "")
var x0013:String = SPUtils.getInstance().getString("x0013", "")
/**
* STRING 备份服务器 APN,无线通信拨号访问点
* */
var x0014:String by PreferenceDelegate("x0014", "")
var x0014:String = SPUtils.getInstance().getString("x0014", "")
/**
* STRING 备份服务器无线通信拨号用户名
* */
var x0015:String by PreferenceDelegate("x0015", "")
var x0015:String = SPUtils.getInstance().getString("x0015", "")
/**
* STRING 备份服务器无线通信拨号密码
* */
var x0016:String by PreferenceDelegate("x0016", "")
var x0016:String = SPUtils.getInstance().getString("x0016", "")
/**
* STRING 备份服务器地址、IP 或域名(2019 版以冒号分割主机和端口,多个服务器使用分号分隔)
* */
var x0017:String by PreferenceDelegate("x0017", "")
var x0017:String = SPUtils.getInstance().getString("x0017", "")
/**
* DWORD 服务器 TCP 端口 // 2019 del
* */
var x0018:Long by PreferenceDelegate("x0018", -1)
var x0018:Long = SPUtils.getInstance().getLong("x0018", -1)
/**
* STRING 道路运输证 IC 卡认证主服务器 IP 地址或域名
* */
var x001A:String by PreferenceDelegate("x001A", "")
var x001A:String = SPUtils.getInstance().getString("x001A", "")
/**
* DWORD 道路运输证 IC 卡认证主服务器 TCP 端口
* */
var x001B:Long by PreferenceDelegate("x001B", -1)
var x001B:Long = SPUtils.getInstance().getLong("x001B", -1)
}
\ No newline at end of file
/*
* Copyright (c) 2021 Razeware LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
* distribute, sublicense, create a derivative work, and/or sell copies of the
* Software in any work that is designed, intended, or marketed for pedagogical or
* instructional purposes related to programming, coding, application development,
* or information technology. Permission for such use, copying, modification,
* merger, publication, distribution, sublicensing, creation of derivative works,
* or sale is expressly withheld.
*
* This project and source code may use libraries or frameworks that are
* released under various Open-Source licenses. Use of those libraries and
* frameworks are governed by their own individual licenses.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.waytous.anticollision.data.api
object ApiConstants {
const val BASE_ENDPOINT = "http://192.168.9.152:9290/"
}
\ No newline at end of file
package com.waytous.anticollision.api
package com.waytous.anticollision.data.api
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import com.waytous.anticollision.BuildConfig
import com.waytous.anticollision.bean.MapDataSource
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
interface ApiService {
interface MapApiService {
/**
* 获取障碍物图层数据
......@@ -86,28 +79,4 @@ interface ApiService {
@GET("api/map/parkspotversion")
suspend fun parkSpotVersion(@Query("version") version:String = "-1"): MapDataSource?
companion object {
private val BASE_URL by lazy {
if (BuildConfig.DEBUG) BuildConfig.TEST_MAP_SOURCE_HOST else BuildConfig.DEV_MAP_SOURCE_HOST
}
private val moshi: Moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
fun create(): ApiService {
val logger = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC }
val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
.create(ApiService::class.java)
}
}
}
\ No newline at end of file
package com.waytous.anticollision.di
import android.content.Context
import android.view.LayoutInflater
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.LayoutMapBoxBinding
import com.waytous.anticollision.databinding.PopupMoreFeaturesBinding
import com.waytous.anticollision.databinding.PopupReportStatusBinding
import com.waytous.anticollision.databinding.PopupWorkStatusEditBinding
import com.waytous.anticollision.ui.view.ButtonMorePopup
import com.waytous.anticollision.ui.view.ButtonReportStatusPopup
import com.waytous.anticollision.ui.view.ButtonWorkStatusPopup
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.qualifiers.ActivityContext
import dagger.hilt.android.scopes.ActivityScoped
@InstallIn(ActivityComponent::class)
@Module
object ActivityViewModule {
@ActivityScoped
@Provides
fun provideMapBoxInflater(@ActivityContext context: Context):LayoutMapBoxBinding{
val layoutInflater = LayoutInflater.from(context).also {
it.inflate(R.layout.layout_map_box,null)
}
return LayoutMapBoxBinding.inflate(layoutInflater,null,false)
}
@ActivityScoped
@Provides
fun provideButtonMorePopupWindowInflater(@ActivityContext context: Context): PopupMoreFeaturesBinding {
val layoutInflater = LayoutInflater.from(context).also {
it.inflate(R.layout.popup_more_features,null)
}
return PopupMoreFeaturesBinding.inflate(layoutInflater,null,false)
}
@ActivityScoped
@Provides
fun provideReportStatusPopupWindowInflater(@ActivityContext context: Context): PopupReportStatusBinding {
val layoutInflater = LayoutInflater.from(context).also {
it.inflate(R.layout.popup_report_status,null)
}
return PopupReportStatusBinding.inflate(layoutInflater,null,false)
}
@ActivityScoped
@Provides
fun provideWorkStatusEditPopupWindowInflater(@ActivityContext context: Context): PopupWorkStatusEditBinding {
val layoutInflater = LayoutInflater.from(context).also {
it.inflate(R.layout.popup_work_status_edit,null)
}
return PopupWorkStatusEditBinding.inflate(layoutInflater,null,false)
}
@ActivityScoped
@Provides
fun provideButtonMorePopupWindow(@ActivityContext context: Context,binding:PopupMoreFeaturesBinding):ButtonMorePopup{
return ButtonMorePopup(context,binding)
}
@ActivityScoped
@Provides
fun provideButtonReportStatusPopupWindow(@ActivityContext context: Context,binding:PopupReportStatusBinding):ButtonReportStatusPopup{
return ButtonReportStatusPopup(context,binding)
}
@ActivityScoped
@Provides
fun provideButtonWorkStatusEditPopupWindow(@ActivityContext context: Context,binding:PopupWorkStatusEditBinding):ButtonWorkStatusPopup{
return ButtonWorkStatusPopup(context,binding)
}
}
\ No newline at end of file
package com.waytous.anticollision.di
import android.content.Context
import android.view.LayoutInflater
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.RadioTabCollectBinding
import com.waytous.anticollision.databinding.RadioTabSettingsBinding
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.FragmentComponent
import dagger.hilt.android.qualifiers.ActivityContext
import dagger.hilt.android.scopes.FragmentScoped
@InstallIn(FragmentComponent::class)
@Module
object FragmentViewModule {
@FragmentScoped
@Provides
fun provideRadioTabCollect(@ActivityContext context: Context):RadioTabCollectBinding{
val layoutInflater = LayoutInflater.from(context).also {
it.inflate(R.layout.radio_tab_collect,null)
}
return RadioTabCollectBinding.inflate(layoutInflater,null,false)
}
@FragmentScoped
@Provides
fun provideRadioTabSettings(@ActivityContext context: Context):RadioTabSettingsBinding{
val layoutInflater = LayoutInflater.from(context).also {
it.inflate(R.layout.radio_tab_settings,null)
}
return RadioTabSettingsBinding.inflate(layoutInflater,null,false)
}
}
\ No newline at end of file
package com.waytous.anticollision.di
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import com.waytous.anticollision.data.api.ApiConstants
import com.waytous.anticollision.data.api.MapApiService
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import java.util.concurrent.TimeUnit
@InstallIn(SingletonComponent::class)
@Module
object NetworkModule {
@Provides
fun provideHttpLoggingInterceptor() =
HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC }
@Provides
fun provideOkHttpClient(logger: HttpLoggingInterceptor) = OkHttpClient.Builder()
.addInterceptor(logger)
.connectTimeout(120,TimeUnit.SECONDS)
.readTimeout(120,TimeUnit.SECONDS)
.build()
@Provides
fun provideRetrofit(client: OkHttpClient): Retrofit = Retrofit.Builder()
.baseUrl(ApiConstants.BASE_ENDPOINT)
.client(client)
.addConverterFactory(
MoshiConverterFactory.create(
Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
)
)
.addConverterFactory(ScalarsConverterFactory.create())
.build()
@Provides
fun provideMapApiService(retrofit: Retrofit): MapApiService = retrofit.create(MapApiService::class.java)
}
\ No newline at end of file
package com.waytous.anticollision.repository
import android.content.Context
import androidx.annotation.RequiresPermission
import androidx.room.Room
import com.blankj.utilcode.util.LogUtils
import com.waytous.anticollision.api.MapSourceService
import com.waytous.anticollision.bean.MapDataSourceWrapper
import com.waytous.anticollision.database.AppDatabase
import kotlinx.coroutines.flow.asFlow
import com.waytous.anticollision.data.api.MapApiService
import com.waytous.anticollision.utils.BARRICADE_SOURCE
import com.waytous.anticollision.utils.DIGGING_WORK_AREA_SOURCE
import com.waytous.anticollision.utils.DUMP_AREA_SOURCE
import com.waytous.anticollision.utils.ELECTRONIC_FENCE_SOURCE
import com.waytous.anticollision.utils.LANE_NODE_SOURCE
import com.waytous.anticollision.utils.LANE_SOURCE
import com.waytous.anticollision.utils.OBSTACLES_SOURCE
import com.waytous.anticollision.utils.PARK_SPOT_SOURCE
import com.waytous.anticollision.utils.RUNNABLE_AREA_SOURCE
import com.waytous.anticollision.utils.STATIC_OBJECTS_SOURCE
import com.waytous.anticollision.utils.STATION_AREA_SOURCE
import com.waytous.anticollision.utils.WET_AREA_SOURCE
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class MainRepository@Inject constructor(context:Context) {
class MainRepository@Inject constructor(val mapApiService: MapApiService) {
private val mapApi by lazy {
MapSourceService.create()
fun remoteObstaclesVersion(version:String = "-1") = flow {
val source = mapApiService.obstaclesVersion(version)?.apply {
sourceId = OBSTACLES_SOURCE
}
private val mapDao by lazy {
Room.databaseBuilder(context,AppDatabase::class.java,"anti_collision.db")
.fallbackToDestructiveMigration().build()
.mapDataSourceDao()
}
fun remoteObstaclesVersion(version:String = "-1") = suspend { mapApi.obstaclesVersion(version) }
.asFlow()
.map {source->
LogUtils.d("remoteObstaclesVersion")
source?.let {
val dbSource = mapDao.findById(OBSTACLES_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = OBSTACLES_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = OBSTACLES_SOURCE })
LogUtils.d("remoteObstaclesVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteObstaclesVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的障碍物图层数据为空!")
emit(source?:throw Exception("获取到的障碍物图层数据为空!"))
}
fun localObstaclesVersion() = flow {
val source = mapDao.findById(OBSTACLES_SOURCE)
emit( MapDataSourceWrapper(source, false))
fun remoteElectronicFenceVersion(version:String = "-1")= flow {
val source = mapApiService.electronicFenceVersion(version)?.apply {
sourceId = ELECTRONIC_FENCE_SOURCE
}
fun remoteElectronicFenceVersion(version:String = "-1")= suspend { mapApi.electronicFenceVersion(version) }
.asFlow()
.map {source->
source?.let {
val dbSource = mapDao.findById(ELECTRONIC_FENCE_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = ELECTRONIC_FENCE_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = ELECTRONIC_FENCE_SOURCE })
LogUtils.d("remoteElectronicFenceVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteElectronicFenceVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的电子围栏地图数据为空!")
emit( source?:throw Exception("获取到的电子围栏地图数据为空!"))
}
fun localElectronicFenceVersion() = flow {
val source = mapDao.findById(ELECTRONIC_FENCE_SOURCE)
emit( MapDataSourceWrapper(source, false))
fun remoteWetAreaVersion(version:String = "-1")= flow {
val source = mapApiService.wetAreaVersion(version)?.apply {
sourceId = WET_AREA_SOURCE
}
fun remoteWetAreaVersion(version:String = "-1")= suspend { mapApi.wetAreaVersion(version) }
.asFlow()
.map {source->
source?.let {
val dbSource = mapDao.findById(WET_AREA_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = WET_AREA_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = WET_AREA_SOURCE })
LogUtils.d("remoteWetAreaVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteWetAreaVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的湿滑区域地图数据为空!")
emit(source?:throw Exception("获取到的湿滑区域地图数据为空!"))
}
fun localWetAreaVersion() = flow {
val source = mapDao.findById(WET_AREA_SOURCE)
emit( MapDataSourceWrapper(source, false))
fun remoteLaneNodeVersion(version:String = "-1")= flow {
val source = mapApiService.laneNodeVersion(version)?.apply {
sourceId = LANE_NODE_SOURCE
}
fun remoteLaneNodeVersion(version:String = "-1")= suspend { mapApi.laneNodeVersion(version) }
.asFlow()
.map {source->
source?.let {
val dbSource = mapDao.findById(LANE_NODE_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = LANE_NODE_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = LANE_NODE_SOURCE })
LogUtils.d("remoteLaneNodeVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteLaneNodeVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的湿滑区域地图数据为空!")
emit(source?:throw Exception("获取到的湿滑区域地图数据为空!"))
}
fun localLaneNodeVersion() = flow {
val source = mapDao.findById(LANE_NODE_SOURCE)
emit( MapDataSourceWrapper(source, false))
fun remoteLaneVersion(version:String = "-1")= flow {
val source = mapApiService.laneVersion(version)?.apply {
sourceId = LANE_SOURCE
}
fun remoteLaneVersion(version:String = "-1")= suspend { mapApi.laneVersion(version) }
.asFlow()
.map {source->
source?.let {
val dbSource = mapDao.findById(LANE_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = LANE_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = LANE_SOURCE })
LogUtils.d("remoteLaneVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteLaneVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的车道图层地图数据为空!")
emit(source?:throw Exception("获取到的车道图层地图数据为空!"))
}
fun localLaneVersion() = flow {
val source = mapDao.findById(LANE_SOURCE)
emit( MapDataSourceWrapper(source, false))
fun remoteRunnableAreaVersion(version:String = "-1")= flow {
val source = mapApiService.runnableAreaVersion(version)?.apply {
sourceId = RUNNABLE_AREA_SOURCE
}
fun remoteRunnableAreaVersion(version:String = "-1")= suspend { mapApi.runnableAreaVersion(version) }
.asFlow()
.map {source->
source?.let {
val dbSource = mapDao.findById(RUNNABLE_AREA_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = RUNNABLE_AREA_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = RUNNABLE_AREA_SOURCE })
LogUtils.d("remoteRunnableAreaVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteRunnableAreaVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的可行使区域地图数据为空!")
emit(source?:throw Exception("获取到的可行使区域地图数据为空!"))
}
fun localRunnableAreaVersion() = flow {
val source = mapDao.findById(RUNNABLE_AREA_SOURCE)
emit( MapDataSourceWrapper(source, false))
fun remoteDumpAreaVersion(version:String = "-1")= flow {
val source = mapApiService.dumpAreaVersion(version)?.apply {
sourceId = DUMP_AREA_SOURCE
}
fun remoteDumpAreaVersion(version:String = "-1")= suspend { mapApi.dumpAreaVersion(version) }
.asFlow()
.map {source->
source?.let {
val dbSource = mapDao.findById(DUMP_AREA_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = DUMP_AREA_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = DUMP_AREA_SOURCE })
LogUtils.d("remoteDumpAreaVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteDumpAreaVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的卸载区地图数据为空!")
emit(source?:throw Exception("获取到的卸载区地图数据为空!"))
}
fun localDumpAreaVersion() = flow {
val source = mapDao.findById(DUMP_AREA_SOURCE)
emit( MapDataSourceWrapper(source, false))
fun remoteDiggingWorkAreaVersion(version:String = "-1")= flow {
val source = mapApiService.diggingWorkAreaVersion(version)?.apply {
sourceId = DIGGING_WORK_AREA_SOURCE
}
fun remoteDiggingWorkAreaVersion(version:String = "-1")= suspend { mapApi.diggingWorkAreaVersion(version) }
.asFlow()
.map {source->
source?.let {
val dbSource = mapDao.findById(DIGGING_WORK_AREA_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = DIGGING_WORK_AREA_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = DIGGING_WORK_AREA_SOURCE })
LogUtils.d("remoteDiggingWorkAreaVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteDiggingWorkAreaVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的装载区地图数据为空!")
emit(source?:throw Exception("获取到的装载区地图数据为空!"))
}
fun localDiggingAreaVersion() = flow {
val source = mapDao.findById(DIGGING_WORK_AREA_SOURCE)
emit( MapDataSourceWrapper(source, false))
fun remoteBarricadeVersion(version:String = "-1")= flow {
val source = mapApiService.barricadeVersion(version)?.apply {
sourceId = BARRICADE_SOURCE
}
fun remoteBarricadeVersion(version:String = "-1")= suspend { mapApi.barricadeVersion(version) }
.asFlow()
.map {source->
source?.let {
val dbSource = mapDao.findById(BARRICADE_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = BARRICADE_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = BARRICADE_SOURCE })
LogUtils.d("remoteBarricadeVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteBarricadeVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的挡墙区域地图数据为空!")
emit(source?:throw Exception("获取到的挡墙区域地图数据为空!"))
}
fun localBarricadeVersion() = flow {
val source = mapDao.findById(BARRICADE_SOURCE)
emit( MapDataSourceWrapper(source, false))
fun remoteStationAreaVersion(version:String = "-1")= flow {
val source = mapApiService.stationAreaVersion(version)?.apply {
sourceId = STATION_AREA_SOURCE
}
fun remoteStationAreaVersion(version:String = "-1")= suspend { mapApi.stationAreaVersion(version) }
.asFlow()
.map {source->
source?.let {
val dbSource = mapDao.findById(STATION_AREA_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = STATION_AREA_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = STATION_AREA_SOURCE })
LogUtils.d("remoteStationAreaVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteStationAreaVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的静态区域地图数据为空!")
emit(source?:throw Exception("获取到的静态区域地图数据为空!"))
}
fun localStationAreaVersion() = flow {
val source = mapDao.findById(STATION_AREA_SOURCE)
emit( MapDataSourceWrapper(source, false))
fun remoteParkSpotVersion(version:String = "-1")= flow {
val source = mapApiService.parkSpotVersion(version)?.apply {
sourceId = PARK_SPOT_SOURCE
}
fun remoteParkSpotVersion(version:String = "-1")= suspend { mapApi.parkSpotVersion(version) }
.asFlow()
.map {source->
source?.let {
val dbSource = mapDao.findById(PARK_SPOT_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = PARK_SPOT_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = PARK_SPOT_SOURCE })
LogUtils.d("remoteParkSpotVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteParkSpotVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的停车位图层地图数据为空!")
emit(source?:throw Exception("获取到的停车位图层地图数据为空!"))
}
fun localParkSpotVersion() = flow {
val source = mapDao.findById(PARK_SPOT_SOURCE)
emit( MapDataSourceWrapper(source, false))
fun remoteStaticObjectsVersion(version:String = "-1")= flow {
val source = mapApiService.staticObjectsVersion(version)?.apply {
sourceId = STATIC_OBJECTS_SOURCE
}
fun remoteStaticObjectsVersion(version:String = "-1")= suspend { mapApi.staticObjectsVersion(version) }
.asFlow()
.map {source->
source?.let {
val dbSource = mapDao.findById(STATIC_OBJECTS_SOURCE)
if (dbSource == null) {
mapDao.insertAll(it.apply { sourceId = STATIC_OBJECTS_SOURCE })
MapDataSourceWrapper(it, true)
} else {
if (dbSource.version != it.version) {
mapDao.deleteSource(dbSource)
mapDao.insertAll(it.apply { sourceId = STATIC_OBJECTS_SOURCE })
LogUtils.d("remoteStaticObjectsVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteStaticObjectsVersion")
MapDataSourceWrapper(it, false)
}
}
}?:throw Exception("获取到的静态区域地图数据为空!")
}
fun localStaticObjectsVersion() = flow {
val source = mapDao.findById(STATIC_OBJECTS_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
companion object {
private const val DUMP_AREA_SOURCE = "dumpAreaSource"
private const val OBSTACLES_SOURCE = "obstaclesSource"
private const val ELECTRONIC_FENCE_SOURCE = "electronicFenceSource"
private const val WET_AREA_SOURCE = "wetAreaSource"
private const val LANE_NODE_SOURCE = "laneNodeSource"
private const val LANE_SOURCE = "laneSource"
private const val RUNNABLE_AREA_SOURCE = "runnableAreaSource"
private const val DIGGING_WORK_AREA_SOURCE = "diggingWorkAreaSource"
private const val BARRICADE_SOURCE = "barricadeSource"
private const val STATION_AREA_SOURCE = "stationAreaSource"
private const val STATIC_OBJECTS_SOURCE = "staticObjectsSource"
private const val PARK_SPOT_SOURCE = "parkSpotSource"
emit(source?:throw Exception("获取到的静态区域地图数据为空!"))
}
}
\ No newline at end of file
package com.waytous.anticollision.ui
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import androidx.asynclayoutinflater.view.AsyncLayoutInflater
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import com.blankj.utilcode.util.BarUtils
import com.blankj.utilcode.util.LogUtils
import com.mapbox.android.gestures.StandardScaleGestureDetector
import com.mapbox.geojson.Point
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.MapboxMap
import com.mapbox.maps.ScreenCoordinate
import com.mapbox.maps.Style
import com.mapbox.maps.ViewAnnotationAnchor
import com.mapbox.maps.extension.style.layers.properties.generated.IconAnchor
import com.mapbox.maps.extension.style.style
import com.mapbox.maps.plugin.animation.flyTo
import com.mapbox.maps.plugin.animation.scaleBy
import com.mapbox.maps.plugin.annotation.AnnotationConfig
import com.mapbox.maps.plugin.annotation.annotations
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationOptions
import com.mapbox.maps.plugin.annotation.generated.createPointAnnotationManager
import com.mapbox.maps.plugin.attribution.attribution
import com.mapbox.maps.plugin.compass.compass
import com.mapbox.maps.plugin.gestures.OnScaleListener
import com.mapbox.maps.plugin.gestures.addOnScaleListener
import com.mapbox.maps.plugin.logo.logo
import com.mapbox.maps.plugin.scalebar.scalebar
import com.mapbox.maps.viewannotation.ViewAnnotationManager
import com.mapbox.maps.viewannotation.viewAnnotationOptions
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.CurrentVehicleViewAnnotationLayoutBinding
import com.waytous.anticollision.databinding.LayoutMapBoxBinding
import com.waytous.anticollision.databinding.OtherVehicleViewAnnotationLayoutBinding
import com.waytous.anticollision.repository.MainRepository
import com.waytous.anticollision.ui.view.DelayCauseDialog
import com.waytous.anticollision.ui.view.FaultCauseDialog
import com.waytous.anticollision.ui.view.MoreFeaturesPopup
import com.waytous.anticollision.ui.view.ReportStatusPopup
import com.waytous.anticollision.ui.view.StandbyDialog
import com.waytous.anticollision.ui.view.WorkStatusEditPopup
import com.waytous.anticollision.utils.BitmapUtils
import com.waytous.anticollision.utils.LATITUDE
import com.waytous.anticollision.utils.LONGITUDE
import com.waytous.anticollision.utils.MY_MAP_BOX_STYLE
import com.waytous.anticollision.utils.TRUCK_PATH_LAYER
import com.waytous.anticollision.utils.addBarricadeLineLayer
import com.waytous.anticollision.utils.addBarricadeSource
import com.waytous.anticollision.utils.addDiggingWorkAreaFillLayer
import com.waytous.anticollision.utils.addDiggingWorkAreaSource
import com.waytous.anticollision.utils.addDiggingWorkAreaSymbolLayer
import com.waytous.anticollision.utils.addDumpAreaFillLayer
import com.waytous.anticollision.utils.addDumpAreaSource
import com.waytous.anticollision.utils.addDumpAreaSymbolLayer
import com.waytous.anticollision.utils.addElectronicFenceFillLayer
import com.waytous.anticollision.utils.addElectronicFenceSource
import com.waytous.anticollision.utils.addElectronicFenceSymbolLayer
import com.waytous.anticollision.utils.addLaneLayer
import com.waytous.anticollision.utils.addLaneNodeCircleLayer
import com.waytous.anticollision.utils.addLaneNodeSource
import com.waytous.anticollision.utils.addLaneNodeSymbolLayer
import com.waytous.anticollision.utils.addLaneSource
import com.waytous.anticollision.utils.addObstaclesFillLayer
import com.waytous.anticollision.utils.addObstaclesSource
import com.waytous.anticollision.utils.addObstaclesSymbolLayer
import com.waytous.anticollision.utils.addParkSpotFillLayer
import com.waytous.anticollision.utils.addParkSpotSource
import com.waytous.anticollision.utils.addParkSpotSymbolLayer
import com.waytous.anticollision.utils.addRunnableAreaLayer
import com.waytous.anticollision.utils.addRunnableAreaSource
import com.waytous.anticollision.utils.addStaticObjectsFillLayer
import com.waytous.anticollision.utils.addStaticObjectsSource
import com.waytous.anticollision.utils.addStaticObjectsSymbolLayer
import com.waytous.anticollision.utils.addStationAreaFillLayer
import com.waytous.anticollision.utils.addStationAreaSource
import com.waytous.anticollision.utils.addStationAreaSymbolLayer
import com.waytous.anticollision.utils.addTruckPathLineLayer
import com.waytous.anticollision.utils.addTruckPathSource
import com.waytous.anticollision.utils.addWetAreaFillLayer
import com.waytous.anticollision.utils.addWetAreaSource
import com.waytous.anticollision.utils.addWetAreaSymbolLayer
import com.waytous.anticollision.utils.adjustLayerOrder
import com.waytous.anticollision.vo.VehicleAnnotation
import kotlinx.coroutines.flow.last
import kotlinx.coroutines.launch
import java.math.BigDecimal
open class BaseMapFragment : Fragment() {
private val mapModel: MainViewModel by viewModels {
MainViewModel.MainViewModelFactory(MainRepository(requireContext()))
}
lateinit var moreFeaturesPopup: MoreFeaturesPopup
lateinit var workStatusEditPopup: WorkStatusEditPopup
lateinit var reportStatusPopup: ReportStatusPopup
lateinit var reportStatusDialog: FaultCauseDialog
lateinit var delaySelectDialog: DelayCauseDialog
lateinit var standbyDialog: StandbyDialog
val iconCurrentNormalVehicleBitmap by lazy {
BitmapUtils.bitmapFromDrawableRes(requireContext(), R.drawable.my_vehicle_normal)
}
private val iconOtherAlarmVehicleBitmap by lazy {
BitmapUtils.bitmapFromDrawableRes(requireContext(), R.drawable.other_vehicle_normal)
}
private val asyncInflater by lazy {
AsyncLayoutInflater(requireContext())
}
lateinit var layoutMapBoxBinding: LayoutMapBoxBinding
lateinit var mapboxMap: MapboxMap
private lateinit var viewAnnotationManager: ViewAnnotationManager
private lateinit var pointAnnotationManager: PointAnnotationManager
private val cameraOptions: CameraOptions by lazy {
CameraOptions.Builder().center(
Point.fromLngLat(
LONGITUDE,
LATITUDE
)
).zoom(14.0).build()
}
companion object {
private val scaleLengths = listOf(
5,
10,
20,
50,
100,
200,
500,
1000,
2000,
5000,
10000,
20000,
50000,
100000,
200000,
500000,
1000000,
2000000
)
const val MINIMUM_ZOOM_LEVEL = 11.0
const val MAXIMUM_ZOOM_LEVEL = 26.0
const val DEFAULT_ZOOM_LEVEL = 14.0
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
BarUtils.setNavBarVisibility(requireActivity(),false)
layoutMapBoxBinding = LayoutMapBoxBinding.inflate(LayoutInflater.from(requireContext()))
reportStatusDialog = FaultCauseDialog(requireContext(),R.style.DialogStyle)
delaySelectDialog = DelayCauseDialog(requireContext(),R.style.DialogStyle)
standbyDialog = StandbyDialog(requireContext(),R.style.DialogStyle)
layoutMapBoxBinding.mapView.run {
logo.enabled = false
compass.enabled = false
attribution.enabled = false
}
workStatusEditPopup = WorkStatusEditPopup(context).also {
it.setOutSideDismiss(true)
it.popupGravity = Gravity.TOP or Gravity.CENTER
it.setBackgroundColor(R.color.color_99000000)
}
moreFeaturesPopup = MoreFeaturesPopup(context).also {
it.setOutSideDismiss(true)
it.popupGravity = Gravity.TOP or Gravity.CENTER
it.maskOffsetY = 20
it.setBackgroundColor(R.color.color_99000000)
it.navigationTo(findNavController())
}
reportStatusPopup = ReportStatusPopup(context).also {
it.setOutSideDismiss(true)
it.popupGravity = Gravity.TOP or Gravity.CENTER
it.setBackgroundColor(R.color.color_99000000)
it.itemFault(reportStatusDialog)
it.itemDelay(delaySelectDialog)
it.itemStandby(standbyDialog)
}
}
fun setupMapBox() {
LogUtils.d("setupMapBox")
mapboxMap = layoutMapBoxBinding.mapView.getMapboxMap().also {
it.setCamera(cameraOptions)
}
layoutMapBoxBinding.zoomIn.setOnClickListener {
val zoomLevel = BigDecimal(mapboxMap.cameraState.zoom).minus(BigDecimal(0.1.toString()))
when (BigDecimal(MINIMUM_ZOOM_LEVEL.toString()).compareTo(zoomLevel)) {
-1 -> {
mapboxMap.setCamera(CameraOptions.Builder().zoom(zoomLevel.toDouble()).build())
}
else -> {
mapboxMap.setCamera(CameraOptions.Builder().zoom(DEFAULT_ZOOM_LEVEL).build())
}
}
LogUtils.d("zoom in:${layoutMapBoxBinding.mapView.scalebar.distancePerPixel}")
}
layoutMapBoxBinding.zoomOut.setOnClickListener {
val zoomLevel = BigDecimal(mapboxMap.cameraState.zoom).add(BigDecimal(0.1.toString()))
when (BigDecimal(MAXIMUM_ZOOM_LEVEL.toString()).compareTo(zoomLevel)) {
-1 -> {
mapboxMap.setCamera(CameraOptions.Builder().zoom(DEFAULT_ZOOM_LEVEL).build())
}
else -> {
mapboxMap.setCamera(CameraOptions.Builder().zoom(zoomLevel.toDouble()).build())
}
}
LogUtils.d("zoom out:${layoutMapBoxBinding.mapView.scalebar.distancePerPixel}")
}
layoutMapBoxBinding.locationTruck.setOnClickListener {
mapboxMap.flyTo(cameraOptions)
}
mapboxMap.loadStyle(style(MY_MAP_BOX_STYLE) {
}) {
setupStyle(it)
}
}
private fun setupStyle(style: Style) {
lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
mapModel.runnableAreaSource().last()?.let { source ->
style.addRunnableAreaSource(source)
style.addRunnableAreaLayer()
}
mapModel.laneSource().last()?.let { source ->
style.addLaneSource(source)
style.addLaneLayer()
}
mapModel.laneNodeSource().last()?.let { source ->
style.addLaneNodeSource(source)
style.addLaneNodeCircleLayer()
style.addLaneNodeSymbolLayer()
}
mapModel.diggingWorkAreaSource().last()?.let { source ->
style.addDiggingWorkAreaSource(source)
style.addDiggingWorkAreaFillLayer()
style.addDiggingWorkAreaSymbolLayer()
}
mapModel.obstaclesSource().last()?.let { source ->
style.addObstaclesSource(source)
style.addObstaclesFillLayer()
style.addObstaclesSymbolLayer()
}
mapModel.electronicFenceSource().last()?.let { source ->
style.addElectronicFenceSource(source)
style.addElectronicFenceFillLayer()
style.addElectronicFenceSymbolLayer()
}
mapModel.wetAreaSource().last()?.let { source ->
style.addWetAreaSource(source)
style.addWetAreaFillLayer()
style.addWetAreaSymbolLayer()
}
mapModel.dumpAreaSource().last()?.let { source ->
style.addDumpAreaSource(source)
style.addDumpAreaFillLayer()
style.addDumpAreaSymbolLayer()
}
mapModel.barricadeSource().last()?.let { source ->
style.addBarricadeSource(source)
style.addBarricadeLineLayer()
}
mapModel.stationAreaSource().last()?.let { source ->
style.addStationAreaSource(source)
style.addStationAreaFillLayer()
style.addStationAreaSymbolLayer()
}
mapModel.staticObjectsSource().last()?.let { source ->
style.addStaticObjectsSource(source)
style.addStaticObjectsFillLayer()
style.addStaticObjectsSymbolLayer()
}
mapModel.parkSpotSource().last()?.let { source ->
style.addParkSpotSource(source)
style.addParkSpotFillLayer()
style.addParkSpotSymbolLayer()
}
style.addTruckPathSource()
style.addTruckPathLineLayer()
style.adjustLayerOrder()
initAnnotationManager()
addTempAnnotations()
}
}
}
fun addTempAnnotations() {
val otherAnnotation = VehicleAnnotation(
"KK-01", 36, 25,
Point.fromLngLat(LONGITUDE, LATITUDE), true
)
updateCurrentVehicleAnnotation(otherAnnotation)
val otherAnnotation1 =
VehicleAnnotation("KK-02", 24, 25, Point.fromLngLat(119.76739, 49.37722), true)
val otherAnnotation2 =
VehicleAnnotation("KK-03", 36, 20, Point.fromLngLat(119.75694, 49.38632), true)
val others = listOf(otherAnnotation1, otherAnnotation2)
addOtherVehicleAnnotations(others)
}
private fun initAnnotationManager() {
viewAnnotationManager = layoutMapBoxBinding.mapView.viewAnnotationManager
pointAnnotationManager =
layoutMapBoxBinding.mapView.annotations.createPointAnnotationManager(
AnnotationConfig(TRUCK_PATH_LAYER)
)
}
fun updateCurrentVehicleAnnotation(otherAnnotation: VehicleAnnotation) {
val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
.withPoint(otherAnnotation.point)
.withIconImage(iconCurrentNormalVehicleBitmap!!)
.withIconSize(0.25)
.withIconAnchor(IconAnchor.BOTTOM)
.withDraggable(false)
val pointAnnotation = pointAnnotationManager.create(pointAnnotationOptions)
pointAnnotation.symbolSortKey = Double.MAX_VALUE
val viewAnnotation = viewAnnotationManager.addViewAnnotation(
resId = R.layout.current_vehicle_view_annotation_layout,
options = viewAnnotationOptions {
geometry(otherAnnotation.point)
associatedFeatureId(pointAnnotation.featureIdentifier)
anchor(ViewAnnotationAnchor.BOTTOM)
offsetY((pointAnnotation.iconImageBitmap?.height!! * 0.25).toInt())
allowOverlap(true)
}
)
val binding = CurrentVehicleViewAnnotationLayoutBinding.bind(viewAnnotation)
binding.annotationCurrentVehicleNo.text =
context?.getString(R.string.annotation_vehicle_no, "KK-001")
binding.annotationCurrentVehicleSpeed.text =
context?.getString(R.string.annotation_vehicle_speed, 36)
}
fun addOtherVehicleAnnotations(others: List<VehicleAnnotation>) {
others.forEach { vehicle ->
val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
.withPoint(vehicle.point)
.withIconImage(iconOtherAlarmVehicleBitmap!!)
.withIconSize(0.25)
.withIconAnchor(IconAnchor.BOTTOM)
.withDraggable(false)
val pointAnnotation = pointAnnotationManager.create(pointAnnotationOptions)
pointAnnotation.symbolSortKey = Double.MAX_VALUE
val viewAnnotation = viewAnnotationManager.addViewAnnotation(
resId = R.layout.other_vehicle_view_annotation_layout,
options = viewAnnotationOptions {
geometry(vehicle.point)
// associatedFeatureId(pointAnnotation.featureIdentifier)
anchor(ViewAnnotationAnchor.BOTTOM)
offsetY((pointAnnotation.iconImageBitmap?.height!! * 0.25).toInt())
allowOverlap(true)
}
)
val binding = OtherVehicleViewAnnotationLayoutBinding.bind(viewAnnotation)
binding.annotationOtherVehicleNo.text =
context?.getString(R.string.annotation_vehicle_no, vehicle.vehicleNo)
binding.annotationOtherVehicleSpeed.text = vehicle.speed.toString()
binding.annotationOtherVehicleDistance.text = vehicle.distance.toString()
}
}
}
\ No newline at end of file
package com.waytous.anticollision.ui
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import com.blankj.utilcode.util.BarUtils
import com.blankj.utilcode.util.ColorUtils
import com.gyf.immersionbar.ImmersionBar
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.ScreenUtils
import com.mapbox.geojson.Point
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.Style
import com.mapbox.maps.ViewAnnotationAnchor
import com.mapbox.maps.extension.style.layers.properties.generated.IconAnchor
import com.mapbox.maps.extension.style.style
import com.mapbox.maps.plugin.animation.flyTo
import com.mapbox.maps.plugin.annotation.AnnotationConfig
import com.mapbox.maps.plugin.annotation.annotations
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationOptions
import com.mapbox.maps.plugin.annotation.generated.createPointAnnotationManager
import com.mapbox.maps.plugin.attribution.attribution
import com.mapbox.maps.plugin.compass.compass
import com.mapbox.maps.plugin.logo.logo
import com.mapbox.maps.plugin.scalebar.scalebar
import com.mapbox.maps.viewannotation.ViewAnnotationManager
import com.mapbox.maps.viewannotation.viewAnnotationOptions
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.ActivityMainBinding
import com.waytous.anticollision.repository.MainRepository
import com.waytous.anticollision.databinding.CurrentVehicleViewAnnotationLayoutBinding
import com.waytous.anticollision.databinding.LayoutMapBoxBinding
import com.waytous.anticollision.databinding.OtherVehicleViewAnnotationLayoutBinding
import com.waytous.anticollision.utils.BARRICADE_SOURCE
import com.waytous.anticollision.utils.BitmapUtils
import com.waytous.anticollision.utils.DIGGING_WORK_AREA_SOURCE
import com.waytous.anticollision.utils.DUMP_AREA_SOURCE
import com.waytous.anticollision.utils.ELECTRONIC_FENCE_SOURCE
import com.waytous.anticollision.utils.LANE_NODE_SOURCE
import com.waytous.anticollision.utils.LANE_SOURCE
import com.waytous.anticollision.utils.LATITUDE
import com.waytous.anticollision.utils.LONGITUDE
import com.waytous.anticollision.utils.MY_MAP_BOX_STYLE
import com.waytous.anticollision.utils.OBSTACLES_SOURCE
import com.waytous.anticollision.utils.PARK_SPOT_SOURCE
import com.waytous.anticollision.utils.RUNNABLE_AREA_SOURCE
import com.waytous.anticollision.utils.STATIC_OBJECTS_SOURCE
import com.waytous.anticollision.utils.STATION_AREA_SOURCE
import com.waytous.anticollision.utils.TRUCK_PATH_LAYER
import com.waytous.anticollision.utils.WET_AREA_SOURCE
import com.waytous.anticollision.utils.addBarricadeLineLayer
import com.waytous.anticollision.utils.addBarricadeSource
import com.waytous.anticollision.utils.addDiggingWorkAreaFillLayer
import com.waytous.anticollision.utils.addDiggingWorkAreaSource
import com.waytous.anticollision.utils.addDiggingWorkAreaSymbolLayer
import com.waytous.anticollision.utils.addDumpAreaFillLayer
import com.waytous.anticollision.utils.addDumpAreaSource
import com.waytous.anticollision.utils.addDumpAreaSymbolLayer
import com.waytous.anticollision.utils.addElectronicFenceFillLayer
import com.waytous.anticollision.utils.addElectronicFenceSource
import com.waytous.anticollision.utils.addElectronicFenceSymbolLayer
import com.waytous.anticollision.utils.addLaneLayer
import com.waytous.anticollision.utils.addLaneNodeCircleLayer
import com.waytous.anticollision.utils.addLaneNodeSource
import com.waytous.anticollision.utils.addLaneNodeSymbolLayer
import com.waytous.anticollision.utils.addLaneSource
import com.waytous.anticollision.utils.addObstaclesFillLayer
import com.waytous.anticollision.utils.addObstaclesSource
import com.waytous.anticollision.utils.addObstaclesSymbolLayer
import com.waytous.anticollision.utils.addParkSpotFillLayer
import com.waytous.anticollision.utils.addParkSpotSource
import com.waytous.anticollision.utils.addParkSpotSymbolLayer
import com.waytous.anticollision.utils.addRunnableAreaLayer
import com.waytous.anticollision.utils.addRunnableAreaSource
import com.waytous.anticollision.utils.addStaticObjectsFillLayer
import com.waytous.anticollision.utils.addStaticObjectsSource
import com.waytous.anticollision.utils.addStaticObjectsSymbolLayer
import com.waytous.anticollision.utils.addStationAreaFillLayer
import com.waytous.anticollision.utils.addStationAreaSource
import com.waytous.anticollision.utils.addStationAreaSymbolLayer
import com.waytous.anticollision.utils.addTruckPathLineLayer
import com.waytous.anticollision.utils.addTruckPathSource
import com.waytous.anticollision.utils.addWetAreaFillLayer
import com.waytous.anticollision.utils.addWetAreaSource
import com.waytous.anticollision.utils.addWetAreaSymbolLayer
import com.waytous.anticollision.utils.adjustLayerOrder
import com.waytous.anticollision.vo.VehicleAnnotation
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import java.math.BigDecimal
import javax.inject.Inject
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val viewModel by lazy {
ViewModelProvider(this,MainViewModel.MainViewModelFactory(MainRepository(this)))[MainViewModel::class.java]
private val viewModel:MainModel by viewModels()
@Inject
lateinit var mapBinding:LayoutMapBoxBinding
private val mapboxMap by lazy {
mapBinding.mapView.getMapboxMap()
}
val iconCurrentNormalVehicleBitmap by lazy {
BitmapUtils.bitmapFromDrawableRes(this, R.drawable.my_vehicle_normal)
}
private val iconOtherAlarmVehicleBitmap by lazy {
BitmapUtils.bitmapFromDrawableRes(this, R.drawable.other_vehicle_normal)
}
private lateinit var viewAnnotationManager: ViewAnnotationManager
private lateinit var pointAnnotationManager: PointAnnotationManager
private val cameraOptions: CameraOptions by lazy {
CameraOptions.Builder().center(
Point.fromLngLat(
LONGITUDE,
LATITUDE
)
).zoom(14.0).build()
}
companion object {
private val scaleLengths = listOf(
5,
10,
20,
50,
100,
200,
500,
1000,
2000,
5000,
10000,
20000,
50000,
100000,
200000,
500000,
1000000,
2000000
)
const val MINIMUM_ZOOM_LEVEL = 11.0
const val MAXIMUM_ZOOM_LEVEL = 26.0
const val DEFAULT_ZOOM_LEVEL = 14.0
}
private fun setupMapBox() {
LogUtils.d("setupMapBox")
mapboxMap.setCamera(cameraOptions)
mapBinding.zoomIn.setOnClickListener {
val zoomLevel = BigDecimal(mapboxMap.cameraState.zoom).minus(BigDecimal(0.1.toString()))
when (BigDecimal(MINIMUM_ZOOM_LEVEL.toString()).compareTo(zoomLevel)) {
-1 -> {
mapboxMap.setCamera(CameraOptions.Builder().zoom(zoomLevel.toDouble()).build())
}
else -> {
mapboxMap.setCamera(CameraOptions.Builder().zoom(DEFAULT_ZOOM_LEVEL).build())
}
}
}
mapBinding.zoomOut.setOnClickListener {
val zoomLevel = BigDecimal(mapboxMap.cameraState.zoom).add(BigDecimal(0.1.toString()))
when (BigDecimal(MAXIMUM_ZOOM_LEVEL.toString()).compareTo(zoomLevel)) {
-1 -> {
mapboxMap.setCamera(CameraOptions.Builder().zoom(DEFAULT_ZOOM_LEVEL).build())
}
else -> {
mapboxMap.setCamera(CameraOptions.Builder().zoom(zoomLevel.toDouble()).build())
}
}
LogUtils.d("zoom out:${mapBinding.mapView.scalebar.distancePerPixel}")
}
mapBinding.locationTruck.setOnClickListener {
mapboxMap.flyTo(cameraOptions)
}
mapboxMap.loadStyle(style(MY_MAP_BOX_STYLE) {
}) {
setupStyle(it)
}
}
fun addTempAnnotations() {
val otherAnnotation = VehicleAnnotation(
"KK-01", 36, 25,
Point.fromLngLat(LONGITUDE, LATITUDE), true
)
updateCurrentVehicleAnnotation(otherAnnotation)
val otherAnnotation1 =
VehicleAnnotation("KK-02", 24, 25, Point.fromLngLat(119.76739, 49.37722), true)
val otherAnnotation2 =
VehicleAnnotation("KK-03", 36, 20, Point.fromLngLat(119.75694, 49.38632), true)
val others = listOf(otherAnnotation1, otherAnnotation2)
addOtherVehicleAnnotations(others)
}
private fun initAnnotationManager() {
viewAnnotationManager = mapBinding.mapView.viewAnnotationManager
pointAnnotationManager =
mapBinding.mapView.annotations.createPointAnnotationManager(
AnnotationConfig(TRUCK_PATH_LAYER)
)
}
fun updateCurrentVehicleAnnotation(otherAnnotation: VehicleAnnotation) {
val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
.withPoint(otherAnnotation.point)
.withIconImage(iconCurrentNormalVehicleBitmap!!)
.withIconSize(0.25)
.withIconAnchor(IconAnchor.BOTTOM)
.withDraggable(false)
val pointAnnotation = pointAnnotationManager.create(pointAnnotationOptions)
pointAnnotation.symbolSortKey = Double.MAX_VALUE
val viewAnnotation = viewAnnotationManager.addViewAnnotation(
resId = R.layout.current_vehicle_view_annotation_layout,
options = viewAnnotationOptions {
geometry(otherAnnotation.point)
associatedFeatureId(pointAnnotation.featureIdentifier)
anchor(ViewAnnotationAnchor.BOTTOM)
offsetY((pointAnnotation.iconImageBitmap?.height!! * 0.25).toInt())
allowOverlap(true)
}
)
val binding = CurrentVehicleViewAnnotationLayoutBinding.bind(viewAnnotation)
binding.annotationCurrentVehicleNo.text =
getString(R.string.annotation_vehicle_no, "KK-001")
binding.annotationCurrentVehicleSpeed.text =
getString(R.string.annotation_vehicle_speed, 36)
}
fun addOtherVehicleAnnotations(others: List<VehicleAnnotation>) {
others.forEach { vehicle ->
val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
.withPoint(vehicle.point)
.withIconImage(iconOtherAlarmVehicleBitmap!!)
.withIconSize(0.25)
.withIconAnchor(IconAnchor.BOTTOM)
.withDraggable(false)
val pointAnnotation = pointAnnotationManager.create(pointAnnotationOptions)
pointAnnotation.symbolSortKey = Double.MAX_VALUE
val viewAnnotation = viewAnnotationManager.addViewAnnotation(
resId = R.layout.other_vehicle_view_annotation_layout,
options = viewAnnotationOptions {
geometry(vehicle.point)
associatedFeatureId(pointAnnotation.featureIdentifier)
anchor(ViewAnnotationAnchor.BOTTOM)
offsetY((pointAnnotation.iconImageBitmap?.height!! * 0.25).toInt())
allowOverlap(true)
}
)
val binding = OtherVehicleViewAnnotationLayoutBinding.bind(viewAnnotation)
binding.annotationOtherVehicleNo.text = getString(R.string.annotation_vehicle_no, vehicle.vehicleNo)
binding.annotationOtherVehicleSpeed.text = vehicle.speed.toString()
binding.annotationOtherVehicleDistance.text = vehicle.distance.toString()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//设置下布局向上移动状态栏的高度
BarUtils.setStatusBarColor(this, ColorUtils.getColor(R.color.status_bg_color))
//设置隐藏虚拟按键
BarUtils.setNavBarVisibility(this,false)
BarUtils.setStatusBarVisibility(this,false)
supportActionBar?.hide()
ImmersionBar.with(this)
.statusBarAlpha(0.0f)
.statusBarDarkFont(true)
.fitsSystemWindows(true)
ScreenUtils.setFullScreen(this)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
with(mapBinding.mapView){
logo.enabled = false
compass.enabled = false
attribution.enabled = false
}
setupMapBox()
}
private fun setupStyle(style: Style) {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
viewModel.loadMapDataSource().collect {
when(it.sourceId){
OBSTACLES_SOURCE ->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addObstaclesSource(it.geojson)
style.addObstaclesFillLayer()
style.addObstaclesSymbolLayer()
}
}
ELECTRONIC_FENCE_SOURCE->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addElectronicFenceSource(it.geojson)
style.addElectronicFenceFillLayer()
style.addElectronicFenceSymbolLayer()
}
}
WET_AREA_SOURCE->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addWetAreaSource(it.geojson)
style.addWetAreaFillLayer()
style.addWetAreaSymbolLayer()
}
}
LANE_NODE_SOURCE->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addLaneNodeSource(it.geojson)
style.addLaneNodeCircleLayer()
style.addLaneNodeSymbolLayer()
}
}
LANE_SOURCE ->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addLaneSource(it.geojson)
style.addLaneLayer()
}
}
RUNNABLE_AREA_SOURCE->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addRunnableAreaSource(it.geojson)
style.addRunnableAreaLayer()
}
}
DUMP_AREA_SOURCE->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addDumpAreaSource(it.geojson)
style.addDumpAreaFillLayer()
style.addDumpAreaSymbolLayer()
}
}
DIGGING_WORK_AREA_SOURCE->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addDiggingWorkAreaSource(it.geojson)
style.addDiggingWorkAreaFillLayer()
style.addDiggingWorkAreaSymbolLayer()
}
}
BARRICADE_SOURCE->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addBarricadeSource(it.geojson)
style.addBarricadeLineLayer()
}
}
STATION_AREA_SOURCE->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addStationAreaSource(it.geojson)
style.addStationAreaFillLayer()
style.addStationAreaSymbolLayer()
}
}
PARK_SPOT_SOURCE->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addParkSpotSource(it.geojson)
style.addParkSpotFillLayer()
style.addParkSpotSymbolLayer()
}
}
STATIC_OBJECTS_SOURCE->{
if (it.geojson.isNotEmpty()&&it.version != "-1") {
style.addStaticObjectsSource(it.geojson)
style.addStaticObjectsFillLayer()
style.addStaticObjectsSymbolLayer()
}
}
else->{
style.addTruckPathSource()
style.addTruckPathLineLayer()
}
}
style.adjustLayerOrder()
}
}
}
}
}
\ No newline at end of file
package com.waytous.anticollision.ui
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.mapbox.geojson.Point
import com.waytous.anticollision.bean.MapDataSource
import com.waytous.anticollision.repository.MainRepository
import com.waytous.anticollision.utils.LATITUDE
import com.waytous.anticollision.utils.LONGITUDE
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flattenMerge
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import java.math.BigDecimal
import javax.inject.Inject
@HiltViewModel
class MainModel @Inject constructor(private val mainRepository: MainRepository) : ViewModel() {
val zoom: MutableLiveData<BigDecimal> by lazy {
MutableLiveData(BigDecimal(16.0))
}
val center: MutableLiveData<Point> by lazy {
MutableLiveData(Point.fromLngLat(LONGITUDE, LATITUDE))
}
private val _obstaclesSource = MutableStateFlow(MapDataSource())
private val _electronicFence = MutableStateFlow(MapDataSource())
private val _wetArea = MutableStateFlow(MapDataSource())
private val _laneNode = MutableStateFlow(MapDataSource())
private val _lane = MutableStateFlow(MapDataSource())
private val _runnableArea = MutableStateFlow(MapDataSource())
private val _dumpArea = MutableStateFlow(MapDataSource())
private val _diggingWorkArea = MutableStateFlow(MapDataSource())
private val _barricade = MutableStateFlow(MapDataSource())
private val _stationArea = MutableStateFlow(MapDataSource())
private val _parkSpot = MutableStateFlow(MapDataSource())
private val _staticObjects = MutableStateFlow(MapDataSource())
init {
viewModelScope.launch {
mainRepository.remoteObstaclesVersion().collect{
if (_obstaclesSource.value.version != it.version) {
_obstaclesSource.value = it
}
}
}
viewModelScope.launch {
mainRepository.remoteElectronicFenceVersion().collect{
if (_electronicFence.value.version != it.version) {
_electronicFence.value = it
}
}
}
viewModelScope.launch {
mainRepository.remoteWetAreaVersion().collect{
if (_wetArea.value.version != it.version) {
_wetArea.value = it
}
}
}
viewModelScope.launch {
mainRepository.remoteLaneNodeVersion().collect{
if (_laneNode.value.version != it.version) {
_laneNode.value = it
}
}
}
viewModelScope.launch {
mainRepository.remoteLaneVersion().collect{
if (_lane.value.version != it.version) {
_lane.value = it
}
}
}
viewModelScope.launch {
mainRepository.remoteRunnableAreaVersion().collect{
if (_runnableArea.value.version != it.version) {
_runnableArea.value = it
}
}
}
viewModelScope.launch {
mainRepository.remoteDumpAreaVersion().collect{
if (_dumpArea.value.version != it.version) {
_dumpArea.value = it
}
}
}
viewModelScope.launch {
mainRepository.remoteDiggingWorkAreaVersion().collect{
if (_diggingWorkArea.value.version != it.version) {
_diggingWorkArea.value = it
}
}
}
viewModelScope.launch {
mainRepository.remoteBarricadeVersion().collect{
if (_barricade.value.version != it.version) {
_barricade.value = it
}
}
}
viewModelScope.launch {
mainRepository.remoteStationAreaVersion().collect{
if (_stationArea.value.version != it.version) {
_stationArea.value = it
}
}
}
viewModelScope.launch {
mainRepository.remoteParkSpotVersion().collect{
if (_parkSpot.value.version != it.version) {
_parkSpot.value = it
}
}
}
viewModelScope.launch {
mainRepository.remoteStaticObjectsVersion().collect{
if (_staticObjects.value.version != it.version) {
_staticObjects.value = it
}
}
}
}
@OptIn(ExperimentalCoroutinesApi::class)
suspend fun loadMapDataSource() = flowOf(
_obstaclesSource,
_electronicFence,
_wetArea,
_laneNode,
_lane,
_runnableArea,
_dumpArea,
_diggingWorkArea,
_barricade,
_stationArea,
_parkSpot,
_staticObjects
).flattenMerge().stateIn(viewModelScope)
}
\ No newline at end of file
package com.waytous.anticollision.ui
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.CreationExtras
import com.blankj.utilcode.util.LogUtils
import com.mapbox.geojson.Point
import com.waytous.anticollision.repository.MainRepository
import com.waytous.anticollision.utils.LATITUDE
import com.waytous.anticollision.utils.LONGITUDE
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import java.math.BigDecimal
import javax.inject.Inject
class MainViewModel @Inject constructor(private val mainRepository: MainRepository) : ViewModel() {
val zoom: MutableLiveData<BigDecimal> by lazy {
MutableLiveData(BigDecimal(16.0))
}
val center: MutableLiveData<Point> by lazy {
MutableLiveData(Point.fromLngLat(LONGITUDE, LATITUDE))
}
fun obstaclesSource() =
flowOf(mainRepository.localObstaclesVersion(), mainRepository.remoteObstaclesVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
fun electronicFenceSource() = flowOf(
mainRepository.localElectronicFenceVersion(),
mainRepository.remoteElectronicFenceVersion()
).flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
fun wetAreaSource() =
flowOf(mainRepository.localWetAreaVersion(), mainRepository.remoteWetAreaVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
fun laneNodeSource() =
flowOf(mainRepository.localLaneNodeVersion(), mainRepository.remoteLaneNodeVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
fun laneSource() = flowOf(mainRepository.localLaneVersion(), mainRepository.remoteLaneVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
fun runnableAreaSource() = flowOf(
mainRepository.localRunnableAreaVersion(),
mainRepository.remoteRunnableAreaVersion()
).flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
fun dumpAreaSource() =
flowOf(mainRepository.localDumpAreaVersion(), mainRepository.remoteDumpAreaVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
fun diggingWorkAreaSource() = flowOf(
mainRepository.localDiggingAreaVersion(),
mainRepository.remoteDiggingWorkAreaVersion()
).flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
fun barricadeSource() =
flowOf(mainRepository.localBarricadeVersion(), mainRepository.remoteBarricadeVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
fun stationAreaSource() =
flowOf(mainRepository.localStationAreaVersion(), mainRepository.remoteStationAreaVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
fun parkSpotSource() =
flowOf(mainRepository.localParkSpotVersion(), mainRepository.remoteParkSpotVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
fun staticObjectsSource() = flowOf(
mainRepository.localStaticObjectsVersion(),
mainRepository.remoteStaticObjectsVersion()
).flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it?.geojson
}.flowOn(Dispatchers.IO)
.catch {
LogUtils.e(it.message)
emit("")
}
class MainViewModelFactory(private val mainRepository: MainRepository) :
ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
return MainViewModel(mainRepository) as T
}
}
}
\ No newline at end of file
package com.waytous.anticollision.ui
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.view.View
import androidx.appcompat.content.res.AppCompatResources
import com.mapbox.geojson.Point
import com.mapbox.maps.MapView
import com.mapbox.maps.Style
import com.mapbox.maps.ViewAnnotationAnchor
import com.mapbox.maps.extension.style.expressions.dsl.generated.interpolate
import com.mapbox.maps.extension.style.layers.properties.generated.*
import com.mapbox.maps.plugin.LocationPuck2D
import com.mapbox.maps.plugin.annotation.annotations
import com.mapbox.maps.plugin.annotation.generated.PointAnnotation
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationOptions
import com.mapbox.maps.plugin.annotation.generated.createPointAnnotationManager
import com.mapbox.maps.plugin.locationcomponent.location
import com.mapbox.maps.viewannotation.ViewAnnotationManager
import com.mapbox.maps.viewannotation.viewAnnotationOptions
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.CurrentVehicleViewAnnotationLayoutBinding
import com.waytous.anticollision.utils.BitmapUtils
import com.waytous.anticollision.utils.LATITUDE
import com.waytous.anticollision.utils.LONGITUDE
/**
* mapbox及控制组件封装
* @author male
* @param context
* */
class MapBoxLayout(private val context: Context,private val mapView:MapView){
private var zoomLevel:Double = 14.0
private lateinit var style: Style
private lateinit var viewAnnotationManager: ViewAnnotationManager
private lateinit var pointAnnotationManager: PointAnnotationManager
private lateinit var pointAnnotation: PointAnnotation
private lateinit var viewAnnotation: View
companion object{
private val scaleLengths = listOf(5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000, 2000000)
private const val MINIMUM_ZOOM_LEVEL = 11.0
private const val MAXIMUM_ZOOM_LEVEL = 26.0
}
private val iconCurrentNormalVehicleBitmap by lazy {
BitmapUtils.bitmapFromDrawableRes(context,R.drawable.my_vehicle_normal)
}
private val iconOtherAlarmVehicleBitmap by lazy {
BitmapUtils.bitmapFromDrawableRes(context,R.drawable.other_vehicle_normal)
}
fun updateTruckLocation(drawable:Int){
mapView.location.locationPuck = LocationPuck2D(AppCompatResources.getDrawable(context,drawable),scaleExpression = interpolate {
linear()
zoom()
stop {
literal(MINIMUM_ZOOM_LEVEL)
literal(0.6)
}
stop {
literal(MAXIMUM_ZOOM_LEVEL)
literal(1.2)
}
}.toJson())
}
}
\ No newline at end of file
......@@ -6,53 +6,31 @@ import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.AdapterView.OnItemSelectedListener
import androidx.appcompat.widget.AppCompatImageView
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.blankj.utilcode.util.LogUtils
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.FragmentCollectBinding
import com.waytous.anticollision.databinding.FragmentCollectTabCollectBinding
import com.waytous.anticollision.databinding.FragmentCollectTabSettingsBinding
import com.waytous.anticollision.ui.BaseMapFragment
import com.waytous.anticollision.databinding.LayoutMapBoxBinding
import com.waytous.anticollision.databinding.RadioTabCollectBinding
import com.waytous.anticollision.databinding.RadioTabSettingsBinding
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
class CollectFragment : BaseMapFragment() {
companion object{
const val TAB_ITEM_COLLECT = 0x01
const val TAB_ITEM_SETTINGS = 0x02
}
@AndroidEntryPoint
class CollectFragment : Fragment() {
private var _binding: FragmentCollectBinding? = null
private lateinit var tabCollectBinding: FragmentCollectTabCollectBinding
@Inject
lateinit var mapBoxBinding: LayoutMapBoxBinding
@Inject
lateinit var tabCollectBinding: RadioTabCollectBinding
@Inject
lateinit var tabSettingsBinding: RadioTabSettingsBinding
private lateinit var tabSettingsBinding: FragmentCollectTabSettingsBinding
private val binding get() = _binding!!
private val iconCalibrates by lazy {
listOf(tabCollectBinding.vehicleLeftFrontWheel,
tabCollectBinding.vehicleRightFrontWheel,
tabCollectBinding.vehicleLeftBackWheel,
tabCollectBinding.vehicleRightBackWheel,
tabCollectBinding.vehicleGeometricCenter,
tabCollectBinding.vehicleFrontAxleCenter,
tabCollectBinding.vehicleBackAxleCenter)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentCollectBinding.inflate(inflater, container, false)
context?:return binding.root
setupMapBox()
binding.collectMapWrapper.addView(layoutMapBoxBinding.root)
tabCollectBinding = FragmentCollectTabCollectBinding.bind(LayoutInflater.from(context).inflate(
R.layout.fragment_collect_tab_collect,
null,
false
)).apply {
collectSpinnerVehicleParts.onItemSelectedListener = object:OnItemSelectedListener{
private val itemSelectedListener by lazy {
object:OnItemSelectedListener{
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
......@@ -75,11 +53,25 @@ class CollectFragment : BaseMapFragment() {
}
}
tabSettingsBinding = FragmentCollectTabSettingsBinding.bind(LayoutInflater.from(context).inflate(
R.layout.fragment_collect_tab_settings,
null,
false
))
private val binding get() = _binding!!
private val iconCalibrates by lazy {
listOf(tabCollectBinding.vehicleLeftFrontWheel,
tabCollectBinding.vehicleRightFrontWheel,
tabCollectBinding.vehicleLeftBackWheel,
tabCollectBinding.vehicleRightBackWheel,
tabCollectBinding.vehicleGeometricCenter,
tabCollectBinding.vehicleFrontAxleCenter,
tabCollectBinding.vehicleBackAxleCenter)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentCollectBinding.inflate(inflater, container, false)
context?:return binding.root
binding.collectMapWrapper.addView(mapBoxBinding.root)
initTabLayout()
binding.collectTabBtnToHome.setOnClickListener {
findNavController().navigate(R.id.navigation_home)
......@@ -89,6 +81,7 @@ class CollectFragment : BaseMapFragment() {
private fun initTabLayout(){
binding.collectTabContent.addView(tabCollectBinding.root)
tabCollectBinding.collectSpinnerVehicleParts.onItemSelectedListener = itemSelectedListener
binding.collectRadioGroup.setOnCheckedChangeListener { _, checkedId ->
binding.collectTabContent.removeAllViews()
if (checkedId == R.id.collectTabCollect) {
......
......@@ -2,41 +2,36 @@ package com.waytous.anticollision.ui.home
import android.os.Bundle
import android.text.SpannableString
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.viewModels
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import com.blankj.utilcode.util.BarUtils
import com.mapbox.maps.MapView
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.DialogFaultCauseSelectBinding
import com.waytous.anticollision.databinding.FragmentNoVideoHomeBinding
import com.waytous.anticollision.repository.MainRepository
import com.waytous.anticollision.ui.BaseMapFragment
import com.waytous.anticollision.ui.MainViewModel
import com.waytous.anticollision.ui.view.MoreFeaturesPopup
import com.waytous.anticollision.ui.view.ReportStatusPopup
import com.waytous.anticollision.ui.view.WorkStatusEditPopup
import com.waytous.anticollision.databinding.LayoutMapBoxBinding
import com.waytous.anticollision.ui.view.ButtonMorePopup
import com.waytous.anticollision.ui.view.ButtonReportStatusPopup
import com.waytous.anticollision.ui.view.ButtonWorkStatusPopup
import com.waytous.anticollision.utils.setTextSize
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
class HomeNoVideoFragment : BaseMapFragment() {
@AndroidEntryPoint
class HomeNoVideoFragment : Fragment() {
private var _binding: FragmentNoVideoHomeBinding? = null
private val binding get() = _binding!!
private lateinit var mapView: MapView
private var count = 0
private val mapModel: MainViewModel by viewModels {
MainViewModel.MainViewModelFactory(MainRepository(requireContext()))
}
@Inject
lateinit var mapBoxBinding:LayoutMapBoxBinding
@Inject
lateinit var popupMoreFeatures:ButtonMorePopup
@Inject
lateinit var popupWorkStatusEdit:ButtonWorkStatusPopup
@Inject
lateinit var popupReportStatus:ButtonReportStatusPopup
override fun onCreateView(
inflater: LayoutInflater,
......@@ -48,18 +43,17 @@ class HomeNoVideoFragment : BaseMapFragment() {
ViewModelProvider(this)[HomeViewModel::class.java]
_binding = FragmentNoVideoHomeBinding.inflate(inflater, container, false)
context ?: return binding.root
setupMapBox()
binding.noVideoMapWrapper.addView(layoutMapBoxBinding.root)
binding.noVideoMapWrapper.addView(mapBoxBinding.root)
setTodayCarriedNum(18)
setTodayIllegallyNum(1)
binding.workStatusEdit.setOnClickListener {
workStatusEditPopup.showPopupWindow(binding.defaultCurrentWorkStatusLayout)
popupWorkStatusEdit.showPopupWindow(binding.defaultCurrentWorkStatusLayout)
}
binding.defaultToggleMore.setOnClickListener {
moreFeaturesPopup.showPopupWindow(binding.defaultToggleMore)
popupMoreFeatures.showPopupWindow(binding.defaultToggleMore)
}
binding.defaultReportStatus.setOnClickListener {
reportStatusPopup.showPopupWindow(binding.defaultReportStatus)
popupReportStatus.showPopupWindow(binding.defaultReportStatus)
}
return binding.root
}
......@@ -77,7 +71,6 @@ class HomeNoVideoFragment : BaseMapFragment() {
override fun onDestroyView() {
super.onDestroyView()
binding.noVideoMapWrapper.removeView(layoutMapBoxBinding.root)
_binding = null
}
......
......@@ -3,37 +3,42 @@ package com.waytous.anticollision.ui.video
import android.net.Uri
import android.os.Bundle
import android.text.SpannableString
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.AppCompatTextView
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.FragmentVideoHomeBinding
import com.waytous.anticollision.ui.BaseMapFragment
import com.waytous.anticollision.ui.view.MoreFeaturesPopup
import com.waytous.anticollision.ui.view.WorkStatusEditPopup
import com.waytous.anticollision.databinding.LayoutMapBoxBinding
import com.waytous.anticollision.ui.view.ButtonMorePopup
import com.waytous.anticollision.ui.view.ButtonReportStatusPopup
import com.waytous.anticollision.ui.view.ButtonWorkStatusPopup
import com.waytous.anticollision.utils.setTextSize
import dagger.hilt.android.AndroidEntryPoint
import java.io.File
import javax.inject.Inject
class HomeVideoFragment : BaseMapFragment() {
@AndroidEntryPoint
class HomeVideoFragment : Fragment() {
private lateinit var binding: FragmentVideoHomeBinding
@Inject
lateinit var mapBoxBinding: LayoutMapBoxBinding
@Inject
lateinit var popupMoreFeatures:ButtonMorePopup
@Inject
lateinit var popupWorkStatusEdit:ButtonWorkStatusPopup
@Inject
lateinit var popupReportStatus: ButtonReportStatusPopup
private var player1: ExoPlayer? = null
private var player2: ExoPlayer? = null
companion object {
fun newInstance() = HomeVideoFragment()
}
private val viewModel: VideoHomeViewModel by viewModels()
override fun onCreateView(
......@@ -42,32 +47,16 @@ class HomeVideoFragment : BaseMapFragment() {
): View? {
binding = FragmentVideoHomeBinding.inflate(inflater, container, false)
context ?: return binding.root
workStatusEditPopup = WorkStatusEditPopup(context).also {
it.setOutSideDismiss(true)
it.popupGravity = Gravity.TOP or Gravity.CENTER
it.setBackgroundColor(R.color.color_99000000)
}
moreFeaturesPopup = MoreFeaturesPopup(context).also {pupop->
pupop.setOutSideDismiss(true)
pupop.popupGravity = Gravity.TOP or Gravity.CENTER
pupop.maskOffsetY = 20
pupop.setBackgroundColor(R.color.color_99000000)
pupop.contentView.findViewById<AppCompatTextView>(R.id.moreFeatureCollect).setOnClickListener {
findNavController().navigate(R.id.action_navigation_video_Home_to_collectFragment)
pupop.dismiss()
}
}
val templateString = getString(R.string.current_speed, 36)
val spannableString = SpannableString(templateString)
binding.workStatusEdit.setOnClickListener {
workStatusEditPopup.showPopupWindow(binding.currentWorkStatusLayout)
popupWorkStatusEdit.showPopupWindow(binding.currentWorkStatusLayout)
}
binding.speedText.setTextSize(spannableString, templateString)
setupMapBox()
binding.videoMapWrapper.addView(layoutMapBoxBinding.root)
binding.videoMapWrapper.addView(mapBoxBinding.root)
initPlayer()
binding.toggleMore.setOnClickListener {
moreFeaturesPopup.showPopupWindow(it)
popupMoreFeatures.showPopupWindow(it)
}
return binding.root
}
......@@ -94,7 +83,6 @@ class HomeVideoFragment : BaseMapFragment() {
}
override fun onDestroyView() {
binding.videoMapWrapper.removeView(layoutMapBoxBinding.root)
player1?.release()
player2?.release()
super.onDestroyView()
......
package com.waytous.anticollision.ui.view
import android.content.Context
import android.view.Gravity
import androidx.navigation.NavController
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.PopupMoreFeaturesBinding
import razerdp.basepopup.BasePopupWindow
import javax.inject.Inject
class MoreFeaturesPopup(context: Context?) : BasePopupWindow(context) {
class ButtonMorePopup @Inject constructor(context: Context?,val binding: PopupMoreFeaturesBinding) : BasePopupWindow(context) {
var popupMoreFeaturesBinding: PopupMoreFeaturesBinding
init {
contentView = createPopupById(R.layout.popup_more_features)
popupMoreFeaturesBinding = PopupMoreFeaturesBinding.bind(contentView)
contentView = binding.root
setOutSideDismiss(true)
popupGravity = Gravity.TOP or Gravity.CENTER
maskOffsetY = 20
setBackgroundColor(R.color.color_99000000)
}
fun navigationTo(navController: NavController){
popupMoreFeaturesBinding.moreFeatureCollect.setOnClickListener {
binding.moreFeatureCollect.setOnClickListener {
dismiss()
navController.navigate(R.id.collectFragment)
}
......
......@@ -2,16 +2,19 @@ package com.waytous.anticollision.ui.view
import android.app.Dialog
import android.content.Context
import android.view.Gravity
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.PopupReportStatusBinding
import razerdp.basepopup.BasePopupWindow
import javax.inject.Inject
class ReportStatusPopup(context: Context?) : BasePopupWindow(context) {
class ButtonReportStatusPopup @Inject constructor(context: Context?,val binding: PopupReportStatusBinding) : BasePopupWindow(context) {
private lateinit var binding: PopupReportStatusBinding
init {
contentView = createPopupById(R.layout.popup_report_status)
binding = PopupReportStatusBinding.bind(contentView)
contentView = binding.root
setOutSideDismiss(true)
popupGravity = Gravity.TOP or Gravity.CENTER
setBackgroundColor(R.color.color_99000000)
}
fun itemDumping(){
......
package com.waytous.anticollision.ui.view
import android.content.Context
import android.view.Gravity
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.PopupWorkStatusEditBinding
import razerdp.basepopup.BasePopupWindow
import javax.inject.Inject
class WorkStatusEditPopup(context: Context?) : BasePopupWindow(context) {
class ButtonWorkStatusPopup @Inject constructor(context: Context?,val binding:PopupWorkStatusEditBinding) : BasePopupWindow(context) {
init {
contentView = createPopupById(R.layout.popup_work_status_edit)
contentView = binding.root
setOutSideDismiss(true)
popupGravity = Gravity.TOP or Gravity.CENTER
setBackgroundColor(R.color.color_99000000)
}
}
\ No newline at end of file
......@@ -18,7 +18,6 @@ import com.mapbox.maps.extension.style.layers.properties.generated.TextRotationA
import com.mapbox.maps.extension.style.layers.properties.generated.Visibility
import com.mapbox.maps.extension.style.sources.addSource
import com.mapbox.maps.extension.style.sources.generated.geoJsonSource
import com.waytous.anticollision.ui.MainViewModel
const val MY_MAP_BOX_STYLE = "asset://style.json"
......@@ -86,14 +85,14 @@ const val ZOOM = 16.0
* obstacles->stationarea->parkspot->lanenode
* */
fun Style.addRunnableAreaSource(source: String){
LogUtils.dTag("MapBoxExtensions","addRunnableAreaSource")
LogUtils.d("addRunnableAreaSource")
val geoJsonSource = geoJsonSource(RUNNABLE_AREA_SOURCE){
data(source)
}
addSource(geoJsonSource)
}
fun Style.addRunnableAreaLayer(){
LogUtils.dTag("MapBoxExtensions","addRunnableAreaLayer")
LogUtils.d("addRunnableAreaLayer")
val fillLayer = fillLayer(
RUNNABLE_AREA_LAYER,
RUNNABLE_AREA_SOURCE
......@@ -114,14 +113,14 @@ fun Style.addRunnableAreaLayer(){
* staticobjs:静态对象区域
* */
fun Style.addStaticObjectsSource(source: String){
LogUtils.dTag("MapBoxExtensions","addStaticObjectsSource")
LogUtils.d("addStaticObjectsSource")
val geoJsonSource = geoJsonSource(STATIC_OBJECTS_SOURCE) {
data(source)
}
addSource(geoJsonSource)
}
fun Style.addStaticObjectsFillLayer(){
LogUtils.dTag("MapBoxExtensions","addStaticObjectsFillLayer")
LogUtils.d("addStaticObjectsFillLayer")
val fillLayer = fillLayer(
STATIC_OBJECTS_LAYER,
STATIC_OBJECTS_SOURCE
......@@ -138,7 +137,7 @@ fun Style.addStaticObjectsFillLayer(){
}
}
fun Style.addStaticObjectsSymbolLayer(){
LogUtils.dTag("MapBoxExtensions","addStaticObjectsSymbolLayer")
LogUtils.d("addStaticObjectsSymbolLayer")
val symbolLayer = symbolLayer(STATIC_OBJECTS_TEXT_LAYER, STATIC_OBJECTS_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
......@@ -162,14 +161,14 @@ fun Style.addStaticObjectsSymbolLayer(){
* diggingarea:挖掘区域
* */
fun Style.addDiggingWorkAreaSource(source: String){
LogUtils.dTag("MapBoxExtensions","addDiggingWorkAreaSource")
LogUtils.d("addDiggingWorkAreaSource")
val geoJsonSource = geoJsonSource(DIGGING_WORK_AREA_SOURCE) {
data(source)
}
addSource(geoJsonSource)
}
fun Style.addDiggingWorkAreaFillLayer(){
LogUtils.dTag("MapBoxExtensions","addStaticObjectsFillLayer")
LogUtils.d("addStaticObjectsFillLayer")
val fillLayer = fillLayer(
DIGGING_WORK_AREA_LAYER,
DIGGING_WORK_AREA_SOURCE
......@@ -186,7 +185,7 @@ fun Style.addDiggingWorkAreaFillLayer(){
}
}
fun Style.addDiggingWorkAreaSymbolLayer(){
LogUtils.dTag("MapBoxExtensions","addDiggingWorkAreaSymbolLayer")
LogUtils.d("addDiggingWorkAreaSymbolLayer")
val symbolLayer = symbolLayer(DIGGING_WORK_AREA_TEXT_LAYER, DIGGING_WORK_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
......@@ -210,14 +209,14 @@ fun Style.addDiggingWorkAreaSymbolLayer(){
* dumparea:排土区域
* */
fun Style.addDumpAreaSource(source: String){
LogUtils.dTag("MapBoxExtensions","addDumpAreaSource")
LogUtils.d("addDumpAreaSource")
val geoJsonSource = geoJsonSource(DUMP_AREA_SOURCE) {
data(source)
}
addSource(geoJsonSource)
}
fun Style.addDumpAreaFillLayer(){
LogUtils.dTag("MapBoxExtensions","addDumpAreaFillLayer")
LogUtils.d("addDumpAreaFillLayer")
val fillLayer = fillLayer(
DUMP_AREA_LAYER,
DUMP_AREA_SOURCE
......@@ -234,7 +233,7 @@ fun Style.addDumpAreaFillLayer(){
}
}
fun Style.addDumpAreaSymbolLayer(){
LogUtils.dTag("MapBoxExtensions","addDumpAreaSymbolLayer")
LogUtils.d("addDumpAreaSymbolLayer")
val symbolLayer = symbolLayer(DUMP_AREA_TEXT_LAYER, DUMP_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
......@@ -258,14 +257,14 @@ fun Style.addDumpAreaSymbolLayer(){
* barricade:挡墙
* */
fun Style.addBarricadeSource(source: String){
LogUtils.dTag("MapBoxExtensions","addBarricadeSource")
LogUtils.d("addBarricadeSource")
val geoJsonSource = geoJsonSource(BARRICADE_SOURCE) {
data(source)
}
addSource(geoJsonSource)
}
fun Style.addBarricadeLineLayer(){
LogUtils.dTag("MapBoxExtensions","addBarricadeLineLayer")
LogUtils.d("addBarricadeLineLayer")
val lineLayer = lineLayer(
BARRICADE_LAYER,
BARRICADE_SOURCE
......@@ -286,14 +285,14 @@ fun Style.addBarricadeLineLayer(){
* electronicFence:电子围栏
* */
fun Style.addElectronicFenceSource(source: String){
LogUtils.dTag("MapBoxExtensions","addElectronicFenceSource")
LogUtils.d("addElectronicFenceSource")
val geoJsonSource = geoJsonSource(ELECTRONIC_FENCE_SOURCE) {
data(source)
}
addSource(geoJsonSource)
}
fun Style.addElectronicFenceFillLayer(){
LogUtils.dTag("MapBoxExtensions","addElectronicFenceFillLayer")
LogUtils.d("addElectronicFenceFillLayer")
val fillLayer = fillLayer(
ELECTRONIC_FENCE_LAYER,
ELECTRONIC_FENCE_SOURCE
......@@ -310,7 +309,7 @@ fun Style.addElectronicFenceFillLayer(){
}
}
fun Style.addElectronicFenceSymbolLayer(){
LogUtils.dTag("MapBoxExtensions","addElectronicFenceSymbolLayer")
LogUtils.d("addElectronicFenceSymbolLayer")
val symbolLayer = symbolLayer(ELECTRONIC_FENCE_TEXT_LAYER, ELECTRONIC_FENCE_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
......@@ -334,14 +333,14 @@ fun Style.addElectronicFenceSymbolLayer(){
* wetArea:湿滑区
* */
fun Style.addWetAreaSource(source: String){
LogUtils.dTag("MapBoxExtensions","addWetAreaSource")
LogUtils.d("addWetAreaSource")
val geoJsonSource = geoJsonSource(WET_AREA_SOURCE) {
data(source)
}
addSource(geoJsonSource)
}
fun Style.addWetAreaFillLayer(){
LogUtils.dTag("MapBoxExtensions","addWetAreaFillLayer")
LogUtils.d("addWetAreaFillLayer")
val fillLayer = fillLayer(
WET_AREA_LAYER,
WET_AREA_SOURCE
......@@ -358,7 +357,7 @@ fun Style.addWetAreaFillLayer(){
}
}
fun Style.addWetAreaSymbolLayer(){
LogUtils.dTag("MapBoxExtensions","addWetAreaSymbolLayer")
LogUtils.d("addWetAreaSymbolLayer")
val symbolLayer = symbolLayer(WET_AREA_TEXT_LAYER, WET_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
......@@ -382,14 +381,14 @@ fun Style.addWetAreaSymbolLayer(){
* lanelayer:整个矿山边界路线
* */
fun Style.addLaneSource(source: String){
LogUtils.dTag("MapBoxExtensions","addLaneSource")
LogUtils.d("addLaneSource")
val geoJsonSource = geoJsonSource(LANE_SOURCE){
data(source)
}
addSource(geoJsonSource)
}
fun Style.addLaneLayer(){
LogUtils.dTag("MapBoxExtensions","addLaneLayer")
LogUtils.d("addLaneLayer")
val lineLayer = lineLayer(
LANE_LAYER,
LANE_SOURCE
......@@ -410,14 +409,14 @@ fun Style.addLaneLayer(){
* obstacles:障碍物
* */
fun Style.addObstaclesSource(source: String){
LogUtils.dTag("MapBoxExtensions","addObstaclesSource")
LogUtils.d("addObstaclesSource")
val geoJsonSource = geoJsonSource(OBSTACLES_SOURCE) {
url(source)
}
addSource(geoJsonSource)
}
fun Style.addObstaclesFillLayer(){
LogUtils.dTag("MapBoxExtensions","addObstaclesFillLayer")
LogUtils.d("addObstaclesFillLayer")
val fillLayer = fillLayer(
OBSTACLES_LAYER,
OBSTACLES_SOURCE
......@@ -433,7 +432,7 @@ fun Style.addObstaclesFillLayer(){
}
}
fun Style.addObstaclesSymbolLayer(){
LogUtils.dTag("MapBoxExtensions","addObstaclesSymbolLayer")
LogUtils.d("addObstaclesSymbolLayer")
val symbolLayer = symbolLayer(OBSTACLES_TEXT_LAYER, OBSTACLES_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
......@@ -457,14 +456,14 @@ fun Style.addObstaclesSymbolLayer(){
* stationarea:静态物体
* */
fun Style.addStationAreaSource(source: String){
LogUtils.dTag("MapBoxExtensions","addStationAreaSource")
LogUtils.d("addStationAreaSource")
val geoJsonSource = geoJsonSource(STATION_AREA_SOURCE) {
data(source)
}
addSource(geoJsonSource)
}
fun Style.addStationAreaFillLayer(){
LogUtils.dTag("MapBoxExtensions","addStationAreaFillLayer")
LogUtils.d("addStationAreaFillLayer")
val fillLayer = fillLayer(
STATION_AREA_LAYER,
STATION_AREA_SOURCE
......@@ -480,7 +479,7 @@ fun Style.addStationAreaFillLayer(){
}
}
fun Style.addStationAreaSymbolLayer(){
LogUtils.dTag("MapBoxExtensions","addStationAreaSymbolLayer")
LogUtils.d("addStationAreaSymbolLayer")
val symbolLayer = symbolLayer(STATION_AREA_TEXT_LAYER, STATION_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
......@@ -503,14 +502,14 @@ fun Style.addStationAreaSymbolLayer(){
* parkspot:停车区
* */
fun Style.addParkSpotSource(source: String){
LogUtils.dTag("MapBoxExtensions","addParkSpotSource")
LogUtils.d("addParkSpotSource")
val geoJsonSource = geoJsonSource(PARK_SPOT_SOURCE) {
data(source)
}
addSource(geoJsonSource)
}
fun Style.addParkSpotFillLayer(){
LogUtils.dTag("MapBoxExtensions","addParkSpotFillLayer")
LogUtils.d("addParkSpotFillLayer")
val fillLayer = fillLayer(
PARK_SPOT_LAYER,
PARK_SPOT_SOURCE
......@@ -526,7 +525,7 @@ fun Style.addParkSpotFillLayer(){
}
}
fun Style.addParkSpotSymbolLayer(){
LogUtils.dTag("MapBoxExtensions","addParkSpotSymbolLayer")
LogUtils.d("addParkSpotSymbolLayer")
val symbolLayer = symbolLayer(PARK_SPOT_TEXT_LAYER, PARK_SPOT_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
......@@ -550,14 +549,14 @@ fun Style.addParkSpotSymbolLayer(){
* lanenode:道路节点
* */
fun Style.addLaneNodeSource(source: String){
LogUtils.dTag("MapBoxExtensions","addLaneNodeSource")
LogUtils.d("addLaneNodeSource")
val geoJsonSource = geoJsonSource(LANE_NODE_SOURCE) {
data(source)
}
addSource(geoJsonSource)
}
fun Style.addLaneNodeCircleLayer(){
LogUtils.dTag("MapBoxExtensions","addLaneNodeCircleLayer")
LogUtils.d("addLaneNodeCircleLayer")
val circleLayer = circleLayer(
LANE_NODE_LAYER,
LANE_NODE_SOURCE
......@@ -569,7 +568,7 @@ fun Style.addLaneNodeCircleLayer(){
addLayer(circleLayer)
}
fun Style.addLaneNodeSymbolLayer(){
LogUtils.dTag("MapBoxExtensions","addLaneNodeSymbolLayer")
LogUtils.d("addLaneNodeSymbolLayer")
val symbolLayer = symbolLayer(LANE_NODE_TEXT_LAYER, LANE_NODE_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
......@@ -585,14 +584,14 @@ fun Style.addLaneNodeSymbolLayer(){
addLayer(symbolLayer)
}
fun Style.addTruckPathSource(){
LogUtils.dTag("MapBoxExtensions","addTruckPathSource")
LogUtils.d("addTruckPathSource")
val source = geoJsonSource(TRUCK_PATH_SOURCE) {
data("{ \"type\": \"FeatureCollection\", \"features\":[]}")
}
addSource(source)
}
fun Style.addTruckPathLineLayer(){
LogUtils.dTag("MapBoxExtensions","addTruckPathLineLayer")
LogUtils.d("addTruckPathLineLayer")
val lineLayer = lineLayer(
TRUCK_PATH_LAYER,
TRUCK_PATH_SOURCE
......@@ -608,8 +607,9 @@ fun Style.addTruckPathLineLayer(){
}
fun Style.adjustLayerOrder(){
LogUtils.dTag("MapBoxExtensions","adjustLayerOrder")
moveStyleLayer(TRUCK_PATH_LAYER,null)
LogUtils.d("adjustLayerOrder")
moveStyleLayer(TRUCK_PATH_LAYER,LayerPosition(null,
null,null))
moveStyleLayer(LANE_NODE_LAYER,LayerPosition(null,
TRUCK_PATH_LAYER,null))
moveStyleLayer(LANE_NODE_TEXT_LAYER,LayerPosition(null,
......
package com.waytous.anticollision.utils
import android.content.Context
import android.content.SharedPreferences
import com.waytous.anticollision.AntiCollisionApp
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class PreferenceDelegate<T>(private val name: String, private val default: T, private val prefName: String = "settings")
: ReadWriteProperty<Any?, T> {
private val prefs: SharedPreferences =
AntiCollisionApp.instance().applicationContext.getSharedPreferences(prefName, Context.MODE_PRIVATE)
@Synchronized
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
println("setValue from delegate")
return getPreference(key = name)
}
@Synchronized
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
println("setValue from delegate")
putPreference(key = name, value = value)
}
private fun getPreference(key: String): T {
return when (default) {
is String -> prefs.getString(key, default)
is Long -> prefs.getLong(key, default)
is Boolean -> prefs.getBoolean(key, default)
is Float -> prefs.getFloat(key, default)
is Int -> prefs.getInt(key, default)
else -> throw IllegalArgumentException("Unknown Type.")
} as T
}
private fun putPreference(key: String, value: T) = with(prefs.edit()) {
when (value) {
is String -> putString(key, value)
is Long -> putLong(key, value)
is Boolean -> putBoolean(key, value)
is Float -> putFloat(key, value)
is Int -> putInt(key, value)
else -> throw IllegalArgumentException("Unknown Type.")
}
}.apply()
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment