Merge branch 'master' into 'master'
Master See merge request qiji4215/OneMapQS!2
This commit is contained in:
+21
-12
@@ -4,6 +4,7 @@ plugins {
|
||||
id 'kotlin-kapt'
|
||||
id 'com.google.dagger.hilt.android'
|
||||
id 'realm-android'
|
||||
id 'kotlin-parcelize' // 序列化
|
||||
}
|
||||
android {
|
||||
namespace 'com.navinfo.omqs'
|
||||
@@ -11,7 +12,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.navinfo.omqs"
|
||||
minSdk 24
|
||||
minSdk 26
|
||||
targetSdk 33
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
@@ -36,17 +37,16 @@ android {
|
||||
viewBinding true
|
||||
dataBinding true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation project(':collect-library')
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.5.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
|
||||
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
@@ -55,17 +55,26 @@ dependencies {
|
||||
// 文件管理 https://github.com/K1rakishou/Fuck-Storage-Access-Framework
|
||||
implementation 'com.github.K1rakishou:Fuck-Storage-Access-Framework:v1.1.3'
|
||||
// Android工具类库 https://blankj.com/2016/07/31/android-utils-code/
|
||||
implementation 'com.blankj:utilcodex:1.30.1'
|
||||
implementation 'com.blankj:utilcodex:1.31.1'
|
||||
//依赖注入
|
||||
//hilt
|
||||
implementation "com.google.dagger:hilt-android:2.44"
|
||||
kapt "com.google.dagger:hilt-compiler:2.44"
|
||||
implementation 'com.google.dagger:hilt-android:2.45'
|
||||
kapt 'com.google.dagger:hilt-compiler:2.45'
|
||||
|
||||
// Retrofit 网络请求相关
|
||||
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
||||
implementation("com.squareup.okhttp3:okhttp:4.9.0")
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
|
||||
implementation('com.squareup.okhttp3:okhttp:5.0.0-alpha.11')
|
||||
implementation('com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.11')
|
||||
|
||||
kapt 'android.arch.persistence.room:compiler:1.1.1'// compiler 需要用 room 的
|
||||
kapt "androidx.room:room-compiler:2.5.1"
|
||||
kapt "androidx.room:room-ktx:2.5.1"
|
||||
|
||||
//读取excel word等文件
|
||||
implementation 'org.apache.poi:poi:5.2.3'
|
||||
implementation 'org.apache.poi:poi-ooxml:5.2.3'
|
||||
|
||||
}
|
||||
//允许引用生成的代码
|
||||
kapt {
|
||||
|
||||
@@ -2,9 +2,11 @@ package com.navinfo.omqs
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
import com.navinfo.omqs.db.MyRealmModule
|
||||
import com.navinfo.omqs.tools.FileManager
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmConfiguration
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
@@ -12,7 +14,19 @@ import java.io.File
|
||||
@HiltAndroidApp
|
||||
class OMQSApplication : Application() {
|
||||
override fun onCreate() {
|
||||
FileManager.initRootDir(this)
|
||||
super.onCreate()
|
||||
FileManager.initRootDir(this)
|
||||
Realm.init(this)
|
||||
val password = "password".encodeToByteArray().copyInto(ByteArray(64))
|
||||
// 1110000011000010111001101110011011101110110111101110010011001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
// Log.d("", "密码是: ${BigInteger(1, password).toString(2).padStart(64, '0')}")
|
||||
val config = RealmConfiguration.Builder()
|
||||
.directory(File(Constant.DATA_PATH))
|
||||
.name("HDData")
|
||||
.modules(Realm.getDefaultModule(), MyRealmModule())
|
||||
.schemaVersion(1)
|
||||
// .encryptionKey(password)
|
||||
.build()
|
||||
Realm.setDefaultConfiguration(config)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.navinfo.omqs.bean
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
|
||||
@Entity(tableName = "OfflineMapCity")
|
||||
@Parcelize
|
||||
data class OfflineMapCityBean @JvmOverloads constructor(
|
||||
@PrimaryKey
|
||||
var id: String = "",
|
||||
var fileName: String = "",
|
||||
var name: String = "",
|
||||
var url: String = "",
|
||||
var version: Long = 0L,
|
||||
var fileSize: Long = 0L,
|
||||
var currentSize: Long = 0L,
|
||||
var status: Int = NONE
|
||||
) : Parcelable {
|
||||
|
||||
companion object Status {
|
||||
const val NONE = 0 //无状态
|
||||
const val WAITING = 1 //等待中
|
||||
const val LOADING = 2 //下载中
|
||||
const val PAUSE = 3 //暂停
|
||||
const val ERROR = 4 //错误
|
||||
const val DONE = 5 //完成
|
||||
const val UPDATE = 6 //有新版本要更新
|
||||
}
|
||||
|
||||
// // status的转换对象
|
||||
// var statusEnum: StatusEnum
|
||||
// get() {
|
||||
// return try {
|
||||
// StatusEnum.values().find { it.status == status }!!
|
||||
// } catch (e: IllegalArgumentException) {
|
||||
// StatusEnum.NONE
|
||||
// }
|
||||
// }
|
||||
// set(value) {
|
||||
// status = value.status
|
||||
// }
|
||||
|
||||
fun getFileSizeText(): String {
|
||||
return if (fileSize < 1024.0)
|
||||
"$fileSize B"
|
||||
else if (fileSize < 1048576.0)
|
||||
"%.2f K".format(fileSize / 1024.0)
|
||||
else if (fileSize < 1073741824.0)
|
||||
"%.2f M".format(fileSize / 1048576.0)
|
||||
else
|
||||
"%.2f M".format(fileSize / 1073741824.0)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.navinfo.omqs.bean
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Entity(tableName = "ScProblemType")
|
||||
@Parcelize
|
||||
data class ScProblemTypeBean(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0,
|
||||
/**
|
||||
* 问题分类
|
||||
*/
|
||||
@ColumnInfo("CLASS_TYPE")
|
||||
var classType: String = "",
|
||||
/**
|
||||
* 问题类型
|
||||
*/
|
||||
@ColumnInfo("TYPE")
|
||||
var problemType: String = "",
|
||||
/**
|
||||
* 问题现象
|
||||
*/
|
||||
@ColumnInfo("PHENOMENON")
|
||||
var phenomenon: String = ""
|
||||
|
||||
) : Parcelable
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.navinfo.omqs.bean
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Entity(tableName = "ScRootCauseAnalysis")
|
||||
@Parcelize
|
||||
data class ScRootCauseAnalysisBean(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0,
|
||||
/**
|
||||
* 问题环节
|
||||
*/
|
||||
@ColumnInfo("PROBLEM_LINK")
|
||||
var problemLink: String = "",
|
||||
/**
|
||||
* 问题原因
|
||||
*/
|
||||
@ColumnInfo("PROBLEM_CAUSE")
|
||||
var problemCause: String = "",
|
||||
) : Parcelable
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.navinfo.omqs.db
|
||||
|
||||
import com.navinfo.collect.library.data.entity.QsRecordBean
|
||||
|
||||
@io.realm.annotations.RealmModule(classes = [QsRecordBean::class])
|
||||
class MyRealmModule {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.navinfo.omqs.db
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
import com.navinfo.omqs.bean.ScProblemTypeBean
|
||||
import com.navinfo.omqs.bean.ScRootCauseAnalysisBean
|
||||
import com.navinfo.omqs.db.dao.OfflineMapDao
|
||||
import com.navinfo.omqs.db.dao.ScProblemTypeDao
|
||||
import com.navinfo.omqs.db.dao.ScRootCauseAnalysisDao
|
||||
|
||||
@Database(
|
||||
entities = [OfflineMapCityBean::class, ScProblemTypeBean::class, ScRootCauseAnalysisBean::class],
|
||||
version = 1,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class RoomAppDatabase : RoomDatabase() {
|
||||
abstract fun getOfflineMapDao(): OfflineMapDao
|
||||
abstract fun getScProblemTypeDao(): ScProblemTypeDao
|
||||
abstract fun getScRootCauseAnalysisDao(): ScRootCauseAnalysisDao
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.navinfo.omqs.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
|
||||
@Dao
|
||||
interface OfflineMapDao {
|
||||
|
||||
@Insert
|
||||
suspend fun insert(message: OfflineMapCityBean): Long
|
||||
|
||||
@Update(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun update(message: OfflineMapCityBean)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertOrUpdate(list: List<OfflineMapCityBean>)
|
||||
|
||||
@Query("select * from OfflineMapCity order by id")
|
||||
suspend fun getOfflineMapList(): List<OfflineMapCityBean>
|
||||
|
||||
@Query("select * from OfflineMapCity where status != 0 order by id")
|
||||
suspend fun getOfflineMapListWithOutNone(): List<OfflineMapCityBean>
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.navinfo.omqs.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import com.navinfo.omqs.bean.ScProblemTypeBean
|
||||
|
||||
|
||||
@Dao
|
||||
interface ScProblemTypeDao {
|
||||
// @Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
// suspend fun insert(bean: ScProblemTypeBean): Long
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertList(list: List<ScProblemTypeBean>)
|
||||
|
||||
|
||||
@Query("delete from ScProblemType")
|
||||
suspend fun deleteAll()
|
||||
|
||||
/**
|
||||
* 更新整个数据库表,由于没有
|
||||
*/
|
||||
@Transaction
|
||||
suspend fun insertOrUpdateList(list: List<ScProblemTypeBean>) {
|
||||
//先删除
|
||||
deleteAll()
|
||||
//后插入
|
||||
insertList(list)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取问题分类,并去重
|
||||
*/
|
||||
@Query("select DISTINCT CLASS_TYPE from ScProblemType order by CLASS_TYPE")
|
||||
suspend fun findClassTypeList(): List<String>?
|
||||
|
||||
/**
|
||||
* 获取问题类型,并去重
|
||||
*/
|
||||
@Query("select * from ScProblemType where CLASS_TYPE=:type order by TYPE")
|
||||
suspend fun findProblemTypeList(type: String): List<ScProblemTypeBean>?
|
||||
|
||||
// /**
|
||||
// *
|
||||
// */
|
||||
// @Query("select PHENOMENON from ScProblemType where CLASS_TYPE=:classType and TYPE=:type order by PHENOMENON")
|
||||
// suspend fun getPhenomenonList(classType: String, type: String): List<String>
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.navinfo.omqs.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import com.navinfo.omqs.bean.ScRootCauseAnalysisBean
|
||||
|
||||
|
||||
@Dao
|
||||
interface ScRootCauseAnalysisDao {
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertList(list: List<ScRootCauseAnalysisBean>)
|
||||
|
||||
|
||||
@Query("delete from ScRootCauseAnalysis")
|
||||
suspend fun deleteAll()
|
||||
|
||||
@Transaction
|
||||
suspend fun insertOrUpdateList(list: List<ScRootCauseAnalysisBean>) {
|
||||
//先删除
|
||||
deleteAll()
|
||||
//后插入
|
||||
insertList(list)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取问题环节数据
|
||||
*/
|
||||
@Query("select * from ScRootCauseAnalysis order by PROBLEM_LINK")
|
||||
suspend fun findAllData(): List<ScRootCauseAnalysisBean>?
|
||||
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
package com.navinfo.omqs.hilt
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.room.Room
|
||||
import com.google.gson.Gson
|
||||
import com.navinfo.omqs.Constant
|
||||
import com.navinfo.omqs.OMQSApplication
|
||||
import com.navinfo.omqs.db.RoomAppDatabase
|
||||
import com.navinfo.omqs.http.RetrofitNetworkServiceAPI
|
||||
import com.navinfo.omqs.tools.RealmCoroutineScope
|
||||
import com.tencent.wcdb.database.SQLiteCipherSpec
|
||||
import com.tencent.wcdb.room.db.WCDBOpenHelperFactory
|
||||
import dagger.Lazy
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
@@ -95,12 +99,41 @@ class GlobalModule {
|
||||
return retrofit.create(RetrofitNetworkServiceAPI::class.java)
|
||||
}
|
||||
|
||||
/**
|
||||
* realm 注册
|
||||
*/
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRealmService(context: Application): RealmCoroutineScope {
|
||||
return RealmCoroutineScope(context)
|
||||
@Provides
|
||||
fun provideDatabase(context: Application): RoomAppDatabase {
|
||||
val DB_PASSWORD = "123456";
|
||||
val cipherSpec = SQLiteCipherSpec()
|
||||
.setPageSize(1024)
|
||||
.setSQLCipherVersion(3)
|
||||
val factory = WCDBOpenHelperFactory()
|
||||
// .passphrase(DB_PASSWORD.toByteArray()) // passphrase to the database, remove this line for plain-text
|
||||
.cipherSpec(cipherSpec) // cipher to use, remove for default settings
|
||||
.writeAheadLoggingEnabled(true) // enable WAL mode, remove if not needed
|
||||
.asyncCheckpointEnabled(true); // enable asynchronous checkpoint, remove if not needed
|
||||
|
||||
return Room.databaseBuilder(
|
||||
context,
|
||||
RoomAppDatabase::class.java,
|
||||
"${Constant.DATA_PATH}/omqs.db"
|
||||
)
|
||||
|
||||
// [WCDB] Specify open helper to use WCDB database implementation instead
|
||||
// of the Android framework.
|
||||
.openHelperFactory(factory)
|
||||
|
||||
// Wipes and rebuilds instead of migrating if no Migration object.
|
||||
// Migration is not part of this codelab.
|
||||
// .fallbackToDestructiveMigration().addCallback(sRoomDatabaseCallback)
|
||||
.build();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * realm 注册
|
||||
// */
|
||||
// @Provides
|
||||
// @Singleton
|
||||
// fun provideRealmService(context: Application): RealmCoroutineScope {
|
||||
// return RealmCoroutineScope(context)
|
||||
// }
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.navinfo.omqs.hilt
|
||||
|
||||
import com.navinfo.collect.library.map.NIMapController
|
||||
import com.navinfo.omqs.db.RoomAppDatabase
|
||||
import com.navinfo.omqs.http.RetrofitNetworkServiceAPI
|
||||
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
|
||||
import com.navinfo.omqs.tools.RealmCoroutineScope
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
@@ -28,12 +28,14 @@ class MainActivityModule {
|
||||
@Provides
|
||||
fun providesOfflineMapDownloadManager(
|
||||
networkServiceAPI: RetrofitNetworkServiceAPI,
|
||||
realmManager: RealmCoroutineScope
|
||||
roomAppDatabase: RoomAppDatabase,
|
||||
mapController: NIMapController
|
||||
): OfflineMapDownloadManager =
|
||||
OfflineMapDownloadManager(networkServiceAPI, realmManager)
|
||||
OfflineMapDownloadManager(networkServiceAPI, roomAppDatabase, mapController)
|
||||
|
||||
/**
|
||||
* 实验失败,这样创建,viewmodel不会在activity销毁的时候同时销毁
|
||||
* 4-14:因为没有传入activity的 owner,无法检测生命周期,
|
||||
*/
|
||||
// @ActivityRetainedScoped
|
||||
// @Provides
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.navinfo.omqs.http
|
||||
|
||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.navinfo.omqs.http
|
||||
|
||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.navinfo.omqs.http
|
||||
|
||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.GET
|
||||
|
||||
+6
-3
@@ -2,16 +2,19 @@ package com.navinfo.omqs.http.offlinemapdownload
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.Observer
|
||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
||||
import com.navinfo.collect.library.map.NIMapController
|
||||
import com.navinfo.omqs.db.RoomAppDatabase
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
import com.navinfo.omqs.http.RetrofitNetworkServiceAPI
|
||||
import com.navinfo.omqs.tools.RealmCoroutineScope
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
* 管理离线地图下载
|
||||
*/
|
||||
class OfflineMapDownloadManager(
|
||||
val netApi: RetrofitNetworkServiceAPI, val realmManager: RealmCoroutineScope
|
||||
val netApi: RetrofitNetworkServiceAPI,
|
||||
val roomDatabase: RoomAppDatabase,
|
||||
val mapController: NIMapController
|
||||
) {
|
||||
/**
|
||||
* 最多同时下载数量
|
||||
|
||||
+15
-11
@@ -4,8 +4,8 @@ import android.util.Log
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
||||
import com.navinfo.omqs.Constant
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
@@ -32,8 +32,8 @@ class OfflineMapDownloadScope(
|
||||
/**
|
||||
* 管理观察者,同时只有一个就行了
|
||||
*/
|
||||
// private var observer: Observer<OfflineMapCityBean>? = null
|
||||
private var lifecycleOwner: LifecycleOwner? = null
|
||||
private val observer = Observer<Any> {}
|
||||
// private var lifecycleOwner: LifecycleOwner? = null
|
||||
|
||||
/**
|
||||
*通知UI更新
|
||||
@@ -89,10 +89,10 @@ class OfflineMapDownloadScope(
|
||||
if (cityBean.status != status || status == OfflineMapCityBean.LOADING) {
|
||||
cityBean.status = status
|
||||
downloadData.postValue(cityBean)
|
||||
|
||||
downloadManager.realmManager.launch {
|
||||
downloadManager.realmManager.insertOrUpdate(cityBean)
|
||||
launch(Dispatchers.IO) {
|
||||
downloadManager.roomDatabase.getOfflineMapDao().update(cityBean)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ class OfflineMapDownloadScope(
|
||||
*/
|
||||
fun observer(owner: LifecycleOwner, ob: Observer<OfflineMapCityBean>) {
|
||||
removeObserver()
|
||||
this.lifecycleOwner = owner
|
||||
// this.lifecycleOwner = owner
|
||||
downloadData.observe(owner, ob)
|
||||
}
|
||||
|
||||
@@ -156,6 +156,9 @@ class OfflineMapDownloadScope(
|
||||
fileTemp.renameTo(File("${Constant.OFFLINE_MAP_PATH}${cityBean.fileName}"))
|
||||
Log.e("jingo", "文件下载完成 修改文件 $res")
|
||||
change(OfflineMapCityBean.DONE)
|
||||
withContext(Dispatchers.Main) {
|
||||
downloadManager.mapController.layerManagerHandler.loadBaseMap()
|
||||
}
|
||||
} else {
|
||||
change(OfflineMapCityBean.PAUSE)
|
||||
}
|
||||
@@ -168,9 +171,10 @@ class OfflineMapDownloadScope(
|
||||
}
|
||||
|
||||
fun removeObserver() {
|
||||
lifecycleOwner?.let {
|
||||
downloadData.removeObservers(it)
|
||||
null
|
||||
}
|
||||
downloadData.observeForever(observer)
|
||||
// lifecycleOwner?.let {
|
||||
downloadData.removeObserver(observer)
|
||||
// null
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
package com.navinfo.omqs.tools
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
||||
import com.navinfo.omqs.Constant
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
import java.io.File
|
||||
|
||||
class FileManager {
|
||||
|
||||
@@ -1,57 +1,47 @@
|
||||
package com.navinfo.omqs.tools
|
||||
|
||||
import android.app.Application
|
||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
||||
import com.navinfo.omqs.Constant
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmConfiguration
|
||||
import io.realm.RealmModel
|
||||
import io.realm.Sort
|
||||
import io.realm.kotlin.where
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.newSingleThreadContext
|
||||
import java.io.File
|
||||
|
||||
class RealmCoroutineScope(context: Application) :
|
||||
CoroutineScope by CoroutineScope(newSingleThreadContext("RealmThread")) {
|
||||
lateinit var realm: Realm
|
||||
|
||||
init {
|
||||
launch {
|
||||
Realm.init(context)
|
||||
val password = "password".encodeToByteArray().copyInto(ByteArray(64))
|
||||
// 1110000011000010111001101110011011101110110111101110010011001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
// Log.d("", "密码是: ${BigInteger(1, password).toString(2).padStart(64, '0')}")
|
||||
val config = RealmConfiguration.Builder()
|
||||
.directory(File(Constant.DATA_PATH))
|
||||
.name("HDData")
|
||||
// .encryptionKey(password)
|
||||
.build()
|
||||
Realm.setDefaultConfiguration(config)
|
||||
realm = Realm.getDefaultInstance()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getOfflineCityList(): List<OfflineMapCityBean> {
|
||||
var list: List<OfflineMapCityBean> = mutableListOf()
|
||||
realm.executeTransaction {
|
||||
val objects = realm.where<OfflineMapCityBean>().findAll().sort("id", Sort.ASCENDING)
|
||||
list = realm.copyFromRealm(objects)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
suspend fun insertOrUpdate(objects: Collection<RealmModel?>?) {
|
||||
realm.executeTransaction {
|
||||
realm.insertOrUpdate(objects)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun insertOrUpdate(realmModel: RealmModel?) {
|
||||
realm.executeTransaction {
|
||||
realm.insertOrUpdate(realmModel)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//package com.navinfo.omqs.tools
|
||||
//
|
||||
//import android.app.Application
|
||||
//import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
||||
//import com.navinfo.omqs.Constant
|
||||
//import io.realm.Realm
|
||||
//import io.realm.RealmConfiguration
|
||||
//import io.realm.RealmModel
|
||||
//import io.realm.Sort
|
||||
//import io.realm.kotlin.where
|
||||
//import kotlinx.coroutines.CoroutineScope
|
||||
//import kotlinx.coroutines.launch
|
||||
//import kotlinx.coroutines.newSingleThreadContext
|
||||
//import java.io.File
|
||||
//
|
||||
//class RealmCoroutineScope(context: Application) :
|
||||
// CoroutineScope by CoroutineScope(newSingleThreadContext("RealmThread")) {
|
||||
// lateinit var realm: Realm
|
||||
//
|
||||
// init {
|
||||
// launch {
|
||||
// realm = Realm.getDefaultInstance()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// suspend fun getOfflineCityList(): List<OfflineMapCityBean> {
|
||||
// var list: List<OfflineMapCityBean> = mutableListOf()
|
||||
// realm.executeTransaction {
|
||||
// val objects = realm.where<OfflineMapCityBean>().findAll().sort("id", Sort.ASCENDING)
|
||||
// list = realm.copyFromRealm(objects)
|
||||
// }
|
||||
// return list
|
||||
// }
|
||||
//
|
||||
// suspend fun insertOrUpdate(objects: Collection<RealmModel?>?) {
|
||||
// realm.executeTransaction {
|
||||
// realm.insertOrUpdate(objects)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// suspend fun insertOrUpdate(realmModel: RealmModel?) {
|
||||
// realm.executeTransaction {
|
||||
// realm.insertOrUpdate(realmModel)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
@@ -1,84 +0,0 @@
|
||||
package com.navinfo.omqs.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import com.github.k1rakishou.fsaf.FileChooser
|
||||
import com.github.k1rakishou.fsaf.callback.FSAFActivityCallbacks
|
||||
import com.navinfo.omqs.databinding.ActivityMainBinding
|
||||
import com.navinfo.omqs.ui.activity.PermissionsActivity
|
||||
|
||||
class MainActivity : PermissionsActivity(), FSAFActivityCallbacks {
|
||||
|
||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private val fileChooser by lazy { FileChooser(this@MainActivity) }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
// val navController = findNavController(R.id.nav_host_fragment_content_main)
|
||||
// appBarConfiguration = AppBarConfiguration(navController.graph)
|
||||
// setupActionBarWithNavController(navController, appBarConfiguration)
|
||||
|
||||
fileChooser.setCallbacks(this@MainActivity)
|
||||
// binding.fab.setOnClickListener { view ->
|
||||
// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||
// .setAnchorView(R.id.fab)
|
||||
// .setAction("Action", null).show()
|
||||
// // 开始数据导入功能
|
||||
// fileChooser.openChooseFileDialog(object: FileChooserCallback() {
|
||||
// override fun onCancel(reason: String) {
|
||||
// }
|
||||
//
|
||||
// override fun onResult(uri: Uri) {
|
||||
// val file = UriUtils.uri2File(uri)
|
||||
// Snackbar.make(view, "文件大小为:${file.length()}", Snackbar.LENGTH_LONG)
|
||||
// .show()
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
}
|
||||
|
||||
override fun onPermissionsGranted() {
|
||||
}
|
||||
|
||||
override fun onPermissionsDenied() {
|
||||
}
|
||||
|
||||
// override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
// // Inflate the menu; this adds items to the action bar if it is present.
|
||||
// menuInflater.inflate(R.menu.menu_main, menu)
|
||||
// return true
|
||||
// }
|
||||
|
||||
// override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
// // Handle action bar item clicks here. The action bar will
|
||||
// // automatically handle clicks on the Home/Up button, so long
|
||||
// // as you specify a parent activity in AndroidManifest.xml.
|
||||
// return when (item.itemId) {
|
||||
// R.id.action_settings -> true
|
||||
// else -> super.onOptionsItemSelected(item)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun onSupportNavigateUp(): Boolean {
|
||||
// val navController = findNavController(R.id.nav_host_fragment_content_main)
|
||||
// return navController.navigateUp(appBarConfiguration)
|
||||
// || super.onSupportNavigateUp()
|
||||
// }
|
||||
|
||||
override fun fsafStartActivityForResult(intent: Intent, requestCode: Int) {
|
||||
startActivityForResult(intent, requestCode)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
fileChooser.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
@@ -58,11 +58,11 @@ class LoginActivity : PermissionsActivity() {
|
||||
loginDialog = null
|
||||
}
|
||||
LoginStatus.LOGIN_STATUS_SUCCESS -> {
|
||||
val intent = Intent(this@LoginActivity, MainActivity::class.java)
|
||||
startActivity(intent)
|
||||
// finish()
|
||||
loginDialog?.dismiss()
|
||||
loginDialog = null
|
||||
val intent = Intent(this@LoginActivity, MainActivity::class.java)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
LoginStatus.LOGIN_STATUS_CANCEL -> {
|
||||
loginDialog?.dismiss()
|
||||
|
||||
@@ -8,10 +8,10 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.navinfo.omqs.bean.LoginUserBean
|
||||
import com.navinfo.omqs.db.RoomAppDatabase
|
||||
import com.navinfo.omqs.http.NetResult
|
||||
import com.navinfo.omqs.http.NetworkService
|
||||
import com.navinfo.omqs.tools.FileManager
|
||||
import com.navinfo.omqs.tools.RealmCoroutineScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.*
|
||||
import okio.IOException
|
||||
@@ -57,7 +57,7 @@ enum class LoginStatus {
|
||||
@HiltViewModel
|
||||
class LoginViewModel @Inject constructor(
|
||||
private val networkService: NetworkService,
|
||||
private val realmManager: RealmCoroutineScope
|
||||
private val roomAppDatabase: RoomAppDatabase
|
||||
) : ViewModel() {
|
||||
//用户信息
|
||||
val loginUser: MutableLiveData<LoginUserBean> = MutableLiveData()
|
||||
@@ -126,9 +126,7 @@ class LoginViewModel @Inject constructor(
|
||||
for (cityBean in result.data) {
|
||||
FileManager.checkOfflineMapFileInfo(cityBean)
|
||||
}
|
||||
realmManager.launch {
|
||||
realmManager.insertOrUpdate(result.data)
|
||||
}
|
||||
roomAppDatabase.getOfflineMapDao().insertOrUpdate(result.data)
|
||||
}
|
||||
}
|
||||
is NetResult.Error -> {
|
||||
@@ -143,7 +141,8 @@ class LoginViewModel @Inject constructor(
|
||||
.show()
|
||||
}
|
||||
}
|
||||
NetResult.Loading -> {}
|
||||
is NetResult.Loading -> {}
|
||||
else -> {}
|
||||
}
|
||||
loginStatus.postValue(LoginStatus.LOGIN_STATUS_SUCCESS)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@ import android.util.Log
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.findNavController
|
||||
import com.navinfo.collect.library.map.NIMapController
|
||||
import com.navinfo.omqs.Constant
|
||||
import com.navinfo.omqs.R
|
||||
@@ -28,6 +30,7 @@ class MainActivity : BaseActivity() {
|
||||
//注入地图控制器
|
||||
@Inject
|
||||
lateinit var mapController: NIMapController
|
||||
|
||||
@Inject
|
||||
lateinit var offlineMapDownloadManager: OfflineMapDownloadManager
|
||||
|
||||
@@ -39,9 +42,9 @@ class MainActivity : BaseActivity() {
|
||||
//初始化地图
|
||||
mapController.init(
|
||||
this,
|
||||
binding.mapView.mainActivityMap,
|
||||
binding.mainActivityMap,
|
||||
null,
|
||||
Constant.ROOT_PATH + "/map/"
|
||||
Constant.MAP_PATH
|
||||
)
|
||||
//关联生命周期
|
||||
binding.lifecycleOwner = this
|
||||
@@ -50,7 +53,7 @@ class MainActivity : BaseActivity() {
|
||||
//给xml传递viewModel对象
|
||||
binding.viewModel = viewModel
|
||||
// lifecycle.addObserver(viewModel)
|
||||
|
||||
lifecycleScope
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
@@ -83,4 +86,15 @@ class MainActivity : BaseActivity() {
|
||||
binding.mainActivityDrawer.open()
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击录音按钮
|
||||
*/
|
||||
fun voiceOnclick() {
|
||||
val naviController = findNavController(R.id.main_activity_right_fragment)
|
||||
naviController.navigate(R.id.EvaluationResultFragment)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.navinfo.omqs.ui.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
||||
abstract class BaseFragment : Fragment() {
|
||||
// override fun onCreateView(
|
||||
// inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
// ): View {
|
||||
// val view = OnCreateView(inflater, container, savedInstanceState)
|
||||
//
|
||||
// view.isFocusableInTouchMode = true;
|
||||
// view.requestFocus();
|
||||
// view.setOnKeyListener { _, keyCode, event ->
|
||||
// if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_DOWN) {
|
||||
// onBackPressed()
|
||||
// }
|
||||
// false
|
||||
// }
|
||||
//
|
||||
//
|
||||
// return view
|
||||
// }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// 获取OnBackPressedDispatcher
|
||||
val dispatcher = requireActivity().onBackPressedDispatcher
|
||||
val callback = object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
// 添加返回键事件处理逻辑
|
||||
dispatcher.addCallback(this, callback)
|
||||
}
|
||||
|
||||
// abstract fun OnCreateView(
|
||||
// inflater: LayoutInflater,
|
||||
// container: ViewGroup?,
|
||||
// savedInstanceState: Bundle?
|
||||
// ): View
|
||||
|
||||
fun onBackPressed(): Boolean{
|
||||
findNavController().navigateUp()
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.navinfo.omqs.ui.fragment.empty
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.navinfo.omqs.databinding.FragmentEmptyBinding
|
||||
|
||||
class EmptyFragment :Fragment(){
|
||||
private var _binding: FragmentEmptyBinding? = null
|
||||
|
||||
private val binding get() = _binding!!
|
||||
// private val viewModel by lazy { viewModels<EvaluationResultViewModel>().value}
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentEmptyBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
+254
@@ -0,0 +1,254 @@
|
||||
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.findNavController
|
||||
import com.navinfo.omqs.R
|
||||
import com.navinfo.omqs.databinding.FragmentEvaluationResultBinding
|
||||
import com.navinfo.omqs.ui.fragment.BaseFragment
|
||||
import com.navinfo.omqs.ui.other.shareViewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
|
||||
private var _binding: FragmentEvaluationResultBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val viewModel by shareViewModels<EvaluationResultViewModel>("QsRecode")
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentEvaluationResultBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
liveDataObserve()
|
||||
|
||||
/**
|
||||
* 点击监听
|
||||
*/
|
||||
binding.evaluationClassType.setOnClickListener(this)
|
||||
binding.evaluationProblemType.setOnClickListener(this)
|
||||
binding.evaluationPhenomenon.setOnClickListener(this)
|
||||
binding.evaluationLink.setOnClickListener(this)
|
||||
binding.evaluationCause.setOnClickListener(this)
|
||||
|
||||
//返回按钮点击
|
||||
binding.evaluationBar.setNavigationOnClickListener {
|
||||
onBackPressed()
|
||||
}
|
||||
//标题栏按钮
|
||||
binding.evaluationBar.setOnMenuItemClickListener {
|
||||
when (it.itemId) {
|
||||
R.id.save -> {
|
||||
viewModel.saveData()
|
||||
true
|
||||
}
|
||||
R.id.delete -> {
|
||||
viewModel.deleteData()
|
||||
true
|
||||
}
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 读取元数据
|
||||
*/
|
||||
viewModel.loadMetadata()
|
||||
// //监听大分类数据变化
|
||||
// viewModel.liveDataClassTypeList.observe(viewLifecycleOwner) {
|
||||
// if (it == null || it.isEmpty()) {
|
||||
// Toast.makeText(requireContext(), "还没有导入元数据!", Toast.LENGTH_SHORT).show()
|
||||
// } else {
|
||||
// binding.evaluationClassType.adapter =
|
||||
// ArrayAdapter(requireContext(), R.layout.text_item_select, it)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// viewModel.liveDataProblemTypeList.observe(viewLifecycleOwner){
|
||||
// if (it == null || it.isEmpty()) {
|
||||
// Toast.makeText(requireContext(), "还没有导入元数据!", Toast.LENGTH_SHORT).show()
|
||||
// }else{
|
||||
// binding.evaluationProblemType.adapter =
|
||||
// ArrayAdapter(requireContext(), R.layout.text_item_select, it)
|
||||
// }
|
||||
// }
|
||||
|
||||
// //选择问题分类的回调
|
||||
// binding.evaluationClassType.onItemSelectedListener =
|
||||
// object : AdapterView.OnItemSelectedListener {
|
||||
// override fun onItemSelected(
|
||||
// parent: AdapterView<*>?, view: View?, position: Int, id: Long
|
||||
// ) {
|
||||
// viewModel.getProblemTypeList(position)
|
||||
// }
|
||||
//
|
||||
// override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
// }
|
||||
// /**
|
||||
// * 监听联动选择的内容
|
||||
// */
|
||||
// viewModel.problemTypeListLiveData.observe(viewLifecycleOwner) {
|
||||
// binding.evaluationClassTabLayout.let { tabLayout ->
|
||||
// tabLayout.removeAllTabs()
|
||||
// val fragmentList = mutableListOf<Fragment>()
|
||||
// for (item in it) {
|
||||
// val tab = tabLayout.newTab()
|
||||
// tab.text = item
|
||||
// tabLayout.addTab(tab)
|
||||
// fragmentList.add(PhenomenonFragment(viewModel.currentClassType, item))
|
||||
// }
|
||||
// phenomenonFragmentAdapter =
|
||||
// activity?.let { a -> EvaluationResultAdapter(a, fragmentList) }
|
||||
// binding.evaluationViewpager.adapter = phenomenonFragmentAdapter
|
||||
//
|
||||
// TabLayoutMediator(
|
||||
// binding.evaluationClassTabLayout,
|
||||
// binding.evaluationViewpager
|
||||
// ) { tab, position ->
|
||||
// tab.text = it[position]
|
||||
// }.attach()
|
||||
// updateHeight(0)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
// binding.evaluationViewpager.registerOnPageChangeCallback(object :
|
||||
// ViewPager2.OnPageChangeCallback() {
|
||||
// override fun onPageSelected(position: Int) {
|
||||
// super.onPageSelected(position)
|
||||
// updateHeight(position)
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
|
||||
// private fun updateHeight(position: Int) {
|
||||
// phenomenonFragmentAdapter?.let {
|
||||
// if (it.fragmentList.size > position) {
|
||||
// val fragment: Fragment = it.fragmentList[position]
|
||||
// if (fragment.view != null) {
|
||||
// val viewWidth = View.MeasureSpec.makeMeasureSpec(
|
||||
// fragment.requireView().width, View.MeasureSpec.EXACTLY
|
||||
// )
|
||||
// val viewHeight =
|
||||
// View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
||||
// fragment.requireView().measure(viewWidth, viewHeight)
|
||||
// binding.evaluationViewpager.let { viewpager ->
|
||||
// if (viewpager.layoutParams.height != fragment.requireView().measuredHeight) {
|
||||
// //必须要用对象去接收,然后修改该对象再采用该对象,否则无法生效...
|
||||
// val layoutParams: ViewGroup.LayoutParams =
|
||||
// viewpager.layoutParams
|
||||
// layoutParams.height = fragment.requireView().measuredHeight
|
||||
// viewpager.layoutParams = layoutParams
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
/**
|
||||
* 监听liveData
|
||||
*/
|
||||
private fun liveDataObserve() {
|
||||
|
||||
//监听问题分类,更新UI
|
||||
viewModel.liveDataCurrentClassType.observe(viewLifecycleOwner) {
|
||||
binding.evaluationClassType.text = it
|
||||
}
|
||||
//监听问题类型,更新UI
|
||||
viewModel.liveDataCurrentProblemType.observe(viewLifecycleOwner) {
|
||||
binding.evaluationProblemType.text = it
|
||||
}
|
||||
//监听问题现象,更新UI
|
||||
viewModel.liveDataCurrentPhenomenon.observe(viewLifecycleOwner) {
|
||||
binding.evaluationPhenomenon.text = it
|
||||
}
|
||||
//监听问题环节,更新UI
|
||||
viewModel.liveDataCurrentProblemLink.observe(viewLifecycleOwner) {
|
||||
binding.evaluationLink.text = it
|
||||
}
|
||||
//监听问题初步原因,更新UI
|
||||
viewModel.liveDataCurrentCause.observe(viewLifecycleOwner) {
|
||||
binding.evaluationCause.text = it
|
||||
}
|
||||
//监听是否退出当前页面
|
||||
viewModel.liveDataFinish.observe(viewLifecycleOwner) {
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
activity?.apply {
|
||||
findNavController(R.id.main_activity_middle_fragment).navigateUp()
|
||||
}
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理点击事件
|
||||
*/
|
||||
override fun onClick(v: View?) {
|
||||
v?.let {
|
||||
when (v.id) {
|
||||
//上三项,打开面板
|
||||
R.id.evaluation_class_type, R.id.evaluation_problem_type, R.id.evaluation_phenomenon -> {
|
||||
activity?.apply {
|
||||
val controller = findNavController(R.id.main_activity_middle_fragment)
|
||||
controller.currentDestination?.let {
|
||||
//如果之前页面是空fragment,直接打开面板
|
||||
if (it.id == R.id.EmptyFragment) {
|
||||
findNavController(
|
||||
R.id.main_activity_middle_fragment
|
||||
).navigate(R.id.PhenomenonFragment)
|
||||
} else if (it.id != R.id.PhenomenonFragment) {//不是空fragment,先弹出之前的fragment
|
||||
findNavController(
|
||||
R.id.main_activity_middle_fragment
|
||||
).navigate(
|
||||
R.id.PhenomenonFragment,
|
||||
null,
|
||||
NavOptions.Builder()
|
||||
.setPopUpTo(it.id, true).build()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//下两项,打开面板
|
||||
R.id.evaluation_link, R.id.evaluation_cause -> {
|
||||
activity?.apply {
|
||||
val controller = findNavController(R.id.main_activity_middle_fragment)
|
||||
controller.currentDestination?.let {
|
||||
//如果之前页面是空fragment,直接打开面板
|
||||
if (it.id == R.id.EmptyFragment) {
|
||||
findNavController(
|
||||
R.id.main_activity_middle_fragment
|
||||
).navigate(R.id.ProblemLinkFragment)
|
||||
} else if (it.id != R.id.ProblemLinkFragment) {//不是空fragment,先弹出之前的fragment
|
||||
findNavController(
|
||||
R.id.main_activity_middle_fragment
|
||||
).navigate(
|
||||
R.id.ProblemLinkFragment,
|
||||
null,
|
||||
NavOptions.Builder()
|
||||
.setPopUpTo(it.id, true).build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.navinfo.collect.library.map.GeoPoint
|
||||
import com.navinfo.collect.library.map.NIMapController
|
||||
import com.navinfo.collect.library.data.entity.QsRecordBean
|
||||
import com.navinfo.omqs.db.RoomAppDatabase
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import io.realm.Realm
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class EvaluationResultViewModel @Inject constructor(
|
||||
private val roomAppDatabase: RoomAppDatabase, private val mapController: NIMapController
|
||||
) : ViewModel() {
|
||||
|
||||
private val markerTitle = "点选marker"
|
||||
|
||||
/**
|
||||
* 操作结束,销毁页面
|
||||
*/
|
||||
val liveDataFinish = MutableLiveData<Boolean>()
|
||||
|
||||
/**
|
||||
* 问题分类 liveData,给[PhenomenonLeftAdapter]展示的数据
|
||||
*/
|
||||
val liveDataClassTypeList = MutableLiveData<List<String>>()
|
||||
|
||||
/**
|
||||
* 问题类型 liveData 给[PhenomenonMiddleAdapter]展示的数据
|
||||
*/
|
||||
val liveDataProblemTypeList = MutableLiveData<List<String>>()
|
||||
|
||||
/**
|
||||
* 问题现象 liveData 给[PhenomenonRightGroupHeaderAdapter]展示的数据
|
||||
*/
|
||||
val liveDataPhenomenonRightList = MutableLiveData<List<PhenomenonMiddleBean>>()
|
||||
|
||||
|
||||
/**
|
||||
* 当前选择问题分类 给[EvaluationResultFragment]中 【问题分类】展示数据
|
||||
*/
|
||||
var liveDataCurrentClassType = MutableLiveData<String>()
|
||||
|
||||
/**
|
||||
* 当前选择的问题类型 给[EvaluationResultFragment]中 【问题类型】展示数据
|
||||
*/
|
||||
var liveDataCurrentProblemType = MutableLiveData<String>()
|
||||
|
||||
/**
|
||||
* 当前选择的问题现象 给[EvaluationResultFragment]中 【问题现象】展示数据
|
||||
*/
|
||||
var liveDataCurrentPhenomenon = MutableLiveData<String>()
|
||||
|
||||
|
||||
/**
|
||||
* 当前选择的问题环节 给[EvaluationResultFragment]中 【问题环节】展示数据
|
||||
*/
|
||||
var liveDataCurrentProblemLink = MutableLiveData<String>()
|
||||
|
||||
/**
|
||||
* 当前选择的问初步原因 给[EvaluationResultFragment]中 【初步原因】展示数据
|
||||
*/
|
||||
var liveDataCurrentCause = MutableLiveData<String>()
|
||||
|
||||
var currentGeoPoint: GeoPoint? = null
|
||||
|
||||
|
||||
init {
|
||||
Log.e("jingo", "EvaluationResultViewModel 创建了 ${hashCode()}")
|
||||
mapController.markerHandle.apply {
|
||||
setOnMapClickListener {
|
||||
currentGeoPoint = it
|
||||
addMarker(it, markerTitle)
|
||||
}
|
||||
}
|
||||
val geoPoint = mapController.locationLayerHandler.getCurrentGeoPoint()
|
||||
geoPoint?.let {
|
||||
currentGeoPoint = it
|
||||
mapController.markerHandle.addMarker(geoPoint, markerTitle)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
Log.e("jingo", "EvaluationResultViewModel 销毁了 ${hashCode()}")
|
||||
mapController.markerHandle.removeMarker(markerTitle)
|
||||
mapController.markerHandle.removeOnMapClickListener()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询数据库,获取问题分类
|
||||
*/
|
||||
fun loadMetadata() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
getClassTypeList()
|
||||
getProblemLinkList()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* //获取问题分类列表
|
||||
*/
|
||||
fun getClassTypeList() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val list = roomAppDatabase.getScProblemTypeDao().findClassTypeList()
|
||||
list?.let {
|
||||
//通知页面更新
|
||||
liveDataClassTypeList.postValue(it)
|
||||
//如果右侧栏没数据,给个默认值
|
||||
if (liveDataCurrentClassType.value == null) {
|
||||
liveDataCurrentClassType.postValue(it[0])
|
||||
}
|
||||
getProblemList(it[0])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取问题环节列表和初步问题
|
||||
*/
|
||||
fun getProblemLinkList() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val list = roomAppDatabase.getScRootCauseAnalysisDao().findAllData()
|
||||
list?.let { tl ->
|
||||
if (tl.isNotEmpty()) {
|
||||
val typeTitleList = mutableListOf<String>()
|
||||
val phenomenonRightList = mutableListOf<PhenomenonMiddleBean>()
|
||||
for (item in tl) {
|
||||
if (!typeTitleList.contains(item.problemLink)) {
|
||||
typeTitleList.add(item.problemLink)
|
||||
}
|
||||
phenomenonRightList.add(
|
||||
PhenomenonMiddleBean(
|
||||
title = item.problemLink, text = item.problemCause, isSelect = false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (liveDataCurrentProblemLink.value == null) {
|
||||
liveDataCurrentProblemLink.postValue(phenomenonRightList[0].text)
|
||||
}
|
||||
if (liveDataCurrentCause.value == null) {
|
||||
liveDataCurrentCause.postValue(typeTitleList[0])
|
||||
}
|
||||
liveDataProblemTypeList.postValue(typeTitleList)
|
||||
liveDataPhenomenonRightList.postValue(phenomenonRightList)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取问题类型列表和问题现象
|
||||
*/
|
||||
private suspend fun getProblemList(classType: String) {
|
||||
val typeList = roomAppDatabase.getScProblemTypeDao().findProblemTypeList(classType)
|
||||
typeList?.let { tl ->
|
||||
if (tl.isNotEmpty()) {
|
||||
val typeTitleList = mutableListOf<String>()
|
||||
val phenomenonRightList = mutableListOf<PhenomenonMiddleBean>()
|
||||
for (item in tl) {
|
||||
if (!typeTitleList.contains(item.problemType)) {
|
||||
typeTitleList.add(item.problemType)
|
||||
}
|
||||
phenomenonRightList.add(
|
||||
PhenomenonMiddleBean(
|
||||
title = item.problemType, text = item.phenomenon, isSelect = false
|
||||
)
|
||||
)
|
||||
}
|
||||
if (liveDataCurrentPhenomenon.value == null) {
|
||||
liveDataCurrentPhenomenon.postValue(phenomenonRightList[0].text)
|
||||
}
|
||||
if (liveDataCurrentProblemType.value == null) {
|
||||
liveDataCurrentProblemType.postValue(typeTitleList[0])
|
||||
}
|
||||
liveDataProblemTypeList.postValue(typeTitleList)
|
||||
liveDataPhenomenonRightList.postValue(phenomenonRightList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询问题类型
|
||||
*/
|
||||
fun getProblemTypeList(classType: String) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
liveDataCurrentClassType.postValue(classType)
|
||||
getProblemList(classType)
|
||||
}
|
||||
}
|
||||
|
||||
fun setPhenomenonMiddleBean(bean: PhenomenonMiddleBean) {
|
||||
if (liveDataCurrentPhenomenon.value != bean.text) liveDataCurrentPhenomenon.value =
|
||||
bean.text
|
||||
if (liveDataCurrentProblemType.value != bean.title) liveDataCurrentProblemType.value =
|
||||
bean.title
|
||||
|
||||
}
|
||||
|
||||
fun setProblemLinkMiddleBean(bean: PhenomenonMiddleBean) {
|
||||
if (liveDataCurrentProblemLink.value != bean.text) liveDataCurrentProblemLink.value =
|
||||
bean.text
|
||||
if (liveDataCurrentCause.value != bean.title) liveDataCurrentCause.value = bean.title
|
||||
|
||||
}
|
||||
|
||||
fun saveData() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val qsRecord = QsRecordBean(
|
||||
id = UUID.randomUUID().toString(),
|
||||
classType = liveDataCurrentClassType.value.toString(),
|
||||
type = liveDataCurrentProblemType.value.toString(),
|
||||
phenomenon = liveDataCurrentPhenomenon.value.toString(),
|
||||
problemLink = liveDataCurrentProblemLink.value.toString(),
|
||||
cause = liveDataCurrentCause.value.toString(),
|
||||
)
|
||||
qsRecord.geometry = currentGeoPoint!!.toGeometry()
|
||||
val realm = Realm.getDefaultInstance()
|
||||
realm.executeTransaction {
|
||||
it.copyToRealmOrUpdate(qsRecord)
|
||||
}
|
||||
realm.close()
|
||||
mapController.mMapView.updateMap()
|
||||
liveDataFinish.postValue(true)
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteData() {
|
||||
|
||||
}
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
|
||||
import com.navinfo.omqs.R
|
||||
import com.navinfo.omqs.databinding.FragmentPhenomenonBinding
|
||||
import com.navinfo.omqs.ui.fragment.BaseFragment
|
||||
import com.navinfo.omqs.ui.other.shareViewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class PhenomenonFragment :
|
||||
BaseFragment() {
|
||||
private var _binding: FragmentPhenomenonBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val viewModel: EvaluationResultViewModel by shareViewModels("QsRecode")
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentPhenomenonBinding.inflate(inflater, container, false)
|
||||
Log.e("jingo", "PhenomenonFragment onCreateView ${hashCode()}")
|
||||
return binding.root
|
||||
}
|
||||
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
//左侧菜单
|
||||
binding.phenomenonLeftRecyclerview.setHasFixedSize(true)
|
||||
binding.phenomenonLeftRecyclerview.layoutManager = LinearLayoutManager(requireContext())
|
||||
val leftAdapter = PhenomenonLeftAdapter { _, text ->
|
||||
viewModel.getProblemTypeList(text)
|
||||
}
|
||||
binding.phenomenonLeftRecyclerview.adapter = leftAdapter
|
||||
//左侧菜单查询结果监听
|
||||
viewModel.liveDataClassTypeList.observe(viewLifecycleOwner) {
|
||||
leftAdapter.refreshData(it)
|
||||
}
|
||||
|
||||
//右侧菜单
|
||||
binding.phenomenonRightRecyclerview.setHasFixedSize(true)
|
||||
var rightLayoutManager = LinearLayoutManager(requireContext())
|
||||
|
||||
binding.phenomenonRightRecyclerview.layoutManager = rightLayoutManager
|
||||
val rightAdapter = PhenomenonRightGroupHeaderAdapter { _, bean ->
|
||||
viewModel.setPhenomenonMiddleBean(bean)
|
||||
}
|
||||
binding.phenomenonRightRecyclerview.adapter = rightAdapter
|
||||
//右侧菜单增加组标题
|
||||
binding.phenomenonRightRecyclerview.addItemDecoration(
|
||||
PhenomenonRightGroupHeaderDecoration(
|
||||
requireContext()
|
||||
)
|
||||
)
|
||||
//右侧菜单查询数据监听
|
||||
viewModel.liveDataPhenomenonRightList.observe(viewLifecycleOwner) {
|
||||
rightAdapter.refreshData(it)
|
||||
}
|
||||
|
||||
val middleAdapter = PhenomenonMiddleAdapter { _, title ->
|
||||
rightLayoutManager.scrollToPositionWithOffset(rightAdapter.getGroupTopIndex(title), 0)
|
||||
|
||||
}
|
||||
|
||||
binding.phenomenonRightRecyclerview.addOnScrollListener(object :
|
||||
OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
}
|
||||
|
||||
//findLastVisibleItemPosition() :最后一个可见位置
|
||||
// findFirstVisibleItemPosition() :第一个可见位置
|
||||
// findLastCompletelyVisibleItemPosition() :最后一个完全可见位置
|
||||
// findFirstCompletelyVisibleItemPosition() :第一个完全可见位置
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
val firstIndex = rightLayoutManager.findFirstVisibleItemPosition()
|
||||
middleAdapter.setRightTitle(rightAdapter.data[firstIndex].title)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
//中间菜单
|
||||
binding.phenomenonMiddleRecyclerview.setHasFixedSize(true)
|
||||
binding.phenomenonMiddleRecyclerview.layoutManager = LinearLayoutManager(requireContext())
|
||||
binding.phenomenonMiddleRecyclerview.adapter = middleAdapter
|
||||
//中间侧菜单查询结果监听
|
||||
viewModel.liveDataProblemTypeList.observe(viewLifecycleOwner) {
|
||||
middleAdapter.refreshData(it)
|
||||
}
|
||||
binding.phenomenonDrawer.setOnClickListener {
|
||||
when (binding.group.visibility) {
|
||||
View.INVISIBLE, View.GONE ->
|
||||
binding.group.visibility = View.VISIBLE
|
||||
else ->
|
||||
binding.group.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.getClassTypeList()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
Log.e("jingo", "PhenomenonFragment onDestroyView ${hashCode()}")
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import com.navinfo.omqs.R
|
||||
import com.navinfo.omqs.databinding.TextItemSelectBinding
|
||||
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
|
||||
import com.navinfo.omqs.ui.other.BaseViewHolder
|
||||
|
||||
class PhenomenonLeftAdapter(private var itemListener: ((Int, String) -> Unit?)? = null) :
|
||||
BaseRecyclerViewAdapter<String>() {
|
||||
private var selectTitle = ""
|
||||
|
||||
override fun getItemViewRes(position: Int): Int {
|
||||
return R.layout.text_item_select
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
|
||||
val viewBinding =
|
||||
TextItemSelectBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return BaseViewHolder(viewBinding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
|
||||
val bd = holder.viewBinding as TextItemSelectBinding
|
||||
val title = data[position]
|
||||
bd.itemId.text = title
|
||||
if (selectTitle == title) {
|
||||
bd.itemId.setBackgroundColor(holder.viewBinding.root.context.getColor(R.color.cv_gray_153))
|
||||
} else {
|
||||
bd.itemId.setBackgroundColor(holder.viewBinding.root.context.getColor(R.color.white))
|
||||
}
|
||||
bd.root.setOnClickListener {
|
||||
if (selectTitle != title) {
|
||||
selectTitle = title
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
itemListener?.invoke(position, title)
|
||||
}
|
||||
}
|
||||
|
||||
override fun refreshData(newData: List<String>) {
|
||||
data = newData
|
||||
selectTitle = newData[0]
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun setRightTitle(title: String) {
|
||||
if (title != selectTitle) {
|
||||
selectTitle = title
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import com.navinfo.omqs.R
|
||||
import com.navinfo.omqs.databinding.TextItemSelectBinding
|
||||
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
|
||||
import com.navinfo.omqs.ui.other.BaseViewHolder
|
||||
|
||||
class PhenomenonMiddleAdapter(private var itemListener: ((Int, String) -> Unit?)? = null) :
|
||||
BaseRecyclerViewAdapter<String>() {
|
||||
private var selectTitle = ""
|
||||
|
||||
override fun getItemViewRes(position: Int): Int {
|
||||
return R.layout.text_item_select
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
|
||||
val viewBinding =
|
||||
TextItemSelectBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return BaseViewHolder(viewBinding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
|
||||
val bd = holder.viewBinding as TextItemSelectBinding
|
||||
val title = data[position]
|
||||
bd.itemId.text = title
|
||||
if (selectTitle == title) {
|
||||
bd.itemId.setBackgroundColor(holder.viewBinding.root.context.getColor(R.color.cv_gray_153))
|
||||
} else {
|
||||
bd.itemId.setBackgroundColor(holder.viewBinding.root.context.getColor(R.color.white))
|
||||
}
|
||||
bd.root.setOnClickListener {
|
||||
if (selectTitle != title) {
|
||||
selectTitle = title
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
itemListener?.invoke(position, title)
|
||||
}
|
||||
}
|
||||
|
||||
override fun refreshData(newData: List<String>) {
|
||||
data = newData
|
||||
selectTitle = newData[0]
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun setRightTitle(title: String) {
|
||||
if (title != selectTitle) {
|
||||
selectTitle = title
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||
|
||||
/**
|
||||
* 问题现象列表
|
||||
*/
|
||||
data class PhenomenonMiddleBean(val title: String, val text: String, var isSelect: Boolean = false)
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import com.navinfo.omqs.R
|
||||
import com.navinfo.omqs.databinding.TextItemSelectBinding
|
||||
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
|
||||
import com.navinfo.omqs.ui.other.BaseViewHolder
|
||||
|
||||
class PhenomenonRightGroupHeaderAdapter(private var itemListener: ((Int, PhenomenonMiddleBean) -> Unit?)? = null) :
|
||||
BaseRecyclerViewAdapter<PhenomenonMiddleBean>() {
|
||||
private var groupTitleList = mutableListOf<String>()
|
||||
override fun getItemViewRes(position: Int): Int {
|
||||
return R.layout.text_item_select
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
|
||||
val viewBinding =
|
||||
TextItemSelectBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return BaseViewHolder(viewBinding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
|
||||
val bd = holder.viewBinding as TextItemSelectBinding
|
||||
bd.itemId.text = data[position].text
|
||||
bd.root.setOnClickListener {
|
||||
itemListener?.invoke(position, data[position])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断position对应的Item是否是组的第一项
|
||||
*
|
||||
* @param position
|
||||
* @return
|
||||
*/
|
||||
fun isItemHeader(position: Int): Boolean {
|
||||
if (position >= data.size)
|
||||
return false
|
||||
return if (position == 0) {
|
||||
true
|
||||
} else {
|
||||
val lastGroupName = data[position - 1].title
|
||||
val currentGroupName = data[position].title
|
||||
//判断上一个数据的组别和下一个数据的组别是否一致,如果不一致则是不同组,也就是为第一项(头部)
|
||||
lastGroupName != currentGroupName
|
||||
}
|
||||
}
|
||||
|
||||
fun isLastGroupTitle(position: Int): Boolean {
|
||||
if (groupTitleList.isNotEmpty() && data[position].title == groupTitleList.last()) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取position对应的Item组名
|
||||
*
|
||||
* @param position
|
||||
* @return
|
||||
*/
|
||||
fun getGroupName(position: Int): String {
|
||||
return data[position].title
|
||||
}
|
||||
|
||||
fun getGroupTopIndex(position: Int): Int {
|
||||
var nowPosition = position
|
||||
val title = data[position].title
|
||||
for (i in data.size - 2 downTo 0) {
|
||||
if (data[i].title == title) {
|
||||
nowPosition = i
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nowPosition
|
||||
}
|
||||
|
||||
fun getGroupTopIndex(title: String): Int {
|
||||
for (i in data.indices) {
|
||||
if (data[i].title == title)
|
||||
return i
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun refreshData(newData: List<PhenomenonMiddleBean>) {
|
||||
super.refreshData(newData)
|
||||
groupTitleList.clear()
|
||||
for (item in newData) {
|
||||
if (groupTitleList.size > 0) {
|
||||
if (groupTitleList.last() != item.title) {
|
||||
groupTitleList.add(item.title)
|
||||
}
|
||||
} else {
|
||||
groupTitleList.add(item.title)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Rect
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ItemDecoration
|
||||
|
||||
|
||||
/**
|
||||
* 自定义装饰器(实现分组+吸顶效果)
|
||||
*/
|
||||
class PhenomenonRightGroupHeaderDecoration(context: Context) : ItemDecoration() {
|
||||
//头部的高
|
||||
private val mItemHeaderHeight: Int
|
||||
private val mTextPaddingLeft: Int
|
||||
|
||||
//画笔,绘制头部和分割线
|
||||
private val mItemHeaderPaint: Paint
|
||||
private val mTextPaint: Paint
|
||||
private val mLinePaint: Paint
|
||||
private val mTextRect: Rect
|
||||
private var lastGroupView: View? = null
|
||||
|
||||
init {
|
||||
mItemHeaderHeight = dp2px(context, 40f)
|
||||
mTextPaddingLeft = dp2px(context, 6f)
|
||||
mTextRect = Rect()
|
||||
mItemHeaderPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||
mItemHeaderPaint.color = Color.GRAY
|
||||
mTextPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||
mTextPaint.textSize = 46f
|
||||
mTextPaint.color = Color.WHITE
|
||||
mLinePaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||
mLinePaint.color = Color.GRAY
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制Item的分割线和组头
|
||||
*
|
||||
* @param c
|
||||
* @param parent
|
||||
* @param state
|
||||
*/
|
||||
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
|
||||
if (parent.adapter is PhenomenonRightGroupHeaderAdapter) {
|
||||
val adapter = parent.adapter as PhenomenonRightGroupHeaderAdapter
|
||||
val count = parent.childCount //获取可见范围内Item的总数
|
||||
for (i in 0 until count) {
|
||||
val view: View = parent.getChildAt(i)
|
||||
|
||||
val position = parent.getChildLayoutPosition(view)
|
||||
val isHeader: Boolean = adapter.isItemHeader(position)
|
||||
val left = parent.paddingLeft
|
||||
val right = parent.width - parent.paddingRight
|
||||
if (isHeader) {
|
||||
c.drawRect(
|
||||
left.toFloat(),
|
||||
(view.top - mItemHeaderHeight).toFloat(),
|
||||
right.toFloat(),
|
||||
view.top.toFloat(),
|
||||
mItemHeaderPaint
|
||||
)
|
||||
val text = adapter.getGroupName(position)
|
||||
mTextPaint.getTextBounds(
|
||||
text,
|
||||
0,
|
||||
text.length,
|
||||
mTextRect
|
||||
)
|
||||
c.drawText(
|
||||
adapter.getGroupName(position),
|
||||
(left + mTextPaddingLeft).toFloat(),
|
||||
(view.top - mItemHeaderHeight + mItemHeaderHeight / 2 + mTextRect.height() / 2).toFloat(),
|
||||
mTextPaint
|
||||
)
|
||||
} else {
|
||||
c.drawRect(
|
||||
left.toFloat(),
|
||||
(view.top - 1).toFloat(), right.toFloat(),
|
||||
view.top.toFloat(), mLinePaint
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制Item的顶部布局(吸顶效果)
|
||||
*
|
||||
* @param c
|
||||
* @param parent
|
||||
* @param state
|
||||
*/
|
||||
override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
|
||||
if (parent.adapter is PhenomenonRightGroupHeaderAdapter) {
|
||||
val adapter = parent.adapter as PhenomenonRightGroupHeaderAdapter
|
||||
val position =
|
||||
(parent.layoutManager as LinearLayoutManager?)!!.findFirstVisibleItemPosition()
|
||||
parent.findViewHolderForAdapterPosition(position)?.let {
|
||||
val view: View = it.itemView
|
||||
val isHeader: Boolean = adapter.isItemHeader(position + 1)
|
||||
val top = parent.paddingTop
|
||||
val left = parent.paddingLeft
|
||||
val right = parent.width - parent.paddingRight
|
||||
if (isHeader) {
|
||||
val bottom = mItemHeaderHeight.coerceAtMost(view.bottom)
|
||||
c.drawRect(
|
||||
left.toFloat(),
|
||||
(top + view.top - mItemHeaderHeight).toFloat(),
|
||||
right.toFloat(),
|
||||
(top + bottom).toFloat(),
|
||||
mItemHeaderPaint
|
||||
)
|
||||
val text = adapter.getGroupName(position)
|
||||
mTextPaint.getTextBounds(
|
||||
text,
|
||||
0,
|
||||
text.length,
|
||||
mTextRect
|
||||
)
|
||||
c.drawText(
|
||||
adapter.getGroupName(position),
|
||||
(left + mTextPaddingLeft).toFloat(),
|
||||
(top + mItemHeaderHeight / 2 + mTextRect.height() / 2 - (mItemHeaderHeight - bottom)).toFloat(),
|
||||
mTextPaint
|
||||
)
|
||||
} else {
|
||||
c.drawRect(
|
||||
left.toFloat(),
|
||||
top.toFloat(), right.toFloat(),
|
||||
(top + mItemHeaderHeight).toFloat(), mItemHeaderPaint
|
||||
)
|
||||
val text = adapter.getGroupName(position)
|
||||
mTextPaint.getTextBounds(
|
||||
text,
|
||||
0,
|
||||
text.length,
|
||||
mTextRect
|
||||
)
|
||||
c.drawText(
|
||||
adapter.getGroupName(position), (left + mTextPaddingLeft).toFloat(),
|
||||
(top + mItemHeaderHeight / 2 + mTextRect.height() / 2).toFloat(), mTextPaint
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
c.save()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置Item的间距
|
||||
*
|
||||
* @param outRect
|
||||
* @param view
|
||||
* @param parent
|
||||
* @param state
|
||||
*/
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
if (parent.adapter is PhenomenonRightGroupHeaderAdapter) {
|
||||
val adapter = parent.adapter as PhenomenonRightGroupHeaderAdapter
|
||||
//获取当前view在整个列表中的位置
|
||||
val position = parent.getChildLayoutPosition(view)
|
||||
//是不是改组的第一个
|
||||
val isHeader: Boolean = adapter.isItemHeader(position)
|
||||
if (isHeader) {
|
||||
outRect.top = mItemHeaderHeight
|
||||
if (adapter.isLastGroupTitle(position)) {
|
||||
lastGroupView = view
|
||||
}
|
||||
} else if (position == (parent.adapter as PhenomenonRightGroupHeaderAdapter).itemCount - 1) {
|
||||
//判断这条是不是最后一条
|
||||
//如果是最后一个,找到他所在组的第一个
|
||||
lastGroupView?.let {
|
||||
if (it.top > 0) {
|
||||
outRect.bottom = it.top - it.height * 2
|
||||
}
|
||||
}
|
||||
outRect.top = 1
|
||||
} else {
|
||||
outRect.top = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dp转换成px
|
||||
*/
|
||||
private fun dp2px(context: Context, dpValue: Float): Int {
|
||||
val scale: Float = context.resources.displayMetrics.density
|
||||
return (dpValue * scale + 0.5f).toInt()
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.navinfo.omqs.databinding.FragmentProblemLinkBinding
|
||||
import com.navinfo.omqs.ui.fragment.BaseFragment
|
||||
import com.navinfo.omqs.ui.other.shareViewModels
|
||||
|
||||
class ProblemLinkFragment : BaseFragment() {
|
||||
private var _binding: FragmentProblemLinkBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val viewModel: EvaluationResultViewModel by shareViewModels("QsRecode")
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentProblemLinkBinding.inflate(inflater, container, false)
|
||||
Log.e("jingo", "linkFragment onCreateView ${hashCode()}")
|
||||
return binding.root
|
||||
}
|
||||
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
//右侧菜单
|
||||
binding.linkRightRecyclerview.setHasFixedSize(true)
|
||||
var rightLayoutManager = LinearLayoutManager(requireContext())
|
||||
|
||||
binding.linkRightRecyclerview.layoutManager = rightLayoutManager
|
||||
val rightAdapter = PhenomenonRightGroupHeaderAdapter { _, bean ->
|
||||
viewModel.setProblemLinkMiddleBean(bean)
|
||||
}
|
||||
binding.linkRightRecyclerview.adapter = rightAdapter
|
||||
//右侧菜单增加组标题
|
||||
binding.linkRightRecyclerview.addItemDecoration(
|
||||
PhenomenonRightGroupHeaderDecoration(
|
||||
requireContext()
|
||||
)
|
||||
)
|
||||
//右侧菜单查询数据监听
|
||||
viewModel.liveDataPhenomenonRightList.observe(viewLifecycleOwner) {
|
||||
rightAdapter.refreshData(it)
|
||||
}
|
||||
|
||||
val middleAdapter = PhenomenonMiddleAdapter { _, title ->
|
||||
rightLayoutManager.scrollToPositionWithOffset(rightAdapter.getGroupTopIndex(title), 0)
|
||||
}
|
||||
|
||||
binding.linkRightRecyclerview.addOnScrollListener(object :
|
||||
RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
}
|
||||
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
val firstIndex = rightLayoutManager.findFirstVisibleItemPosition()
|
||||
middleAdapter.setRightTitle(rightAdapter.data[firstIndex].title)
|
||||
}
|
||||
})
|
||||
|
||||
//中间菜单
|
||||
binding.linkMiddleRecyclerview.setHasFixedSize(true)
|
||||
binding.linkMiddleRecyclerview.layoutManager = LinearLayoutManager(requireContext())
|
||||
binding.linkMiddleRecyclerview.adapter = middleAdapter
|
||||
//中间侧菜单查询结果监听
|
||||
viewModel.liveDataProblemTypeList.observe(viewLifecycleOwner) {
|
||||
middleAdapter.refreshData(it)
|
||||
}
|
||||
binding.linkDrawer.setOnClickListener {
|
||||
when (binding.group.visibility) {
|
||||
View.INVISIBLE, View.GONE ->
|
||||
binding.group.visibility = View.VISIBLE
|
||||
else ->
|
||||
binding.group.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.getProblemLinkList()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
Log.e("jingo", "linkFragment onDestroyView ${hashCode()}")
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package com.navinfo.omqs.ui.fragment.offlinemap
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import dagger.hilt.EntryPoint
|
||||
|
||||
/**
|
||||
* 离线地图主页面,viewpage适配器
|
||||
|
||||
+3
-3
@@ -6,9 +6,9 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.Observer
|
||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
||||
import com.navinfo.omqs.R
|
||||
import com.navinfo.omqs.databinding.AdapterOfflineMapCityBinding
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
|
||||
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
|
||||
import com.navinfo.omqs.ui.other.BaseViewHolder
|
||||
@@ -22,7 +22,7 @@ import javax.inject.Inject
|
||||
*使用 LiveData 的 observeForever 然后在 ViewHolder 销毁前手动调用 removeObserver
|
||||
*使用 LifecycleRegistry 给 ViewHolder 分发生命周期(这里使用了这个)
|
||||
*/
|
||||
class OfflineMapCityListAdapter @Inject constructor(
|
||||
class OfflineMapCityListAdapter(
|
||||
private val downloadManager: OfflineMapDownloadManager, private val context: Context
|
||||
) : BaseRecyclerViewAdapter<OfflineMapCityBean>() {
|
||||
|
||||
@@ -126,7 +126,7 @@ class OfflineMapCityListAdapter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
override fun getItemViewRes(position: Int): Int {
|
||||
return R.layout.adapter_offline_map_city
|
||||
}
|
||||
}
|
||||
|
||||
+11
-13
@@ -4,14 +4,10 @@ import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
||||
import com.navinfo.omqs.tools.FileManager
|
||||
import com.navinfo.omqs.tools.RealmCoroutineScope
|
||||
import com.navinfo.omqs.db.RoomAppDatabase
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.realm.Realm
|
||||
import io.realm.Sort
|
||||
import io.realm.kotlin.where
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
@@ -22,6 +18,7 @@ import javax.inject.Inject
|
||||
@HiltViewModel
|
||||
class OfflineMapCityListViewModel @Inject constructor(
|
||||
@ApplicationContext val context: Context,
|
||||
private val roomDatabase: RoomAppDatabase
|
||||
) : ViewModel() {
|
||||
|
||||
val cityListLiveData = MutableLiveData<List<OfflineMapCityBean>>()
|
||||
@@ -31,13 +28,14 @@ class OfflineMapCityListViewModel @Inject constructor(
|
||||
*/
|
||||
fun getCityList() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val realm = Realm.getDefaultInstance()
|
||||
val objects = realm.where<OfflineMapCityBean>().findAll().sort("id", Sort.ASCENDING)
|
||||
val list = realm.copyFromRealm(objects)
|
||||
realm.close()
|
||||
for (item in list) {
|
||||
FileManager.checkOfflineMapFileInfo(item)
|
||||
}
|
||||
// val realm = Realm.getDefaultInstance()
|
||||
// val objects = realm.where<OfflineMapCityBean>().findAll().sort("id", Sort.ASCENDING)
|
||||
// val list = realm.copyFromRealm(objects)
|
||||
// realm.close()
|
||||
// for (item in list) {
|
||||
// FileManager.checkOfflineMapFileInfo(item)
|
||||
// }
|
||||
val list = roomDatabase.getOfflineMapDao().getOfflineMapList()
|
||||
cityListLiveData.postValue(list)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
package com.navinfo.omqs.ui.fragment.offlinemap
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.navinfo.omqs.databinding.FragmentOfflineMapBinding
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* 离线地图
|
||||
* 离线地图总页面
|
||||
*/
|
||||
class OfflineMapFragment : Fragment() {
|
||||
|
||||
|
||||
+36
-6
@@ -6,16 +6,33 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.navinfo.omqs.databinding.FragmentOfflineMapBinding
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.navinfo.omqs.databinding.FragmentOfflineMapStateListBinding
|
||||
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
/**
|
||||
* 离线地图管理页面
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class OfflineMapStateListFragment : Fragment() {
|
||||
@Inject
|
||||
lateinit var downloadManager: OfflineMapDownloadManager
|
||||
private var _binding: FragmentOfflineMapStateListBinding? = null
|
||||
|
||||
private val viewModel by viewModels<OfflineMapStateListViewModel>()
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private val adapter: OfflineMapCityListAdapter by lazy {
|
||||
OfflineMapCityListAdapter(
|
||||
downloadManager,
|
||||
requireContext()
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
@@ -27,11 +44,24 @@ class OfflineMapStateListFragment : Fragment() {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
//// 设置 RecyclerView 的固定大小,避免在滚动时重新计算视图大小和布局,提高性能
|
||||
binding.offlineMapCityStateListRecyclerview.setHasFixedSize(true)
|
||||
binding.offlineMapCityStateListRecyclerview.layoutManager = layoutManager
|
||||
binding.offlineMapCityStateListRecyclerview.adapter = adapter
|
||||
viewModel.cityListLiveData.observe(viewLifecycleOwner) {
|
||||
adapter.refreshData(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
viewModel.getCityList()
|
||||
}
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.navinfo.omqs.ui.fragment.offlinemap
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.navinfo.omqs.db.RoomAppDatabase
|
||||
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* 离线地图城市列表viewModel
|
||||
*/
|
||||
@HiltViewModel
|
||||
class OfflineMapStateListViewModel @Inject constructor(
|
||||
@ApplicationContext val context: Context,
|
||||
private val roomDatabase: RoomAppDatabase
|
||||
) : ViewModel() {
|
||||
|
||||
val cityListLiveData = MutableLiveData<List<OfflineMapCityBean>>()
|
||||
|
||||
/**
|
||||
* 去获取正在下载或 已经下载的离线地图列表
|
||||
*/
|
||||
fun getCityList() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val list = roomDatabase.getOfflineMapDao().getOfflineMapListWithOutNone()
|
||||
if (cityListLiveData.value != null) {
|
||||
if (cityListLiveData.value!!.size != list.size)
|
||||
cityListLiveData.postValue(list)
|
||||
}else{
|
||||
cityListLiveData.postValue(list)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.navinfo.omqs.ui.fragment.offlinemap
|
||||
|
||||
import com.navinfo.omqs.databinding.AdapterOfflineMapCityBinding
|
||||
import com.navinfo.omqs.ui.other.BaseViewHolder
|
||||
|
||||
class OfflineMapViewHolder(dataBinding: AdapterOfflineMapCityBinding) : BaseViewHolder(dataBinding) {
|
||||
init{
|
||||
dataBinding.offlineMapDownloadBtn
|
||||
}
|
||||
}
|
||||
+14
@@ -15,10 +15,12 @@ import com.github.k1rakishou.fsaf.callback.FSAFActivityCallbacks
|
||||
import com.github.k1rakishou.fsaf.callback.FileChooserCallback
|
||||
import com.navinfo.omqs.R
|
||||
import com.navinfo.omqs.databinding.FragmentPersonalCenterBinding
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
/**
|
||||
* 个人中心
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks {
|
||||
|
||||
private var _binding: FragmentPersonalCenterBinding? = null
|
||||
@@ -54,6 +56,18 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks {
|
||||
}
|
||||
})
|
||||
}
|
||||
R.id.personal_center_menu_import_yuan_data->{
|
||||
// 用户选中导入数据,打开文件选择器,用户选择导入的数据文件目录
|
||||
fileChooser.openChooseFileDialog(object: FileChooserCallback() {
|
||||
override fun onCancel(reason: String) {
|
||||
}
|
||||
|
||||
override fun onResult(uri: Uri) {
|
||||
viewModel.importScProblemData(uri)
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
+75
-2
@@ -1,16 +1,89 @@
|
||||
package com.navinfo.omqs.ui.fragment.personalcenter
|
||||
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.blankj.utilcode.util.UriUtils
|
||||
import com.navinfo.omqs.bean.ScProblemTypeBean
|
||||
import com.navinfo.omqs.bean.ScRootCauseAnalysisBean
|
||||
import com.navinfo.omqs.db.RoomAppDatabase
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.apache.poi.ss.usermodel.Cell
|
||||
import org.apache.poi.ss.usermodel.Row
|
||||
import org.apache.poi.ss.usermodel.Sheet
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import javax.inject.Inject
|
||||
|
||||
class PersonalCenterViewModel: ViewModel() {
|
||||
@HiltViewModel
|
||||
class PersonalCenterViewModel @Inject constructor(
|
||||
private val roomAppDatabase: RoomAppDatabase
|
||||
) : ViewModel() {
|
||||
fun importOmdbData(omdbFile: File) {
|
||||
// 检查File是否为sqlite数据库
|
||||
if (omdbFile == null || omdbFile.exists()) {
|
||||
if (omdbFile == null || !omdbFile.exists()) {
|
||||
throw Exception("文件不存在")
|
||||
}
|
||||
if (!omdbFile.name.endsWith(".sqlite") and !omdbFile.name.endsWith("db")) {
|
||||
throw Exception("文件不存在")
|
||||
}
|
||||
}
|
||||
|
||||
fun importScProblemData(uri: Uri) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val file = UriUtils.uri2File(uri)
|
||||
val inputStream: InputStream =
|
||||
FileInputStream(file) //getAssets().open("sample.xlsx")
|
||||
val workbook = WorkbookFactory.create(inputStream)
|
||||
//获取所有sheet
|
||||
val sheet1 = workbook.getSheet("SC_PROBLEM_TYPE")
|
||||
sheet1?.let {
|
||||
val rowCount: Int = it.physicalNumberOfRows // 获取行数
|
||||
val list = mutableListOf<ScProblemTypeBean>()
|
||||
for (i in 1 until rowCount) {
|
||||
val row: Row = it.getRow(i) // 获取行
|
||||
val cellCount: Int = row.physicalNumberOfCells // 获取列数
|
||||
if (cellCount == 3) {
|
||||
val bean = ScProblemTypeBean()
|
||||
bean.classType = row.getCell(0).stringCellValue
|
||||
bean.problemType = row.getCell(1).stringCellValue
|
||||
bean.phenomenon = row.getCell(2).stringCellValue
|
||||
list.add(bean)
|
||||
Log.e("jingo", bean.toString())
|
||||
}
|
||||
}
|
||||
roomAppDatabase.getScProblemTypeDao().insertOrUpdateList(list)
|
||||
}
|
||||
val sheet2 = workbook.getSheet("SC_ROOT_CAUSE_ANALYSIS")
|
||||
sheet2?.let {
|
||||
val rowCount: Int = it.physicalNumberOfRows // 获取行数
|
||||
val list = mutableListOf<ScRootCauseAnalysisBean>()
|
||||
for (i in 1 until rowCount) {
|
||||
val row: Row = it.getRow(i) // 获取行
|
||||
val cellCount: Int = row.physicalNumberOfCells // 获取列数
|
||||
if (cellCount == 2) {
|
||||
val bean = ScRootCauseAnalysisBean()
|
||||
bean.problemLink = row.getCell(0).stringCellValue
|
||||
bean.problemCause = row.getCell(1).stringCellValue
|
||||
list.add(bean)
|
||||
Log.e("jingo", bean.toString())
|
||||
}
|
||||
}
|
||||
roomAppDatabase.getScRootCauseAnalysisDao().insertOrUpdateList(list)
|
||||
}
|
||||
workbook.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
Log.e("jingo", e.toString())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.navinfo.omqs.ui.other
|
||||
|
||||
interface AdapterItemClickListener {
|
||||
fun onItemClick(position: Int)
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import android.view.View.OnClickListener
|
||||
import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.navinfo.omqs.R
|
||||
|
||||
/**
|
||||
* RecyclerView 适配器基础类
|
||||
@@ -26,32 +27,38 @@ abstract class BaseRecyclerViewAdapter<T>(var data: List<T> = listOf()) :
|
||||
// )
|
||||
// }
|
||||
|
||||
abstract fun getItemViewRes(position: Int): Int
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return getItemViewRes(position)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return data.size
|
||||
}
|
||||
|
||||
fun refreshData(newData: List<T>) {
|
||||
this.data = newData
|
||||
this.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
|
||||
override fun onViewAttachedToWindow(holder: BaseViewHolder) {
|
||||
super.onViewAttachedToWindow(holder)
|
||||
holder.onStart()
|
||||
}
|
||||
|
||||
|
||||
override fun onViewDetachedFromWindow(holder: BaseViewHolder) {
|
||||
super.onViewDetachedFromWindow(holder)
|
||||
holder.apply {
|
||||
onStop()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
|
||||
// this.recyclerView = recyclerView
|
||||
// super.onAttachedToRecyclerView(recyclerView)
|
||||
// this.recyclerView = recyclerView
|
||||
// override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
open fun refreshData(newData: List<T>) {
|
||||
this.data = newData
|
||||
this.notifyDataSetChanged()
|
||||
}
|
||||
// }
|
||||
//
|
||||
// override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.navinfo.omqs.ui.other
|
||||
|
||||
import androidx.annotation.MainThread
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.createViewModelLazy
|
||||
import androidx.lifecycle.*
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
|
||||
/**
|
||||
* 用来共享的viewModel
|
||||
*/
|
||||
val vMStores = HashMap<String, ViewModelStoreOwner>()
|
||||
|
||||
|
||||
@MainThread
|
||||
inline fun <reified VM : ViewModel> Fragment.shareViewModels(
|
||||
scopeName: String,
|
||||
noinline ownerProducer: () -> ViewModelStoreOwner = { this },
|
||||
noinline factoryProducer: (() -> ViewModelProvider.Factory)? = null
|
||||
): Lazy<VM> {
|
||||
val owner by lazy(LazyThreadSafetyMode.NONE) { ownerProducer() }
|
||||
|
||||
val store: ViewModelStoreOwner
|
||||
if (vMStores.keys.contains(scopeName)) {
|
||||
store = vMStores[scopeName]!!
|
||||
} else {
|
||||
vMStores[scopeName] = owner
|
||||
store = owner
|
||||
this.let { fragment ->
|
||||
fragment.lifecycle.addObserver(object : LifecycleEventObserver {
|
||||
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
|
||||
if (event == Lifecycle.Event.ON_DESTROY) {
|
||||
fragment.lifecycle.removeObserver(this)
|
||||
store.viewModelStore.clear()
|
||||
vMStores.remove(scopeName)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// store.register(this)
|
||||
|
||||
return createViewModelLazy(
|
||||
VM::class,
|
||||
{ store.viewModelStore },
|
||||
{
|
||||
(store as? HasDefaultViewModelProviderFactory)?.defaultViewModelCreationExtras
|
||||
?: CreationExtras.Empty
|
||||
},
|
||||
factoryProducer ?: {
|
||||
(store as? HasDefaultViewModelProviderFactory)?.defaultViewModelProviderFactory
|
||||
?: defaultViewModelProviderFactory
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
//@MainThread
|
||||
//inline fun <reified VM : ViewModel> LifecycleOwner.shareViewModels(
|
||||
// scopeName: String,
|
||||
// factory: ViewModelProvider.Factory? = null
|
||||
//): Lazy<VM> {
|
||||
// val store: VMStore
|
||||
// if (vMStores.keys.contains(scopeName)) {
|
||||
// store = vMStores[scopeName]!!
|
||||
// } else {
|
||||
// store = VMStore()
|
||||
// vMStores[scopeName] = store
|
||||
// }
|
||||
// store.register(this)
|
||||
// return ViewModelLazy(VM::class,
|
||||
// { store.viewModelStore },
|
||||
// { factory ?: MyViewModelFactory() })
|
||||
//}
|
||||
|
||||
|
||||
class MyViewModelFactory(
|
||||
) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return modelClass.getConstructor().newInstance()
|
||||
}
|
||||
}
|
||||
|
||||
class VMStore(val owner: ViewModelStoreOwner) {
|
||||
|
||||
// private val bindTargets = ArrayList<LifecycleOwner>()
|
||||
// fun register(host: LifecycleOwner) {
|
||||
// if (!bindTargets.contains(host)) {
|
||||
// bindTargets.add(host)
|
||||
// host.lifecycle.addObserver(object : LifecycleEventObserver {
|
||||
// override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
|
||||
// if (event == Lifecycle.Event.ON_DESTROY) {
|
||||
// host.lifecycle.removeObserver(this)
|
||||
// bindTargets.remove(host)
|
||||
// if (bindTargets.isEmpty()) {//如果当前商店没有关联对象,则释放资源
|
||||
// vMStores.entries.find { it.value == this@VMStore }?.also {
|
||||
// owner.viewModelStore.clear()
|
||||
// vMStores.remove(it.key)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#100F0F"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8.46,11.88l1.41,-1.41L12,12.59l2.12,-2.12 1.41,1.41L13.41,14l2.12,2.12 -1.41,1.41L12,15.41l-2.12,2.12 -1.41,-1.41L10.59,14l-2.13,-2.12zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#18FD00"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,15c1.66,0 2.99,-1.34 2.99,-3L15,6c0,-1.66 -1.34,-3 -3,-3S9,4.34 9,6v6c0,1.66 1.34,3 3,3zM17.3,12c0,3 -2.54,5.1 -5.3,5.1S6.7,15 6.7,12L5,12c0,3.42 2.72,6.23 6,6.72L11,22h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#100F0F"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
|
||||
</vector>
|
||||
@@ -35,13 +35,14 @@
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/login_fragment_user_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:scrollbarAlwaysDrawHorizontalTrack="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.4">
|
||||
|
||||
@@ -54,10 +55,12 @@
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/login_fragment_user_layout">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
|
||||
@@ -21,20 +21,88 @@
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<include
|
||||
android:id="@+id/map_view"
|
||||
layout="@layout/map_view"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:mainActivity="@{mainActivity}"
|
||||
app:viewModel="@{viewModel}" />
|
||||
tools:context=".ui.activity.map.MainActivity">
|
||||
|
||||
<com.navinfo.collect.library.map.NIMapView
|
||||
android:id="@+id/main_activity_map"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/main_activity_person_center"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:onClick="@{()->mainActivity.openMenu()}"
|
||||
android:src="@drawable/baseline_person_24"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/main_activity_location"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginBottom="80dp"
|
||||
android:onClick="@{()->viewModel.onClickLocationButton()}"
|
||||
android:src="@drawable/baseline_my_location_24"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/main_activity_voice"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginBottom="120dp"
|
||||
android:onClick="@{()->mainActivity.voiceOnclick()}"
|
||||
android:src="@drawable/baseline_keyboard_voice_24"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/main_activity_middle_fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintHorizontal_weight="6"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@+id/main_activity_right_fragment"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navGraph="@navigation/middle_fragment_nav_graph" />
|
||||
|
||||
<fragment
|
||||
android:id="@id/main_activity_right_fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintHorizontal_weight="4"
|
||||
app:layout_constraintLeft_toRightOf="@id/main_activity_middle_fragment"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navGraph="@navigation/right_fragment_nav_graph" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/main_activity_fragment"
|
||||
android:id="@+id/main_activity_drawer_fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="300dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="left"
|
||||
app:navGraph="@navigation/nav_graph" />
|
||||
app:layout_constraintHorizontal_bias="0.3"
|
||||
app:navGraph="@navigation/left_drawer_nav_graph" />
|
||||
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
||||
</layout>
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<com.navinfo.collect.library.map.NIMapView
|
||||
android:id="@+id/main_activity_map1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:context=".ui.fragment.empty.EmptyFragment">
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
tools:context=".ui.fragment.evaluationresult.EvaluationResultFragment">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/evaluation_appbar_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/evaluation_bar"
|
||||
style="@style/Widget.MaterialComponents.Toolbar.Surface"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="@color/default_blue"
|
||||
app:menu="@menu/evaluation_bar_mean"
|
||||
app:navigationIcon="@drawable/btn_back_xml"
|
||||
app:title="测评结果" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/evaluation_appbar_layout">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="问题分类" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/evaluation_class_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@drawable/fm_card_map_down_status_bg" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/evaluation_problem_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@drawable/fm_card_map_down_status_bg" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/evaluation_phenomenon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@drawable/fm_card_map_down_status_bg" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/evaluation_link"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@drawable/fm_card_map_down_status_bg" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/evaluation_cause"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@drawable/fm_card_map_down_status_bg" />
|
||||
|
||||
<!-- <com.google.android.material.tabs.TabLayout-->
|
||||
<!-- android:id="@+id/evaluation_class_tab_layout"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginTop="5dp" />-->
|
||||
|
||||
<!-- <androidx.viewpager2.widget.ViewPager2-->
|
||||
<!-- android:id="@+id/evaluation_viewpager"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="match_parent"-->
|
||||
<!-- android:layout_marginTop="5dp" />-->
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,99 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#000000"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
style="@style/title_default_style"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#553C3F41">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/btn_back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingBottom="@dimen/default_widget_padding"
|
||||
android:paddingLeft="@dimen/default_widget_padding"
|
||||
android:paddingRight="@dimen/default_widget_padding"
|
||||
android:paddingTop="@dimen/default_widget_padding"
|
||||
android:src="@drawable/btn_back_xml" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/rg_city"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_manager"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/fm_card_map_btn_bg_line"
|
||||
android:button="@null"
|
||||
android:drawableLeft="@null"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="@dimen/default_widget_padding"
|
||||
android:paddingLeft="@dimen/default_widget_padding"
|
||||
android:paddingRight="@dimen/default_widget_padding"
|
||||
android:paddingTop="@dimen/default_widget_padding"
|
||||
android:text="下载管理"
|
||||
android:textColor="@color/btn_blue_white"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_city_list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/fm_card_map_btn_bg_line"
|
||||
android:button="@null"
|
||||
android:checked="true"
|
||||
android:drawableLeft="@null"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="@dimen/default_widget_padding"
|
||||
android:paddingLeft="@dimen/default_widget_padding"
|
||||
android:paddingRight="@dimen/default_widget_padding"
|
||||
android:paddingTop="@dimen/default_widget_padding"
|
||||
android:text="城市列表"
|
||||
android:textColor="@color/btn_blue_white"
|
||||
android:textSize="18sp" />
|
||||
</RadioGroup>
|
||||
</RelativeLayout>
|
||||
<EditText
|
||||
android:id="@+id/edt_search"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/input_blue_type"
|
||||
android:hint="搜索"></EditText>
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<TextView
|
||||
android:id="@+id/tv_map_download_network_hint"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center"
|
||||
android:textColor="#FFFFFF"
|
||||
android:visibility="gone"
|
||||
android:text="网络错误,请检查网络后重试"></TextView>
|
||||
<!-- <com.yanzhenjie.recyclerview.SwipeRecyclerView-->
|
||||
<!-- android:id="@+id/lv_map_manager"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:visibility="invisible"-->
|
||||
<!-- android:layout_height="match_parent">-->
|
||||
<!-- </com.yanzhenjie.recyclerview.SwipeRecyclerView>-->
|
||||
<!-- <com.yanzhenjie.recyclerview.SwipeRecyclerView-->
|
||||
<!-- android:id="@+id/lv_map_city"-->
|
||||
<!-- android:visibility="visible"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="match_parent">-->
|
||||
<!-- </com.yanzhenjie.recyclerview.SwipeRecyclerView>-->
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
@@ -26,20 +26,13 @@
|
||||
android:text="城市列表" />
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/offline_map_search"
|
||||
style="@style/input_blue_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="搜索"
|
||||
app:layout_constraintTop_toBottomOf="@id/offline_map_tab_layout" />
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/offline_map_viewpager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/offline_map_search" />
|
||||
app:layout_constraintTop_toBottomOf="@id/offline_map_tab_layout" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/offline_map_back"
|
||||
@@ -51,4 +44,6 @@
|
||||
app:layout_constraintBottom_toBottomOf="@id/offline_map_tab_layout"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/offline_map_tab_layout" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -6,8 +6,19 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.fragment.offlinemap.OfflineMapCityListFragment">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/offline_map_search"
|
||||
style="@style/input_blue_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="搜索"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/offline_map_city_list_recyclerview"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/offline_map_search" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -4,15 +4,11 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/default_red"
|
||||
tools:context=".ui.fragment.offlinemap.OfflineMapStateListFragment">
|
||||
|
||||
<TextView
|
||||
android:text="第一页"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/offline_map_city_state_list_recyclerview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -2,7 +2,7 @@
|
||||
<com.google.android.material.navigation.NavigationView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
|
||||
tools:context=".ui.fragment.personalcenter.PersonalCenterFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="left"
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="right|center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="30dp"
|
||||
tools:context="com.navinfo.omqs.ui.fragment.evaluationresult.PhenomenonFragment">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/phenomenon_drawer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/progress_bg"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingTop="30dp"
|
||||
android:paddingRight="10dp"
|
||||
android:paddingBottom="30dp"
|
||||
android:src="@drawable/btn_back_xml" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/phenomenon_title_bg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="65dp"
|
||||
android:background="@color/default_blue"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:text="问题列表"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/phenomenon_left_recyclerview"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="2"
|
||||
android:background="@color/white" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/phenomenon_middle_recyclerview"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/white" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/phenomenon_right_recyclerview"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="4"
|
||||
android:background="@color/white" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="right|center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="100dp"
|
||||
tools:context="com.navinfo.omqs.ui.fragment.evaluationresult.ProblemLinkFragment">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/link_drawer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/progress_bg"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingTop="30dp"
|
||||
android:paddingRight="10dp"
|
||||
android:paddingBottom="30dp"
|
||||
android:src="@drawable/btn_back_xml" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/link_title_bg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="65dp"
|
||||
android:background="@color/default_blue"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:text="问题列表"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/link_middle_recyclerview"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="2"
|
||||
android:background="@color/white" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/link_right_recyclerview"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="4"
|
||||
android:background="@color/white" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -1,48 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
<variable
|
||||
name="mainActivity"
|
||||
type="com.navinfo.omqs.ui.activity.map.MainActivity" />
|
||||
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="com.navinfo.omqs.ui.activity.map.MainViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.activity.map.MainActivity">
|
||||
|
||||
<com.navinfo.collect.library.map.NIMapView
|
||||
android:id="@+id/main_activity_map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/main_activity_person_center"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:onClick="@{()->mainActivity.openMenu()}"
|
||||
android:src="@drawable/baseline_person_24"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/main_activity_location"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginBottom="80dp"
|
||||
android:onClick="@{()->viewModel.onClickLocationButton()}"
|
||||
android:src="@drawable/baseline_my_location_24"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/action_settings" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/evaluation_class_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp" />
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/evaluation_class_tab_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/default_blue">
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="下载管理" />
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="城市列表" />
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/item_id"
|
||||
android:layout_width="match_parent"
|
||||
android:gravity="center"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="5dp"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="18sp">
|
||||
|
||||
</TextView>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/delete"
|
||||
android:contentDescription="删除数据"
|
||||
android:icon="@drawable/baseline_delete_forever_24"
|
||||
android:title="删除"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/save"
|
||||
android:contentDescription="保存数据"
|
||||
android:icon="@drawable/baseline_save_24"
|
||||
android:title="保存"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
</menu>
|
||||
@@ -15,9 +15,9 @@
|
||||
android:icon="@drawable/ic_baseline_import_export_24"
|
||||
android:title="导入数据" />
|
||||
<item
|
||||
android:id="@+id/personal_center_menu_offline_map2"
|
||||
android:icon="@drawable/baseline_person_24"
|
||||
android:title="menu_slideshow" />
|
||||
android:id="@+id/personal_center_menu_import_yuan_data"
|
||||
android:icon="@drawable/ic_baseline_import_export_24"
|
||||
android:title="导入元数据" />
|
||||
</group>
|
||||
<group
|
||||
android:id="@+id/group2"
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/nav_graph"
|
||||
android:id="@+id/left_drawer_nav_graph"
|
||||
app:startDestination="@id/PersonalCenterFragment">
|
||||
|
||||
<fragment
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/middle_fragment_nav_graph"
|
||||
app:startDestination="@id/EmptyFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/EmptyFragment"
|
||||
android:name="com.navinfo.omqs.ui.fragment.empty.EmptyFragment"
|
||||
android:label="空页面"
|
||||
tools:layout="@layout/fragment_empty"></fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/PhenomenonFragment"
|
||||
android:name="com.navinfo.omqs.ui.fragment.evaluationresult.PhenomenonFragment"
|
||||
android:label="评测页面"
|
||||
tools:layout="@layout/fragment_phenomenon"></fragment>
|
||||
<fragment
|
||||
android:id="@+id/ProblemLinkFragment"
|
||||
android:name="com.navinfo.omqs.ui.fragment.evaluationresult.ProblemLinkFragment"
|
||||
android:label="评测页面"
|
||||
tools:layout="@layout/fragment_problem_link"></fragment>
|
||||
</navigation>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/right_fragment_nav_graph"
|
||||
app:startDestination="@id/EmptyFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/EmptyFragment"
|
||||
android:name="com.navinfo.omqs.ui.fragment.empty.EmptyFragment"
|
||||
android:label="空页面"
|
||||
tools:layout="@layout/fragment_empty"></fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/EvaluationResultFragment"
|
||||
android:name="com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultFragment"
|
||||
android:label="评测页面"
|
||||
tools:layout="@layout/fragment_evaluation_result"></fragment>
|
||||
</navigation>
|
||||
@@ -1,5 +1,6 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath "io.realm:realm-gradle-plugin:10.11.1"
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
id 'kotlin-parcelize' // 序列化
|
||||
id 'kotlin-android'
|
||||
id 'kotlin-kapt'
|
||||
id 'realm-android'
|
||||
}
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'realm-android'
|
||||
|
||||
ext.roomversion = "2.1.0"
|
||||
ext.vtmVersion = "0.18.0"
|
||||
ext.realm_version = '10.10.1'
|
||||
ext.appcompatVersion = "1.3.0"
|
||||
@@ -31,7 +33,7 @@ android {
|
||||
}
|
||||
}
|
||||
ndk {
|
||||
abiFilters "armeabi", "armeabi-v7a"
|
||||
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,20 +55,31 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//configurations.all {
|
||||
// resolutionStrategy {
|
||||
// force 'com.intellij:annotations:13.0'
|
||||
// }
|
||||
//}
|
||||
dependencies {
|
||||
api fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
||||
api files('libs/BaiduLBS_AndroidSDK_Lib.aar')
|
||||
implementation "androidx.appcompat:appcompat:$appcompatVersion"
|
||||
implementation "com.google.android.material:material:$materialVersion"
|
||||
api files('libs/BaiduLBS_Android.jar')
|
||||
|
||||
//
|
||||
api 'androidx.core:core-ktx:1.9.0'
|
||||
api 'androidx.appcompat:appcompat:1.6.1'
|
||||
api 'com.google.android.material:material:1.8.0'
|
||||
api 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
api 'androidx.navigation:navigation-fragment-ktx:2.5.3'
|
||||
api 'androidx.navigation:navigation-ui-ktx:2.5.3'
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
implementation 'com.yanzhenjie:kalle:0.1.7'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
// implementation 'com.yanzhenjie:kalle:0.1.7'
|
||||
|
||||
// VTM依赖
|
||||
implementation "net.sf.kxml:kxml2:2.3.0"
|
||||
implementation "org.slf4j:slf4j-api:1.7.28"
|
||||
implementation 'org.slf4j:slf4j-api:2.0.7'
|
||||
implementation "org.mapsforge:vtm:$vtmVersion"
|
||||
implementation "org.mapsforge:vtm-themes:$vtmVersion"
|
||||
implementation "org.mapsforge:vtm-android:$vtmVersion"
|
||||
@@ -94,30 +107,37 @@ dependencies {
|
||||
implementation "com.badlogicgames.gdx:gdx-backend-android:1.11.0"
|
||||
implementation "com.caverock:androidsvg:1.4"
|
||||
implementation "org.mapsforge:vtm-jts:$vtmVersion"
|
||||
implementation "org.locationtech.jts:jts-core:1.18.2"
|
||||
implementation "com.squareup.okhttp3:okhttp:3.12.13"
|
||||
implementation "com.squareup.okio:okio:1.15.0"
|
||||
implementation 'org.locationtech.jts:jts-core:1.19.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.11'
|
||||
implementation 'com.squareup.okio:okio:3.3.0'
|
||||
|
||||
implementation "com.fasterxml.jackson.core:jackson-annotations:2.9.9"
|
||||
implementation "com.fasterxml.jackson.core:jackson-core:2.9.9"
|
||||
implementation "com.fasterxml.jackson.core:jackson-databind:2.9.9"
|
||||
implementation 'com.tencent.wcdb:room:1.0.8' // 代替 room-runtime,同时也不需要再引用 wcdb-android
|
||||
|
||||
implementation "androidx.sqlite:sqlite:2.0.1"
|
||||
implementation "androidx.room:room-runtime:2.1.0"
|
||||
annotationProcessor "androidx.room:room-compiler:2.1.0"
|
||||
kapt "androidx.room:room-compiler:2.1.0"
|
||||
androidTestImplementation 'androidx.room:room-testing:2.0.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
|
||||
kapt 'androidx.lifecycle:lifecycle-compiler:2.0.0'
|
||||
implementation 'com.tencent.wcdb:wcdb-android:1.0.0'
|
||||
implementation "androidx.core:core-ktx:1.8.0"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
// 协程核心库
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
|
||||
// 协程Android支持库
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
|
||||
// 协程Java8支持库
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.4'
|
||||
//room 数据库相关
|
||||
api 'com.tencent.wcdb:room:1.1-19' // 代替 room-runtime,同时也不需要再引用 wcdb-android
|
||||
api 'androidx.sqlite:sqlite-ktx:2.3.1'
|
||||
api "androidx.room:room-runtime:2.5.1"
|
||||
api "androidx.room:room-ktx:2.5.1"
|
||||
annotationProcessor "androidx.room:room-compiler:2.5.1"
|
||||
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
|
||||
kapt 'android.arch.persistence.room:compiler:1.1.1'// compiler 需要用 room 的
|
||||
kapt "androidx.room:room-compiler:2.5.1"
|
||||
kapt "androidx.room:room-ktx:2.5.1"
|
||||
|
||||
// //分页加载
|
||||
// api "androidx.room:room-paging:$roomversion"
|
||||
// api "androidx.paging:paging-runtime-ktx:3.1.1"
|
||||
|
||||
androidTestImplementation "android.arch.persistence.room:testing:1.1.1"
|
||||
api 'com.tencent.wcdb:wcdb-android:1.1-19'
|
||||
|
||||
// // 协程核心库
|
||||
// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
|
||||
// // 协程Android支持库
|
||||
// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
|
||||
// // 协程Java8支持库
|
||||
// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.4'
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+57
-57
@@ -1,57 +1,57 @@
|
||||
package com.navinfo.collect.library.data.entity
|
||||
|
||||
import io.realm.RealmObject
|
||||
import io.realm.annotations.PrimaryKey
|
||||
|
||||
//enum class StatusEnum(val status: Int) {
|
||||
// NONE(0), WAITING(1), LOADING(2), PAUSE(3),
|
||||
// ERROR(4), DONE(5), UPDATE(6)
|
||||
//}
|
||||
|
||||
open class OfflineMapCityBean @JvmOverloads constructor(
|
||||
@PrimaryKey var id: String = "",
|
||||
var fileName: String = "",
|
||||
var name: String = "",
|
||||
var url: String = "",
|
||||
var version: Long = 0L,
|
||||
var fileSize: Long = 0L,
|
||||
var currentSize: Long = 0L,
|
||||
var status: Int = NONE
|
||||
) : RealmObject() {
|
||||
|
||||
companion object Status{
|
||||
const val NONE = 0 //无状态
|
||||
const val WAITING = 1 //等待中
|
||||
const val LOADING = 2 //下载中
|
||||
const val PAUSE = 3 //暂停
|
||||
const val ERROR = 4 //错误
|
||||
const val DONE = 5 //完成
|
||||
const val UPDATE = 6 //有新版本要更新
|
||||
}
|
||||
|
||||
// // status的转换对象
|
||||
// var statusEnum: StatusEnum
|
||||
// get() {
|
||||
// return try {
|
||||
// StatusEnum.values().find { it.status == status }!!
|
||||
// } catch (e: IllegalArgumentException) {
|
||||
// StatusEnum.NONE
|
||||
// }
|
||||
// }
|
||||
// set(value) {
|
||||
// status = value.status
|
||||
// }
|
||||
|
||||
fun getFileSizeText(): String {
|
||||
return if (fileSize < 1024.0)
|
||||
"$fileSize B"
|
||||
else if (fileSize < 1048576.0)
|
||||
"%.2f K".format(fileSize / 1024.0)
|
||||
else if (fileSize < 1073741824.0)
|
||||
"%.2f M".format(fileSize / 1048576.0)
|
||||
else
|
||||
"%.2f M".format(fileSize / 1073741824.0)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//package com.navinfo.collect.library.data.entity
|
||||
//
|
||||
//import io.realm.RealmObject
|
||||
//import io.realm.annotations.PrimaryKey
|
||||
//
|
||||
////enum class StatusEnum(val status: Int) {
|
||||
//// NONE(0), WAITING(1), LOADING(2), PAUSE(3),
|
||||
//// ERROR(4), DONE(5), UPDATE(6)
|
||||
////}
|
||||
//
|
||||
//open class OfflineMapCityBean @JvmOverloads constructor(
|
||||
// @PrimaryKey var id: String = "",
|
||||
// var fileName: String = "",
|
||||
// var name: String = "",
|
||||
// var url: String = "",
|
||||
// var version: Long = 0L,
|
||||
// var fileSize: Long = 0L,
|
||||
// var currentSize: Long = 0L,
|
||||
// var status: Int = NONE
|
||||
//) : RealmObject() {
|
||||
//
|
||||
// companion object Status{
|
||||
// const val NONE = 0 //无状态
|
||||
// const val WAITING = 1 //等待中
|
||||
// const val LOADING = 2 //下载中
|
||||
// const val PAUSE = 3 //暂停
|
||||
// const val ERROR = 4 //错误
|
||||
// const val DONE = 5 //完成
|
||||
// const val UPDATE = 6 //有新版本要更新
|
||||
// }
|
||||
//
|
||||
//// // status的转换对象
|
||||
//// var statusEnum: StatusEnum
|
||||
//// get() {
|
||||
//// return try {
|
||||
//// StatusEnum.values().find { it.status == status }!!
|
||||
//// } catch (e: IllegalArgumentException) {
|
||||
//// StatusEnum.NONE
|
||||
//// }
|
||||
//// }
|
||||
//// set(value) {
|
||||
//// status = value.status
|
||||
//// }
|
||||
//
|
||||
// fun getFileSizeText(): String {
|
||||
// return if (fileSize < 1024.0)
|
||||
// "$fileSize B"
|
||||
// else if (fileSize < 1048576.0)
|
||||
// "%.2f K".format(fileSize / 1024.0)
|
||||
// else if (fileSize < 1073741824.0)
|
||||
// "%.2f M".format(fileSize / 1048576.0)
|
||||
// else
|
||||
// "%.2f M".format(fileSize / 1073741824.0)
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
||||
+43
-43
@@ -1,43 +1,43 @@
|
||||
package com.navinfo.collect.library.data.entity
|
||||
|
||||
import io.realm.RealmModel
|
||||
import io.realm.RealmObject
|
||||
import io.realm.annotations.PrimaryKey
|
||||
import io.realm.annotations.RealmClass
|
||||
|
||||
@RealmClass
|
||||
open class OfflineMapCityRealmObject: RealmModel {
|
||||
@PrimaryKey
|
||||
var id: String = ""
|
||||
var fileName: String=""
|
||||
var name: String = ""
|
||||
var url: String = ""
|
||||
var version: Long = 0
|
||||
var fileSize: Long = 0
|
||||
var currentSize:Long = 0
|
||||
var status:Int = 0
|
||||
|
||||
constructor(){
|
||||
|
||||
}
|
||||
|
||||
constructor(
|
||||
id: String,
|
||||
fileName: String,
|
||||
name: String,
|
||||
url: String,
|
||||
version: Long,
|
||||
fileSize: Long,
|
||||
currentSize: Long,
|
||||
status: Int
|
||||
) {
|
||||
this.id = id
|
||||
this.fileName = fileName
|
||||
this.name = name
|
||||
this.url = url
|
||||
this.version = version
|
||||
this.fileSize = fileSize
|
||||
this.currentSize = currentSize
|
||||
this.status = status
|
||||
}
|
||||
}
|
||||
//package com.navinfo.collect.library.data.entity
|
||||
//
|
||||
//import io.realm.RealmModel
|
||||
//import io.realm.RealmObject
|
||||
//import io.realm.annotations.PrimaryKey
|
||||
//import io.realm.annotations.RealmClass
|
||||
//
|
||||
//@RealmClass
|
||||
//open class OfflineMapCityRealmObject: RealmModel {
|
||||
// @PrimaryKey
|
||||
// var id: String = ""
|
||||
// var fileName: String=""
|
||||
// var name: String = ""
|
||||
// var url: String = ""
|
||||
// var version: Long = 0
|
||||
// var fileSize: Long = 0
|
||||
// var currentSize:Long = 0
|
||||
// var status:Int = 0
|
||||
//
|
||||
// constructor(){
|
||||
//
|
||||
// }
|
||||
//
|
||||
// constructor(
|
||||
// id: String,
|
||||
// fileName: String,
|
||||
// name: String,
|
||||
// url: String,
|
||||
// version: Long,
|
||||
// fileSize: Long,
|
||||
// currentSize: Long,
|
||||
// status: Int
|
||||
// ) {
|
||||
// this.id = id
|
||||
// this.fileName = fileName
|
||||
// this.name = name
|
||||
// this.url = url
|
||||
// this.version = version
|
||||
// this.fileSize = fileSize
|
||||
// this.currentSize = currentSize
|
||||
// this.status = status
|
||||
// }
|
||||
//}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package com.navinfo.collect.library.data.entity
|
||||
|
||||
import com.navinfo.collect.library.utils.GeometryToolsKt
|
||||
import io.realm.RealmObject
|
||||
import io.realm.RealmSet
|
||||
import io.realm.annotations.PrimaryKey
|
||||
import io.realm.annotations.RealmClass
|
||||
|
||||
|
||||
/**
|
||||
* @author zhjch
|
||||
* @version V1.0
|
||||
* @ClassName: Rd_qcRecord
|
||||
* @Date 2016/1/12
|
||||
* @Description: ${TODO}(质检对象)
|
||||
*/
|
||||
@RealmClass
|
||||
open class QsRecordBean @JvmOverloads constructor(
|
||||
/**
|
||||
* id 主键
|
||||
*
|
||||
*/
|
||||
@PrimaryKey
|
||||
var id: String = "",
|
||||
/**
|
||||
* 关联要素id
|
||||
*/
|
||||
var elementId: String = "",
|
||||
/**
|
||||
* linkPid 绑定的道路ID
|
||||
*/
|
||||
var linkId: String = "",
|
||||
/**
|
||||
*问题分类
|
||||
*/
|
||||
var classType: String = "",
|
||||
/**
|
||||
* 问题类型
|
||||
*/
|
||||
var type: String = "",
|
||||
|
||||
/**
|
||||
* 问题现象
|
||||
*/
|
||||
var phenomenon: String = "",
|
||||
/**
|
||||
* 描述信息
|
||||
*/
|
||||
var description: String = "",
|
||||
/**
|
||||
* 问题环节
|
||||
*/
|
||||
var problemLink: String = "",
|
||||
/**
|
||||
* 问题原因
|
||||
* 根本原因(RCA)
|
||||
*/
|
||||
|
||||
var cause: String = "",
|
||||
/**
|
||||
* 质检员ID
|
||||
*/
|
||||
var checkUserId: String = "",
|
||||
/**
|
||||
* 质检日期
|
||||
*/
|
||||
var checkTime: String = "",
|
||||
/**
|
||||
* 确认人
|
||||
*/
|
||||
var confirmUserId: String = "",
|
||||
/**
|
||||
* 状态 0 无; 1 删除;2 更新;3 新增;
|
||||
*/
|
||||
|
||||
var t_lifecycle: Int = 3,
|
||||
/**
|
||||
* 问题记录提交状态 0 未提交;1 已提交;
|
||||
*/
|
||||
var t_status: Int = 0,
|
||||
/**
|
||||
* 显示坐标
|
||||
*/
|
||||
// var geometry: String = "",
|
||||
/**
|
||||
* 显示坐标
|
||||
*/
|
||||
var guideGeometry: String = "",
|
||||
|
||||
) : RealmObject() {
|
||||
|
||||
|
||||
private val tileX = RealmSet<Int>() // x方向的tile编码
|
||||
private val tileY = RealmSet<Int>() // y方向的tile编码
|
||||
var geometry: String = ""
|
||||
set(value) {
|
||||
field = value
|
||||
// 根据geometry自动计算当前要素的x-tile和y-tile
|
||||
GeometryToolsKt.getTileXByGeometry(value, tileX)
|
||||
GeometryToolsKt.getTileYByGeometry(value, tileY)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.navinfo.collect.library.map
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class GeoPoint(
|
||||
var latitude: Double = 0.0,
|
||||
var longitude: Double = 0.0
|
||||
) : Parcelable {
|
||||
fun toGeometry(): String {
|
||||
return "POINT($longitude $latitude)"
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.navinfo.collect.library.map
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.navinfo.collect.library.map.handler.*
|
||||
import com.navinfo.collect.library.map.maphandler.MeasureLayerHandler
|
||||
import com.navinfo.collect.library.map.handler.ViewportHandler
|
||||
@@ -23,7 +24,7 @@ class NIMapController {
|
||||
lateinit var measureLayerHandler: MeasureLayerHandler
|
||||
|
||||
|
||||
fun init(context: Context, mapView: NIMapView, options: NIMapOptions? = null, mapPath: String) {
|
||||
fun init(context: AppCompatActivity, mapView: NIMapView, options: NIMapOptions? = null, mapPath: String) {
|
||||
Constant.MAP_PATH = mapPath
|
||||
layerManagerHandler = LayerManagerHandler(context, mapView)
|
||||
locationLayerHandler = LocationLayerHandler(context, mapView)
|
||||
@@ -37,5 +38,6 @@ class NIMapController {
|
||||
mapView.setOptions(options)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.navinfo.collect.library.map;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
@@ -15,37 +14,21 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.navinfo.collect.library.R;
|
||||
import com.navinfo.collect.library.map.layers.NaviMapScaleBar;
|
||||
import com.navinfo.collect.library.map.source.MapLifeDBTileSource;
|
||||
import com.navinfo.collect.library.map.source.MapLifeNiLocationTileDataSource;
|
||||
import com.navinfo.collect.library.map.source.MapLifeNiLocationTileSource;
|
||||
import com.navinfo.collect.library.system.Constant;
|
||||
|
||||
import org.oscim.android.MapPreferences;
|
||||
import org.oscim.android.MapView;
|
||||
import org.oscim.core.GeoPoint;
|
||||
import org.oscim.android.theme.AssetsRenderTheme;
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.event.Event;
|
||||
import org.oscim.event.Gesture;
|
||||
import org.oscim.event.GestureListener;
|
||||
import org.oscim.layers.GroupLayer;
|
||||
import org.oscim.layers.Layer;
|
||||
import org.oscim.layers.TileGridLayer;
|
||||
import org.oscim.layers.tile.buildings.BuildingLayer;
|
||||
import org.oscim.layers.tile.vector.OsmTileLayer;
|
||||
import org.oscim.layers.tile.vector.VectorTileLayer;
|
||||
import org.oscim.layers.tile.vector.labeling.LabelLayer;
|
||||
import org.oscim.layers.tile.vector.labeling.LabelTileLoaderHook;
|
||||
import org.oscim.map.Map;
|
||||
import org.oscim.renderer.GLViewport;
|
||||
import org.oscim.theme.IRenderTheme;
|
||||
import org.oscim.theme.ThemeLoader;
|
||||
import org.oscim.theme.VtmThemes;
|
||||
import org.oscim.tiling.source.mapfile.MapFileTileSource;
|
||||
import org.oscim.tiling.source.mapfile.MultiMapFileTileSource;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
/**
|
||||
@@ -125,14 +108,14 @@ public final class NIMapView extends RelativeLayout {
|
||||
*
|
||||
* @param point
|
||||
*/
|
||||
void onMapClick(GeoPoint point);
|
||||
void onMapClick(com.navinfo.collect.library.map.GeoPoint point);
|
||||
|
||||
/**
|
||||
* 地图内 Poi 单击事件回调函数
|
||||
*
|
||||
* @param poi
|
||||
*/
|
||||
void onMapPoiClick(GeoPoint poi);
|
||||
// void onMapPoiClick(GeoPoint poi);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,10 +201,8 @@ public final class NIMapView extends RelativeLayout {
|
||||
this.mContext = context;
|
||||
|
||||
mapView = rootView.findViewById(R.id.base_map_view);
|
||||
// map = new NIMap(this);
|
||||
compassImage = rootView.findViewById(R.id.navinfo_map_compass);
|
||||
initMapGroup(); // 初始化图层组
|
||||
// mLayerManager = new NILayerManager(context, getVtmMap());
|
||||
|
||||
logoImage = rootView.findViewById(R.id.navinfo_map_logo);
|
||||
mRotateAnimation = new NIRotateAnimation(compassImage);
|
||||
@@ -251,6 +232,7 @@ public final class NIMapView extends RelativeLayout {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 增加比例尺图层
|
||||
NaviMapScaleBar naviMapScaleBar = new NaviMapScaleBar(getVtmMap());
|
||||
naviMapScaleBar.initScaleBarLayer(GLViewport.Position.BOTTOM_LEFT, 25, 60);
|
||||
@@ -302,6 +284,9 @@ public final class NIMapView extends RelativeLayout {
|
||||
|
||||
zoomLayout = rootView.findViewById(R.id.navinfo_map_zoom_layer);
|
||||
switchTileVectorLayerTheme(MAP_THEME.DEFAULT);
|
||||
|
||||
MapEventsReceiver mapEventReceiver = new MapEventsReceiver(mapView.map());
|
||||
getVtmMap().layers().add(mapEventReceiver);
|
||||
}
|
||||
|
||||
|
||||
@@ -923,7 +908,7 @@ public final class NIMapView extends RelativeLayout {
|
||||
GeoPoint geoPoint = mMap.viewport().fromScreenPoint(e.getX(), e.getY());
|
||||
if (g instanceof Gesture.Tap) { // 单击事件
|
||||
if (mapClickListener != null) {
|
||||
mapClickListener.onMapClick(geoPoint);
|
||||
mapClickListener.onMapClick(new com.navinfo.collect.library.map.GeoPoint(geoPoint.getLatitude(), geoPoint.getLongitude()));
|
||||
}
|
||||
} else if (g instanceof Gesture.DoubleTap) { // 双击
|
||||
if (mapDoubleClickListener != null) {
|
||||
@@ -934,17 +919,6 @@ public final class NIMapView extends RelativeLayout {
|
||||
mapLongClickListener.onMapLongClick(geoPoint);
|
||||
}
|
||||
}
|
||||
setOnMapClickListener(new OnMapClickListener() {
|
||||
@Override
|
||||
public void onMapClick(GeoPoint point) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapPoiClick(GeoPoint poi) {
|
||||
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -952,7 +926,7 @@ public final class NIMapView extends RelativeLayout {
|
||||
/**
|
||||
* 设置地图的点击事件
|
||||
*/
|
||||
public void setOnMapClickListener(@Nullable OnMapClickListener listener) {
|
||||
public void setOnMapClickListener(OnMapClickListener listener) {
|
||||
this.mapClickListener = listener;
|
||||
}
|
||||
|
||||
|
||||
+10
-2
@@ -1,11 +1,12 @@
|
||||
package com.navinfo.collect.library.map.handler
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.navinfo.collect.library.map.NIMapView
|
||||
import org.oscim.layers.Layer
|
||||
|
||||
abstract class BaseHandler(context: Context, mapView: NIMapView) {
|
||||
protected val mContext: Context = context
|
||||
abstract class BaseHandler(context: AppCompatActivity, mapView: NIMapView) {
|
||||
protected val mContext: AppCompatActivity = context
|
||||
protected val mMapView: NIMapView = mapView
|
||||
|
||||
fun addLayer(layer: Layer, groupType: NIMapView.LAYER_GROUPS) {
|
||||
@@ -19,4 +20,11 @@ abstract class BaseHandler(context: Context, mapView: NIMapView) {
|
||||
mMapView.vtmMap.layers().remove(layer)
|
||||
}
|
||||
|
||||
fun setOnMapClickListener(listener: NIMapView.OnMapClickListener) {
|
||||
mMapView.setOnMapClickListener(listener)
|
||||
}
|
||||
|
||||
fun removeOnMapClickListener() {
|
||||
mMapView.setOnMapClickListener(null)
|
||||
}
|
||||
}
|
||||
+127
-39
@@ -1,25 +1,46 @@
|
||||
package com.navinfo.collect.library.map.handler
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Environment
|
||||
import android.graphics.Color
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.navinfo.collect.library.data.entity.QsRecordBean
|
||||
import com.navinfo.collect.library.map.NIMapView
|
||||
import com.navinfo.collect.library.map.NIMapView.LAYER_GROUPS
|
||||
import com.navinfo.collect.library.map.source.NavinfoMapRastorTileSource
|
||||
import com.navinfo.collect.library.map.source.NavinfoMultiMapFileTileSource
|
||||
import com.navinfo.collect.library.system.Constant
|
||||
import io.realm.Realm
|
||||
import io.realm.kotlin.where
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.Cache
|
||||
import okhttp3.OkHttpClient
|
||||
import org.oscim.layers.Layer
|
||||
import org.oscim.layers.LocationLayer
|
||||
import org.oscim.layers.tile.bitmap.BitmapTileLayer
|
||||
import org.oscim.backend.CanvasAdapter
|
||||
import org.oscim.backend.canvas.Paint
|
||||
import org.oscim.layers.GroupLayer
|
||||
import org.oscim.layers.tile.buildings.BuildingLayer
|
||||
import org.oscim.layers.tile.vector.VectorTileLayer
|
||||
import org.oscim.layers.tile.vector.labeling.LabelLayer
|
||||
import org.oscim.tiling.source.OkHttpEngine.OkHttpFactory
|
||||
import org.oscim.tiling.source.mapfile.MapFileTileSource
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Layer 操作
|
||||
*/
|
||||
class LayerManagerHandler(context: Context, mapView: NIMapView) :
|
||||
class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) :
|
||||
BaseHandler(context, mapView) {
|
||||
private var baseRasterLayer: Layer? = null
|
||||
private var baseGroupLayer // 用于盛放所有基础底图的图层组,便于统一管理
|
||||
: GroupLayer? = null
|
||||
|
||||
/**
|
||||
* 默认文字颜色
|
||||
*/
|
||||
private val mDefaultTextColor = "#4E55AF"
|
||||
|
||||
/**
|
||||
* 文字画笔
|
||||
*/
|
||||
|
||||
private lateinit var paint: Paint
|
||||
|
||||
init {
|
||||
initMap()
|
||||
@@ -29,9 +50,12 @@ class LayerManagerHandler(context: Context, mapView: NIMapView) :
|
||||
* 初始化地图
|
||||
*/
|
||||
private fun initMap() {
|
||||
switchBaseMapType(BASE_MAP_TYPE.CYCLE_MAP)
|
||||
|
||||
// initVectorTileLayer()
|
||||
loadBaseMap()
|
||||
mMapView.switchTileVectorLayerTheme(NIMapView.MAP_THEME.DEFAULT)
|
||||
//初始化之间数据图层
|
||||
initQsRecordDataLayer()
|
||||
mMapView.vtmMap.updateMap()
|
||||
// initMapLifeSource()
|
||||
}
|
||||
|
||||
@@ -39,40 +63,104 @@ class LayerManagerHandler(context: Context, mapView: NIMapView) :
|
||||
/**
|
||||
* 切换基础底图样式
|
||||
*/
|
||||
fun switchBaseMapType(type: BASE_MAP_TYPE) {
|
||||
if (baseRasterLayer != null) {
|
||||
mMapView.vtmMap.layers().remove(baseRasterLayer)
|
||||
baseRasterLayer = null
|
||||
mMapView.vtmMap.updateMap()
|
||||
fun loadBaseMap() {
|
||||
//给地图layer分组
|
||||
if (baseGroupLayer == null) {
|
||||
baseGroupLayer = GroupLayer(mMapView.vtmMap)
|
||||
addLayer(baseGroupLayer!!, NIMapView.LAYER_GROUPS.BASE)
|
||||
}
|
||||
baseRasterLayer = getRasterTileLayer(type.url, type.tilePath, true)
|
||||
addLayer(baseRasterLayer!!, LAYER_GROUPS.BASE)
|
||||
mMapView.updateMap()
|
||||
}
|
||||
baseGroupLayer?.let {
|
||||
for (layer in it.layers) {
|
||||
removeLayer(layer)
|
||||
}
|
||||
it.layers.clear()
|
||||
val builder = OkHttpClient.Builder()
|
||||
val urlTileSource: NavinfoMultiMapFileTileSource =
|
||||
NavinfoMultiMapFileTileSource.builder()
|
||||
.httpFactory(OkHttpFactory(builder)) //.locale("en")
|
||||
.build()
|
||||
|
||||
private fun getRasterTileLayer(
|
||||
url: String?,
|
||||
tilePath: String?,
|
||||
useCache: Boolean
|
||||
): Layer {
|
||||
val builder = OkHttpClient.Builder()
|
||||
val mTileSource =
|
||||
NavinfoMapRastorTileSource.builder(url).tilePath(tilePath)
|
||||
.httpFactory(OkHttpFactory(builder)).build()
|
||||
// 如果使用缓存
|
||||
if (useCache) {
|
||||
val cacheDirectory: File =
|
||||
File(Constant.MAP_PATH, "tiles-raster")
|
||||
val cacheSize = 300 * 1024 * 1024 // 300 MB
|
||||
// Cache the tiles into file system
|
||||
val cacheDirectory = File(Constant.MAP_PATH, "cache")
|
||||
val cacheSize = 200 * 1024 * 1024 // 10 MB
|
||||
val cache = Cache(cacheDirectory, cacheSize.toLong())
|
||||
builder.cache(cache)
|
||||
}
|
||||
|
||||
// mTileSource.setHttpEngine(new OkHttpEngine.OkHttpFactory(builder));
|
||||
// mTileSource.setHttpRequestHeaders(Collections.singletonMap("User-Agent", "vtm-android-example"));
|
||||
// mTileSource.setCache(new TileCache(mContext, defaultDir, url.substring(url.indexOf(":")+1)));
|
||||
return BitmapTileLayer(mMapView.vtmMap, mTileSource)
|
||||
// val headerMap = HashMap<String, String>()
|
||||
// headerMap["token"] = ""//Constant.TOKEN
|
||||
// urlTileSource.setHttpRequestHeaders(headerMap)
|
||||
val baseLayer = VectorTileLayer(mMapView.vtmMap, urlTileSource)
|
||||
|
||||
val baseMapFolder = File("${Constant.MAP_PATH}offline")
|
||||
|
||||
if (baseMapFolder.exists()) {
|
||||
val dirFileList = baseMapFolder.listFiles()
|
||||
if (dirFileList != null && dirFileList.isNotEmpty()) {
|
||||
for (mapFile in dirFileList) {
|
||||
if (!mapFile.isFile || !mapFile.name.endsWith(".map")) {
|
||||
continue
|
||||
}
|
||||
val mTileSource = MapFileTileSource()
|
||||
mTileSource.setPreferredLanguage("zh")
|
||||
if (mTileSource.setMapFile(mapFile.absolutePath)) {
|
||||
urlTileSource.add(mTileSource)
|
||||
}
|
||||
}
|
||||
}
|
||||
baseLayer.tileSource = urlTileSource
|
||||
//增加基础路网图层
|
||||
it.layers.add(baseLayer)
|
||||
//增加建筑图层
|
||||
it.layers.add(BuildingLayer(mMapView.vtmMap, baseLayer))
|
||||
//增加文字图层
|
||||
it.layers.add(LabelLayer(mMapView.vtmMap, baseLayer))
|
||||
for (layer in it.layers) {
|
||||
addLayer(layer, NIMapView.LAYER_GROUPS.BASE)
|
||||
}
|
||||
mMapView.updateMap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initQsRecordDataLayer() {
|
||||
paint = CanvasAdapter.newPaint()
|
||||
paint.setTypeface(Paint.FontFamily.DEFAULT, Paint.FontStyle.NORMAL)
|
||||
paint.setTextSize(13 * CanvasAdapter.getScale())
|
||||
paint.strokeWidth = 2 * CanvasAdapter.getScale()
|
||||
paint.color = Color.parseColor(mDefaultTextColor)
|
||||
|
||||
mContext.lifecycleScope.launch(Dispatchers.IO) {
|
||||
|
||||
|
||||
val realm = Realm.getDefaultInstance()
|
||||
realm.executeTransaction {
|
||||
val list = realm.where<QsRecordBean>().findAll()
|
||||
paint.setColor(Color.parseColor(mDefaultTextColor))
|
||||
}
|
||||
realm.close()
|
||||
}
|
||||
}
|
||||
|
||||
// private fun getRasterTileLayer(
|
||||
// url: String?,
|
||||
// tilePath: String?,
|
||||
// useCache: Boolean
|
||||
// ): Layer {
|
||||
// val builder = OkHttpClient.Builder()
|
||||
// val mTileSource =
|
||||
// NavinfoMapRastorTileSource.builder(url).tilePath(tilePath)
|
||||
// .httpFactory(OkHttpFactory(builder)).build()
|
||||
// // 如果使用缓存
|
||||
// if (useCache) {
|
||||
// val cacheDirectory =
|
||||
// File(Constant.MAP_PATH, "cache")
|
||||
// val cacheSize = 300 * 1024 * 1024 // 300 MB
|
||||
// val cache = Cache(cacheDirectory, cacheSize.toLong())
|
||||
// builder.cache(cache)
|
||||
// }
|
||||
//
|
||||
// return BitmapTileLayer(mMapView.vtmMap, mTileSource)
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+27
-16
@@ -8,12 +8,12 @@ import com.baidu.location.BDLocation
|
||||
import com.baidu.location.LocationClient
|
||||
import com.baidu.location.LocationClientOption
|
||||
import com.baidu.location.LocationClientOption.LocationMode
|
||||
import com.navinfo.collect.library.map.GeoPoint
|
||||
import com.navinfo.collect.library.map.NIMapView
|
||||
import org.oscim.layers.LocationLayer
|
||||
|
||||
|
||||
class LocationLayerHandler(context: Context, mapView: NIMapView) :
|
||||
BaseHandler(context, mapView) {
|
||||
class LocationLayerHandler(context: Context, mapView: NIMapView) : BaseHandler(context, mapView) {
|
||||
|
||||
private var mCurrentLocation: BDLocation? = null
|
||||
private var bFirst = true
|
||||
@@ -55,13 +55,11 @@ class LocationLayerHandler(context: Context, mapView: NIMapView) :
|
||||
val errorCode = it.locType
|
||||
mCurrentLocation = it
|
||||
mLocationLayer.setPosition(
|
||||
it.latitude,
|
||||
it.longitude,
|
||||
it.radius
|
||||
it.latitude, it.longitude, it.radius
|
||||
)
|
||||
//第一次定位成功显示当前位置
|
||||
if (this.bFirst) {
|
||||
animateToCurrentPosition()
|
||||
animateToCurrentPosition(16.0)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -97,9 +95,7 @@ class LocationLayerHandler(context: Context, mapView: NIMapView) :
|
||||
// locationOption.setOpenAutoNotifyMode()
|
||||
//设置打开自动回调位置模式,该开关打开后,期间只要定位SDK检测到位置变化就会主动回调给开发者
|
||||
locationOption.setOpenAutoNotifyMode(
|
||||
1000,
|
||||
1,
|
||||
LocationClientOption.LOC_SENSITIVITY_HIGHT
|
||||
1000, 1, LocationClientOption.LOC_SENSITIVITY_HIGHT
|
||||
)
|
||||
//需将配置好的LocationClientOption对象,通过setLocOption方法传递给LocationClient对象使用
|
||||
locationClient.locOption = locationOption
|
||||
@@ -130,21 +126,36 @@ class LocationLayerHandler(context: Context, mapView: NIMapView) :
|
||||
/**
|
||||
* 回到当前位置
|
||||
*/
|
||||
fun animateToCurrentPosition()
|
||||
{
|
||||
fun animateToCurrentPosition(zoom: Double) {
|
||||
|
||||
mCurrentLocation?.run {
|
||||
val mapPosition = mMapView.vtmMap.mapPosition;
|
||||
mapPosition.setPosition(this.latitude, this.longitude);
|
||||
mMapView.vtmMap.animator().animateTo(300, mapPosition);
|
||||
val mapPosition = mMapView.vtmMap.mapPosition
|
||||
mapPosition.zoom = zoom
|
||||
mapPosition.setPosition(this.latitude, this.longitude)
|
||||
mMapView.vtmMap.animator().animateTo(300, mapPosition)
|
||||
}
|
||||
}
|
||||
|
||||
fun animateToCurrentPosition() {
|
||||
mCurrentLocation?.run {
|
||||
val mapPosition = mMapView.vtmMap.mapPosition
|
||||
mapPosition.setPosition(this.latitude, this.longitude)
|
||||
mMapView.vtmMap.animator().animateTo(300, mapPosition)
|
||||
}
|
||||
}
|
||||
|
||||
fun getCurrentGeoPoint(): GeoPoint? {
|
||||
mCurrentLocation?.let {
|
||||
return GeoPoint(it.latitude, it.longitude)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现定位回调
|
||||
*/
|
||||
private class MyLocationListener(callback: (BDLocation) -> Unit) :
|
||||
BDAbstractLocationListener() {
|
||||
private class MyLocationListener(callback: (BDLocation) -> Unit) : BDAbstractLocationListener() {
|
||||
val call = callback;
|
||||
override fun onReceiveLocation(location: BDLocation) {
|
||||
call(location)
|
||||
|
||||
+83
-57
@@ -1,75 +1,101 @@
|
||||
package com.navinfo.collect.library.map.handler
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.BitmapFactory
|
||||
import com.navinfo.collect.library.R
|
||||
import com.navinfo.collect.library.map.GeoPoint
|
||||
import com.navinfo.collect.library.map.NIMapView
|
||||
import com.navinfo.collect.library.utils.StringUtil
|
||||
import org.oscim.core.GeoPoint
|
||||
import org.oscim.android.canvas.AndroidBitmap
|
||||
import org.oscim.layers.marker.ItemizedLayer
|
||||
import org.oscim.layers.marker.ItemizedLayer.OnItemGestureListener
|
||||
import org.oscim.layers.marker.MarkerInterface
|
||||
import org.oscim.layers.marker.MarkerItem
|
||||
import org.oscim.layers.marker.MarkerSymbol
|
||||
|
||||
/**
|
||||
* marker 操作
|
||||
*/
|
||||
open class MarkHandler(context: Context, mapView:NIMapView) :
|
||||
BaseHandler(context, mapView), OnItemGestureListener<MarkerInterface> {
|
||||
class MarkHandler(context: Context, mapView: NIMapView) :
|
||||
BaseHandler(context, mapView) {
|
||||
|
||||
// //增加marker
|
||||
// fun addMarker(
|
||||
// geoPoint: GeoPoint,
|
||||
// title: String?,
|
||||
// description: String? = ""
|
||||
// ): MarkerItem {
|
||||
// var marker: MarkerItem? = null
|
||||
// for (e in mMapView.layerManager.defaultMarkerLayer.itemList) {
|
||||
// if (e is MarkerItem && e.title == title) {
|
||||
// marker = e;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (marker == null) {
|
||||
// var tempTitle = title;
|
||||
// if (tempTitle.isNullOrBlank()) {
|
||||
// tempTitle = StringUtil.createUUID();
|
||||
// }
|
||||
// val marker = MarkerItem(
|
||||
// tempTitle,
|
||||
// description,
|
||||
// geoPoint
|
||||
// )
|
||||
// mMapView.layerManager.defaultMarkerLayer.addItem(marker);
|
||||
// mMapView.vtmMap.updateMap(true)
|
||||
// return marker
|
||||
// } else {
|
||||
// marker.description = description
|
||||
// marker.geoPoint = geoPoint
|
||||
// mMapView.layerManager.defaultMarkerLayer.removeItem(marker)
|
||||
// mMapView.layerManager.defaultMarkerLayer.addItem(marker)
|
||||
// mMapView.vtmMap.updateMap(true)
|
||||
// return marker
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun removeMarker(title: String) {
|
||||
// var marker: MarkerItem? = null
|
||||
// for (e in mMapView.layerManager.defaultMarkerLayer.itemList) {
|
||||
// if (e is MarkerItem && e.title == title) {
|
||||
// marker = e;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (marker != null) {
|
||||
// mMapView.layerManager.defaultMarkerLayer.removeItem(marker)
|
||||
// mMapView.vtmMap.updateMap(true)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
override fun onItemSingleTapUp(index: Int, item: MarkerInterface): Boolean {
|
||||
return false
|
||||
// //默认marker图层
|
||||
private var mDefaultMarkerLayer: ItemizedLayer
|
||||
|
||||
init {
|
||||
//新增marker图标样式
|
||||
val mDefaultBitmap =
|
||||
AndroidBitmap(BitmapFactory.decodeResource(context.resources, R.mipmap.marker));
|
||||
|
||||
val markerSymbol = MarkerSymbol(
|
||||
mDefaultBitmap,
|
||||
MarkerSymbol.HotspotPlace.BOTTOM_CENTER
|
||||
);
|
||||
//新增marker图层
|
||||
mDefaultMarkerLayer = ItemizedLayer(
|
||||
mapView.vtmMap,
|
||||
ArrayList<MarkerInterface>(),
|
||||
markerSymbol,
|
||||
object : OnItemGestureListener<MarkerInterface> {
|
||||
override fun onItemSingleTapUp(index: Int, item: MarkerInterface?): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onItemLongPress(index: Int, item: MarkerInterface?): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
addLayer(mDefaultMarkerLayer, NIMapView.LAYER_GROUPS.OPERATE);
|
||||
}
|
||||
|
||||
override fun onItemLongPress(index: Int, item: MarkerInterface): Boolean {
|
||||
return false
|
||||
//增加marker
|
||||
fun addMarker(
|
||||
geoPoint: GeoPoint,
|
||||
title: String?,
|
||||
description: String? = ""
|
||||
) {
|
||||
var marker: MarkerItem? = null
|
||||
for (e in mDefaultMarkerLayer.itemList) {
|
||||
if (e is MarkerItem && e.title == title) {
|
||||
marker = e
|
||||
break
|
||||
}
|
||||
}
|
||||
if (marker == null) {
|
||||
var tempTitle = title;
|
||||
if (tempTitle.isNullOrBlank()) {
|
||||
tempTitle = StringUtil.createUUID();
|
||||
}
|
||||
val marker = MarkerItem(
|
||||
tempTitle,
|
||||
description,
|
||||
org.oscim.core.GeoPoint(geoPoint.latitude, geoPoint.longitude)
|
||||
)
|
||||
mDefaultMarkerLayer.addItem(marker);
|
||||
mMapView.vtmMap.updateMap(true)
|
||||
} else {
|
||||
marker.description = description
|
||||
marker.geoPoint = org.oscim.core.GeoPoint(geoPoint.latitude, geoPoint.longitude)
|
||||
mDefaultMarkerLayer.removeItem(marker)
|
||||
mDefaultMarkerLayer.addItem(marker)
|
||||
mMapView.vtmMap.updateMap(true)
|
||||
}
|
||||
}
|
||||
|
||||
fun removeMarker(title: String) {
|
||||
var marker: MarkerItem? = null
|
||||
for (e in mDefaultMarkerLayer.itemList) {
|
||||
if (e is MarkerItem && e.title == title) {
|
||||
marker = e
|
||||
break
|
||||
}
|
||||
}
|
||||
if (marker != null) {
|
||||
mDefaultMarkerLayer.removeItem(marker)
|
||||
mMapView.vtmMap.updateMap(true)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-2
@@ -7,7 +7,6 @@ import org.oscim.core.GeoPoint
|
||||
import org.oscim.core.Point
|
||||
|
||||
open class ViewportHandler(context: Context, mapView: NIMapView) : BaseHandler(context, mapView) {
|
||||
|
||||
/**
|
||||
* Set pivot horizontal / vertical relative to view center in [-1, 1].
|
||||
* e.g. pivotY 0.5 is usually preferred for navigation, moving center to 25% of view height.
|
||||
@@ -73,7 +72,7 @@ open class ViewportHandler(context: Context, mapView: NIMapView) : BaseHandler(c
|
||||
px: Float, py: Float
|
||||
): Map<String, Any> {
|
||||
|
||||
val geo = mMapView.vtmMap.viewport().fromScreenPoint(px,py)
|
||||
val geo = mMapView.vtmMap.viewport().fromScreenPoint(px, py)
|
||||
|
||||
return mapOf(
|
||||
"latitude" to geo.latitude,
|
||||
|
||||
+14
-67
@@ -1,39 +1,38 @@
|
||||
package com.navinfo.collect.library.map.source;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.navinfo.collect.library.system.Constant;
|
||||
|
||||
import org.oscim.core.BoundingBox;
|
||||
import org.oscim.core.MapElement;
|
||||
import org.oscim.core.Tag;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.tiling.ITileDataSource;
|
||||
import org.oscim.tiling.OverzoomTileDataSource;
|
||||
import org.oscim.tiling.source.UrlTileSource;
|
||||
import org.oscim.tiling.source.geojson.GeojsonTileSource;
|
||||
import org.oscim.tiling.source.mapfile.IMapFileTileSource;
|
||||
import org.oscim.tiling.source.mapfile.MapDatabase;
|
||||
import org.oscim.tiling.source.mapfile.MapFileTileSource;
|
||||
import org.oscim.utils.FastMath;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
*com.navinfo.map.source
|
||||
*com.nmp.map.source
|
||||
*zhjch
|
||||
*2021/9/17
|
||||
*9:46
|
||||
*说明()
|
||||
*/
|
||||
public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements IMapFileTileSource {
|
||||
public class NavinfoMultiMapFileTileSource extends UrlTileSource implements IMapFileTileSource {
|
||||
|
||||
// private static final String DEFAULT_URL = "http://cmp-gateway-sp9-port.ayiqdpfs.cloud.app.ncloud.navinfo.com/maponline/map/online";
|
||||
private static final String DEFAULT_URL = "http://epohvqjxts85k6u-port.ayiqdpfs.cloud.app.ncloud.navinfo.com/map/online/geoJson";
|
||||
private static final String DEFAULT_PATH = "x={X}&y={Y}&z={Z}";
|
||||
private static final String DEFAULT_URL = "http://c.tile.opencyclemap.org/cycle";
|
||||
|
||||
private static final String DEFAULT_PATH = "/{Z}}/{X}/{Y}.png";
|
||||
private static final TileUrlFormatter mTileUrlFormatter = URL_FORMATTER;
|
||||
|
||||
|
||||
@@ -67,7 +66,6 @@ public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements
|
||||
public String getTileUrl(Tile tile) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(DEFAULT_URL).append("?").append(mTileUrlFormatter.formatTilePath(this, tile));
|
||||
System.out.println(sb.toString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -125,66 +123,13 @@ public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements
|
||||
mapDatabase.restrictToZoomRange(zoomLevels[0], zoomLevels[1]);
|
||||
multiMapDatabase.add(mapDatabase);
|
||||
} catch (IOException e) {
|
||||
Log.e("jingo", e.getMessage());
|
||||
log.debug(e.getMessage());
|
||||
}
|
||||
}
|
||||
// return new NavinfoMultiMapDatabase(this, new NavinfoVectorTileDecoder(locale), getHttpEngine());
|
||||
return new OverzoomTileDataSource(multiMapDatabase, mOverZoom);
|
||||
}
|
||||
private static Map<String, Tag> mappings = new LinkedHashMap<>();
|
||||
|
||||
private static Tag addMapping(String key, String val) {
|
||||
Tag tag = new Tag(key, val);
|
||||
mappings.put(key + "=" + val, tag);
|
||||
return tag;
|
||||
}
|
||||
@Override
|
||||
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
|
||||
boolean hasName = false;
|
||||
String fallbackName = null;
|
||||
|
||||
for (Map.Entry<String, Object> entry : properties.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
String val = (value instanceof String) ? (String) value : String.valueOf(value);
|
||||
|
||||
if (key.startsWith(Tag.KEY_NAME)) {
|
||||
int len = key.length();
|
||||
if (len == 4) {
|
||||
fallbackName = val;
|
||||
continue;
|
||||
}
|
||||
if (len < 7)
|
||||
continue;
|
||||
if (locale.equals(key.substring(5))) {
|
||||
hasName = true;
|
||||
mapElement.tags.add(new Tag(Tag.KEY_NAME, val, false));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Tag tag = mappings.get(key + "=" + val);
|
||||
if (tag == null)
|
||||
tag = addMapping(key, val);
|
||||
mapElement.tags.add(tag);
|
||||
}
|
||||
|
||||
if (!hasName && fallbackName != null)
|
||||
mapElement.tags.add(new Tag(Tag.KEY_NAME, fallbackName, false));
|
||||
|
||||
// Calculate height of building parts
|
||||
if (!properties.containsKey(Tag.KEY_HEIGHT)) {
|
||||
if (properties.containsKey(Tag.KEY_VOLUME) && properties.containsKey(Tag.KEY_AREA)) {
|
||||
Object volume = properties.get(Tag.KEY_VOLUME);
|
||||
String volumeStr = (volume instanceof String) ? (String) volume : String.valueOf(volume);
|
||||
Object area = properties.get(Tag.KEY_AREA);
|
||||
String areaStr = (area instanceof String) ? (String) area : String.valueOf(area);
|
||||
float height = Float.parseFloat(volumeStr) / Float.parseFloat(areaStr);
|
||||
String heightStr = String.valueOf(FastMath.round2(height));
|
||||
mapElement.tags.add(new Tag(Tag.KEY_HEIGHT, heightStr, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenResult open() {
|
||||
@@ -194,8 +139,10 @@ public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements
|
||||
if (result != OpenResult.SUCCESS)
|
||||
openResult = result;
|
||||
}
|
||||
if(openResult != OpenResult.SUCCESS)
|
||||
return super.open();
|
||||
if(openResult != OpenResult.SUCCESS) {
|
||||
|
||||
return super.open();
|
||||
}
|
||||
return openResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ import java.util.Map;
|
||||
|
||||
public class Constant {
|
||||
|
||||
//服务地址
|
||||
public static String URL_BASE = "http://cmp-gateway-sp9-port.ayiqdpfs.cloud.app.ncloud.navinfo.com/";
|
||||
|
||||
public static String MAP_PATH = Environment.getExternalStorageDirectory() + "/map/";
|
||||
|
||||
public static void setVisibleTypeMap(Map<String, Boolean> visibleTypeMap) {
|
||||
|
||||
@@ -10,7 +10,7 @@ class GeometryToolsKt {
|
||||
/**
|
||||
* 根据给定的geometry计算其横跨的20级瓦片Y值
|
||||
*/
|
||||
fun getTileYByGeometry(wkt: String, tileYSet: MutableSet<Int?>): Set<Int?>? {
|
||||
fun getTileYByGeometry(wkt: String, tileYSet: MutableSet<Int?>){
|
||||
|
||||
val reader = WKTReader()
|
||||
val geometry = reader.read(wkt);
|
||||
@@ -20,6 +20,7 @@ class GeometryToolsKt {
|
||||
if (tileYSet == null) {
|
||||
tileYSet = RealmSet()
|
||||
}
|
||||
tileYSet.clear()
|
||||
val envelope = geometry.envelope
|
||||
if (envelope != null) {
|
||||
val coordinates = envelope.coordinates
|
||||
@@ -48,13 +49,12 @@ class GeometryToolsKt {
|
||||
}
|
||||
}
|
||||
println("YGeometry-time:" + (System.currentTimeMillis() - startTime))
|
||||
return tileYSet
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据给定的geometry计算其横跨的20级瓦片X值
|
||||
*/
|
||||
fun getTileXByGeometry(wkt: String, tileXSet: MutableSet<Int?>): Set<Int?>? {
|
||||
fun getTileXByGeometry(wkt: String, tileXSet: MutableSet<Int?>) {
|
||||
val reader = WKTReader()
|
||||
val geometry = reader.read(wkt);
|
||||
|
||||
@@ -63,6 +63,7 @@ class GeometryToolsKt {
|
||||
if (tileXSet == null) {
|
||||
tileXSet = RealmSet()
|
||||
}
|
||||
tileXSet.clear()
|
||||
if (geometry != null) {
|
||||
val envelope = geometry.envelope
|
||||
if (envelope != null) {
|
||||
@@ -92,7 +93,6 @@ class GeometryToolsKt {
|
||||
}
|
||||
}
|
||||
println("XGeometry-time:" + (System.currentTimeMillis() - startTime))
|
||||
return tileXSet
|
||||
}
|
||||
|
||||
fun getMasterPoint(wkt: String): String {
|
||||
|
||||
+9
-7
@@ -1,30 +1,32 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
google()
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
maven { url 'https://jitpack.io' }
|
||||
maven { url "https://maven.aliyun.com/repository/google" }
|
||||
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
|
||||
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||
maven { url 'https://maven.aliyun.com/repository/jcenter' }
|
||||
maven { url 'https://download.flutter.io' }
|
||||
maven { url 'https://storage.googleapis.com/download.flutter.io' }
|
||||
maven { url 'https://maven.aliyun.com/repository/central' }
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven { url 'https://jitpack.io' }
|
||||
|
||||
maven { url "https://maven.aliyun.com/repository/google" }
|
||||
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
|
||||
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||
maven { url 'https://maven.aliyun.com/repository/jcenter' }
|
||||
maven { url 'https://download.flutter.io' }
|
||||
maven { url 'https://storage.googleapis.com/download.flutter.io' }
|
||||
maven { url 'https://maven.aliyun.com/repository/central' }
|
||||
maven { url 'https://jitpack.io' }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
rootProject.name = "OMQualityInspection"
|
||||
|
||||
Reference in New Issue
Block a user