fix: 合并代码

This commit is contained in:
xiaoyan 2023-04-19 15:46:16 +08:00
commit 7ea778780c
42 changed files with 1756 additions and 478 deletions

View File

@ -45,12 +45,8 @@ android {
dependencies {
implementation project(':collect-library')
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.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'

View File

@ -2,6 +2,7 @@ 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
@ -24,6 +25,8 @@ class OMQSApplication : Application() {
.directory(File(Constant.DATA_PATH))
.name("OMQS.realm")
.encryptionKey(password)
.modules(Realm.getDefaultModule(), MyRealmModule())
.schemaVersion(1)
.build()
Realm.setDefaultConfiguration(config)
}

View File

@ -1,6 +0,0 @@
package com.navinfo.omqs.bean
import java.io.Serializable
open class BaseBean : Serializable, Cloneable {
}

View File

@ -1,115 +0,0 @@
package com.navinfo.omqs.bean
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
/**
* @author zhjch
* @version V1.0
* @ClassName: Rd_qcRecord
* @Date 2016/1/12
* @Description: ${TODO}(质检对象)
*/
open class QsRecord @JvmOverloads constructor(
/**
* id 主键
*
*/
@PrimaryKey var id: String = "",
/**
* linkPid 绑定的道路ID
*/
var linkPid: String = "",
/**
*问题分类
*/
var classType: String = "",
/**
* 问题类型
*/
var type: String = "",
/**
* 问题现象
*/
var phenomenon: String = "",
/**
* 问题描述
*/
var description: String = "",
/**
* 设置initial_cause
* @param initial_cause
* initial_cause
*/
// var initial_cause: String? = StringEntity.STRING_DEFAULT
// /**
// * 获取root_cause
// * @return root_cause
// */
// /**
// * 设置root_cause
// * @param root_cause
// * root_cause
// */
////根本原因RCA
// var root_cause: String? = StringEntity.STRING_DEFAULT
// /**
// * 获取check_userid
// * @return check_userid
// */
// /**
// * 设置check_userid
// * @param check_userid
// * check_userid
// */
////质检员
// var check_userid: String? = StringEntity.STRING_DEFAULT
// /**
// * 获取check_time
// * @return check_time
// */
// /**
// * 设置check_time
// * @param check_time
// * check_time
// */
////质检日期
// var check_time: String? = StringEntity.STRING_DEFAULT
// /**
// * 获取confirm_userid
// * @return confirm_userid
// */
// /**
// * 设置confirm_userid
// * @param confirm_userid
// * confirm_userid
// */
////确认人
// var confirm_userid: String? = StringEntity.STRING_DEFAULT
// /**
// * 获取t_lifecycle
// * @return t_lifecycle
// */
// /**
// * 设置t_lifecycle
// * @param t_lifecycle
// * t_lifecycle
// */
////状态 0 无; 1 删除2 更新3 新增;
// var t_lifecycle = 0
// /**
// * 获取t_status
// * @return t_status
// */
// /**
// * 设置t_status
// * @param t_status
// * t_status
// */
////问题记录提交状态 0 未提交1 已提交;
// var t_status = 0
) : RealmObject(
)

View File

@ -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 {
}

View File

@ -1,8 +1,6 @@
package com.navinfo.omqs.db.dao
import androidx.room.*
import androidx.sqlite.db.SupportSQLiteDatabase
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase.getDatabase
import com.navinfo.omqs.bean.ScProblemTypeBean
@ -38,13 +36,13 @@ interface ScProblemTypeDao {
/**
* 获取问题类型并去重
*/
@Query("select DISTINCT TYPE from ScProblemType where CLASS_TYPE=:type order by TYPE")
suspend fun findProblemTypeList(type: String): 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>
// /**
// *
// */
// @Query("select PHENOMENON from ScProblemType where CLASS_TYPE=:classType and TYPE=:type order by PHENOMENON")
// suspend fun getPhenomenonList(classType: String, type: String): List<String>
}

View File

@ -22,4 +22,10 @@ interface ScRootCauseAnalysisDao {
insertList(list)
}
/**
* 获取问题环节数据
*/
@Query("select * from ScRootCauseAnalysis order by PROBLEM_LINK")
suspend fun findAllData(): List<ScRootCauseAnalysisBean>?
}

View File

@ -35,6 +35,7 @@ class MainActivityModule {
/**
* 实验失败这样创建viewmodel不会在activity销毁的时候同时销毁
* 4-14:因为没有传入activity的 owner,无法检测生命周期
*/
// @ActivityRetainedScoped
// @Provides

View File

@ -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()

View File

@ -141,7 +141,8 @@ class LoginViewModel @Inject constructor(
.show()
}
}
NetResult.Loading -> {}
is NetResult.Loading -> {}
else -> {}
}
loginStatus.postValue(LoginStatus.LOGIN_STATUS_SUCCESS)
}

View File

@ -6,6 +6,7 @@ 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
@ -52,7 +53,7 @@ class MainActivity : BaseActivity() {
//给xml传递viewModel对象
binding.viewModel = viewModel
// lifecycle.addObserver(viewModel)
lifecycleScope
}
override fun onStart() {
@ -92,4 +93,8 @@ class MainActivity : BaseActivity() {
val naviController = findNavController(R.id.main_activity_right_fragment)
naviController.navigate(R.id.EvaluationResultFragment)
}
override fun onBackPressed() {
super.onBackPressed()
}
}

View File

@ -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
}
}

View File

@ -1,16 +0,0 @@
package com.navinfo.omqs.ui.fragment.evaluationresult
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
class EvaluationResultAdapter(activity: FragmentActivity, val fragmentList: List<Fragment>) :
FragmentStateAdapter(activity) {
override fun getItemCount(): Int {
return fragmentList.size
}
override fun createFragment(position: Int): Fragment {
return fragmentList[position]
}
}

View File

@ -4,128 +4,251 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.tabs.TabLayoutMediator
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 : Fragment() {
class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
private var _binding: FragmentEvaluationResultBinding? = null
private val binding get() = _binding!!
private val viewModel by lazy { viewModels<EvaluationResultViewModel>().value }
private var phenomenonFragmentAdapter: EvaluationResultAdapter? = null
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)
//返回按钮
binding.evaluationBar.setNavigationOnClickListener {
findNavController().popBackStack()
}
//监听数据变化
viewModel.classTypeListLiveData.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)
}
}
//选择问题分类的回调
binding.evaluationClassType.onItemSelectedListener =
object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?, view: View?, position: Int, id: Long
) {
viewModel.getProblemTypeList(position)
}
liveDataObserve()
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.evaluationClassType.setOnClickListener(this)
binding.evaluationProblemType.setOnClickListener(this)
binding.evaluationPhenomenon.setOnClickListener(this)
binding.evaluationLink.setOnClickListener(this)
binding.evaluationCause.setOnClickListener(this)
//返回按钮点击
binding.evaluationBar.setNavigationOnClickListener {
onBackPressed()
}
//获取数据
viewModel.getClassTypeList()
binding.evaluationViewpager.registerOnPageChangeCallback(object :
ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
updateHeight(position)
//标题栏按钮
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
}
}
// 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 -> {}
}
}
}
}

View File

@ -1,73 +1,242 @@
package com.navinfo.omqs.ui.fragment.evaluationresult
import android.util.Log
import androidx.lifecycle.LiveData
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 okhttp3.Dispatcher
import java.util.*
import javax.inject.Inject
@HiltViewModel
class EvaluationResultViewModel @Inject constructor(
private val roomAppDatabase: RoomAppDatabase,
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()
}
/**
* 问题分类 liveData
*/
val classTypeListLiveData = MutableLiveData<List<String>?>()
/**
* 问题类型 liveData
*/
val problemTypeListLiveData = MutableLiveData<List<String>>()
var currentClassType: String = ""
/**
* 查询数据库获取问题分类
*/
fun loadMetadata() {
viewModelScope.launch(Dispatchers.IO) {
getClassTypeList()
getProblemLinkList()
}
}
/**
* //获取问题分类列表
*/
fun getClassTypeList() {
viewModelScope.launch(Dispatchers.IO) {
val list = roomAppDatabase.getScProblemTypeDao().findClassTypeList()
classTypeListLiveData.postValue(list)
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(index: Int) {
fun getProblemTypeList(classType: String) {
viewModelScope.launch(Dispatchers.IO) {
classTypeListLiveData.value?.let {
if (index < it.size) {
currentClassType = it[index]
val list =
roomAppDatabase.getScProblemTypeDao().findProblemTypeList(currentClassType)
problemTypeListLiveData.postValue(list)
}
}
liveDataCurrentClassType.postValue(classType)
getProblemList(classType)
}
}
fun getPhenomenonList() {
viewModelScope.launch (Dispatchers.IO){
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() {
}
}

View File

@ -1,24 +0,0 @@
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 PhenomenonAdapter() : BaseRecyclerViewAdapter<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) {
(holder.viewBinding as TextItemSelectBinding).itemId.text = data[position]
}
}

View File

@ -6,45 +6,111 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
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.db.RoomAppDatabase
import com.navinfo.omqs.ui.fragment.BaseFragment
import com.navinfo.omqs.ui.other.shareViewModels
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import javax.inject.Inject
@AndroidEntryPoint
class PhenomenonFragment(private val classType: String, private val title: String) :
Fragment() {
@Inject
lateinit var roomAppDatabase: RoomAppDatabase
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?,
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.phenomenonRecyclerview.setHasFixedSize(true)
binding.phenomenonRecyclerview.layoutManager = LinearLayoutManager(context)
val adapter = PhenomenonAdapter()
binding.phenomenonRecyclerview.adapter = adapter
lifecycleScope.launch {
Log.e("jingo", "$classType $title ")
val list = roomAppDatabase.getScProblemTypeDao().getPhenomenonList(classType, title)
Log.e("jingo", "${list.toString()}")
adapter.refreshData(list)
//左侧菜单
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() {

View File

@ -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()
}
}
}

View File

@ -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()
}
}
}

View File

@ -0,0 +1,6 @@
package com.navinfo.omqs.ui.fragment.evaluationresult
/**
* 问题现象列表
*/
data class PhenomenonMiddleBean(val title: String, val text: String, var isSelect: Boolean = false)

View File

@ -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)
}
}
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -0,0 +1,5 @@
package com.navinfo.omqs.ui.other
interface AdapterItemClickListener {
fun onItemClick(position: Int)
}

View File

@ -37,27 +37,28 @@ abstract class BaseRecyclerViewAdapter<T>(var data: List<T> = listOf()) :
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) {

View File

@ -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)
// }
// }
// }
// }
// })
// }
// }
}

View File

@ -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

View File

@ -5,6 +5,7 @@
tools:context=".ui.activity.map.MainActivity">
<data>
<variable
name="mainActivity"
type="com.navinfo.omqs.ui.activity.map.MainActivity" />
@ -27,8 +28,12 @@
<com.navinfo.collect.library.map.NIMapView
android:id="@+id/main_activity_map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
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"
@ -64,21 +69,40 @@
app:layout_constraintRight_toRightOf="parent" />
<fragment
android:id="@+id/main_activity_right_fragment"
android:id="@+id/main_activity_middle_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintHorizontal_bias="0.3"
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_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:layout_constraintHorizontal_bias="0.3"
app:navGraph="@navigation/left_drawer_nav_graph" />
</androidx.drawerlayout.widget.DrawerLayout>
</layout>

View File

@ -45,24 +45,52 @@
android:layout_height="wrap_content"
android:text="问题分类" />
<Spinner
<TextView
android:id="@+id/evaluation_class_type"
android:layout_width="match_parent"
android:layout_height="50dp"
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"
<TextView
android:id="@+id/evaluation_problem_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp" />
android:layout_marginTop="5dp"
android:background="@drawable/fm_card_map_down_status_bg" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/evaluation_viewpager"
<TextView
android:id="@+id/evaluation_phenomenon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp" />
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>

View File

@ -1,15 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<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="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
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">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/phenomenon_recyclerview"
android:layout_width="match_parent"
<ImageView
android:id="@+id/phenomenon_drawer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
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>

View File

@ -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>

View File

@ -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>

View File

@ -63,10 +63,19 @@ android {
dependencies {
api fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
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.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation 'com.yanzhenjie:kalle:0.1.7'
// implementation 'com.yanzhenjie:kalle:0.1.7'
// VTM依赖
implementation "net.sf.kxml:kxml2:2.3.0"

View File

@ -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)
}
}

View File

@ -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)"
}
}

View File

@ -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)
@ -38,5 +39,6 @@ class NIMapController {
mMapView.vtmMap.viewport().maxZoomLevel = Constant.MAX_ZOOM // 设置地图的最大级别
}
}

View File

@ -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;
}

View File

@ -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)
}
}

View File

@ -1,15 +1,21 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
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.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.backend.CanvasAdapter
import org.oscim.backend.canvas.Paint
import org.oscim.layers.GroupLayer
import org.oscim.layers.Layer
import org.oscim.layers.tile.bitmap.BitmapTileLayer
import org.oscim.layers.tile.buildings.BuildingLayer
import org.oscim.layers.tile.vector.VectorTileLayer
import org.oscim.layers.tile.vector.labeling.LabelLayer
@ -20,11 +26,22 @@ import java.io.File
/**
* Layer 操作
*/
class LayerManagerHandler(context: Context, mapView: NIMapView) :
class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) :
BaseHandler(context, mapView) {
private var baseGroupLayer // 用于盛放所有基础底图的图层组,便于统一管理
: GroupLayer? = null
/**
* 默认文字颜色
*/
private val mDefaultTextColor = "#4E55AF"
/**
* 文字画笔
*/
private lateinit var paint: Paint
init {
initMap()
}
@ -36,8 +53,9 @@ class LayerManagerHandler(context: Context, mapView: NIMapView) :
loadBaseMap()
mMapView.switchTileVectorLayerTheme(NIMapView.MAP_THEME.DEFAULT)
//初始化之间数据图层
initQsRecordDataLayer()
mMapView.vtmMap.updateMap()
// initVectorTileLayer()
// initMapLifeSource()
}
@ -46,7 +64,7 @@ class LayerManagerHandler(context: Context, mapView: NIMapView) :
* 切换基础底图样式
*/
fun loadBaseMap() {
//给地图layer分组
if (baseGroupLayer == null) {
baseGroupLayer = GroupLayer(mMapView.vtmMap)
addLayer(baseGroupLayer!!, NIMapView.LAYER_GROUPS.BASE)
@ -90,8 +108,11 @@ class LayerManagerHandler(context: Context, mapView: NIMapView) :
}
}
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)
@ -101,26 +122,45 @@ class LayerManagerHandler(context: Context, mapView: NIMapView) :
}
}
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)
}
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)
return BitmapTileLayer(mMapView.vtmMap, mTileSource)
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)
// }
}
/**

View File

@ -8,6 +8,7 @@ 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
@ -142,6 +143,13 @@ class LocationLayerHandler(context: Context, mapView: NIMapView) : BaseHandler(c
mMapView.vtmMap.animator().animateTo(300, mapPosition)
}
}
fun getCurrentGeoPoint(): GeoPoint? {
mCurrentLocation?.let {
return GeoPoint(it.latitude, it.longitude)
}
return null
}
}
/**

View File

@ -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)
}
}
}

View File

@ -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,