This commit is contained in:
qiji4215 2023-07-07 18:06:38 +08:00
commit c8c7c4d4ce
36 changed files with 3637 additions and 135 deletions

View File

@ -127,6 +127,10 @@ dependencies {
implementation "androidx.camera:camera-view:1.0.0-alpha24"
implementation 'com.google.mlkit:barcode-scanning:16.1.1'
//
implementation 'com.github.bumptech.glide:glide:4.15.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.15.1'
}
//
kapt {

View File

@ -184,8 +184,39 @@ class MainActivity : BaseActivity() {
}
//捕捉列表变化回调
viewModel.liveDataQsRecordIdList.observe(this) {
//处理页面跳转
viewModel.navigationRightFragment(this, it)
//跳转到质检数据页面
//获取右侧fragment容器
val naviController = findNavController(R.id.main_activity_right_fragment)
naviController.currentDestination?.let { navDestination ->
when (navDestination.id) {
R.id.RightEmptyFragment -> {
if (it.size == 1) {
val bundle = Bundle()
bundle.putString("QsId", it[0])
naviController.navigate(R.id.EvaluationResultFragment, bundle)
}
}
}
}
}
//捕捉列表变化回调
viewModel.liveDataNoteIdList.observe(this) {
//跳转到质检数据页面
//获取右侧fragment容器
val naviController = findNavController(R.id.main_activity_right_fragment)
naviController.currentDestination?.let { navDestination ->
when (navDestination.id) {
R.id.RightEmptyFragment -> {
if (it.size == 1) {
val bundle = Bundle()
bundle.putString("NoteId", it[0])
naviController.navigate(R.id.NoteFragment, bundle)
}
}
}
}
}
//右上角菜单是否被点击
viewModel.liveDataMenuState.observe(this) {
@ -253,7 +284,7 @@ class MainActivity : BaseActivity() {
}
}
viewModel.liveDataSignMoreInfo.observe(this){
viewModel.liveDataSignMoreInfo.observe(this) {
val fragment =
supportFragmentManager.findFragmentById(R.id.main_activity_sign_more_info_fragment)
if (fragment == null) {
@ -432,10 +463,17 @@ class MainActivity : BaseActivity() {
/**
* 隐藏或显示右侧展开按钮
*/
fun setRightSwitchButton(visibility: Int) {
fun setRightSwitchButtonVisibility(visibility: Int) {
binding.mainActivityFragmentSwitch.visibility = visibility
}
/**
* 顶部菜单按钮
*/
fun setTopMenuButtonVisibility(visibility: Int) {
binding.mainActivityMenu.visibility = visibility
}
/**
* 点击录音按钮
*/
@ -557,4 +595,20 @@ class MainActivity : BaseActivity() {
viewModel.showSignMoreInfo(viewModel.liveDataRoadName.value!!)
}
}
/**
* 新增便签,打开便签fragment
*/
fun onClickNewNote() {
rightController.navigate(R.id.NoteFragment)
binding.mainActivityMenu.isSelected = false
binding.mainActivityMenuGroup.visibility = View.INVISIBLE
}
/**
* 右侧按钮+经纬度按钮
*/
fun setRightButtonsVisible(visible: Int) {
binding.mainActivityRightVisibilityButtonsGroup2.visibility = visible
}
}

View File

@ -71,6 +71,9 @@ class MainViewModel @Inject constructor(
//地图点击捕捉到的质检数据ID列表
val liveDataQsRecordIdList = MutableLiveData<List<String>>()
//地图点击捕捉到的标签ID列表
val liveDataNoteIdList = MutableLiveData<List<String>>()
//左侧看板数据
val liveDataSignList = MutableLiveData<List<SignBean>>()
@ -128,6 +131,10 @@ class MainViewModel @Inject constructor(
override fun onQsRecordList(list: MutableList<String>) {
liveDataQsRecordIdList.value = list
}
override fun onNoteList(list: MutableList<String>) {
liveDataNoteIdList.value = list
}
})
initLocation()
//处理地图点击操作
@ -295,7 +302,8 @@ class MainViewModel @Inject constructor(
}
}
liveDataTopSignList.postValue(topSignList.distinctBy { it.name }.sortedBy { it.index })
liveDataTopSignList.postValue(topSignList.distinctBy { it.name }
.sortedBy { it.index })
liveDataSignList.postValue(signList.sortedBy { it.distance })
val speechText = SignUtil.getRoadSpeechText(topSignList)
@ -470,25 +478,6 @@ class MainViewModel @Inject constructor(
}
}
/**
* 处理页面调转
*/
fun navigationRightFragment(activity: MainActivity, list: List<String>) {
//获取右侧fragment容器
val naviController = activity.findNavController(R.id.main_activity_right_fragment)
naviController.currentDestination?.let { navDestination ->
when (navDestination.id) {
R.id.RightEmptyFragment -> {
if (list.size == 1) {
val bundle = Bundle()
bundle.putString("QsId", list[0])
naviController.navigate(R.id.EvaluationResultFragment, bundle)
}
}
}
}
}
/**
* 开启线选择

View File

@ -32,18 +32,27 @@ class EmptyFragment : Fragment() {
override fun onStart() {
super.onStart()
val currentDestination = findNavController().currentDestination
//有右侧面板的时候
if (currentDestination?.label == "右侧空页面") {
currentDestinationLabel = "右侧空页面"
(activity as MainActivity).setRightSwitchButton(View.GONE)
currentDestination?.let {
//有右侧面板的时候
currentDestinationLabel = it.label.toString()
if (it.label == "右侧空页面") {
(activity as MainActivity).setRightSwitchButtonVisibility(View.GONE)
(activity as MainActivity).setTopMenuButtonVisibility(View.VISIBLE)
} else if (it.label == "中间空页面") {
(activity as MainActivity).setRightButtonsVisible(View.VISIBLE)
}
}
}
override fun onStop() {
super.onStop()
//没有有右侧面板的时候
if (currentDestinationLabel == "右侧空页面") {
(activity as MainActivity).setRightSwitchButton(View.VISIBLE)
(activity as MainActivity).setRightSwitchButtonVisibility(View.VISIBLE)
(activity as MainActivity).setTopMenuButtonVisibility(View.GONE)
} else if (currentDestinationLabel == "中间空页面") {
(activity as MainActivity).setRightButtonsVisible(View.GONE)
}
}

View File

@ -1,12 +1,16 @@
package com.navinfo.omqs.ui.fragment.evaluationresult
import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.*
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.databinding.DataBindingUtil
import androidx.navigation.NavOptions
import androidx.navigation.findNavController
@ -21,12 +25,12 @@ import com.navinfo.omqs.ui.dialog.FirstDialog
import com.navinfo.omqs.ui.fragment.BaseFragment
import com.navinfo.omqs.ui.other.shareViewModels
import dagger.hilt.android.AndroidEntryPoint
import org.videolan.vlc.Util
@AndroidEntryPoint
class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
private lateinit var binding: FragmentEvaluationResultBinding
private var mCameraLauncher: ActivityResultLauncher<Intent>? = null
/**
* [PhenomenonFragment],[ProblemLinkFragment],[EvaluationResultFragment]共用同一个viewModel
@ -37,6 +41,23 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
PictureAdapter()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mCameraLauncher = registerForActivityResult<Intent, ActivityResult>(
ActivityResultContracts.StartActivityForResult()
) { result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK) {
// 处理相机返回的结果
val extras = result.data!!.extras
val imageBitmap: Bitmap? = extras!!["data"] as Bitmap?
// 在这里处理图片数据
if (imageBitmap != null)
viewModel.savePhoto(imageBitmap)
}
}
}
// private val args:EmptyFragmentArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
@ -62,7 +83,7 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
adapter.refreshData(it)
}
binding.evaluationPictureViewpager
return binding.root
}
@ -106,15 +127,26 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
val list = mutableListOf("1", "2", "3")
pictureAdapter.refreshData(list)
//照片左右选择键点击监听
binding.evaluationPictureLeft.setOnClickListener(this)
binding.evaluationPictureRight.setOnClickListener(this)
binding.evaluationCamera.setOnClickListener(this)
//设置照片偏移量
val viewPager = binding.evaluationPictureViewpager
val vto = viewPager.viewTreeObserver
vto.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
val width = viewPager.width
// 处理View宽度
// 在回调完成后需要将监听器从View树中移除以避免重复调用
viewPager.viewTreeObserver.removeOnGlobalLayoutListener(this)
val recyclerView = viewPager.getChildAt(0) as RecyclerView
val recyclerView = binding.evaluationPictureViewpager.getChildAt(0) as RecyclerView
recyclerView.setPadding(0, 0, Util.convertDpToPx(requireContext(), 50), 0)
recyclerView.clipToPadding = false
recyclerView.setPadding(0, 0, width / 2 - 30, 0)
recyclerView.clipToPadding = false
}
})
binding.evaluationVoice.setOnTouchListener { _, event ->
Log.e("qj", event?.action.toString())
@ -123,11 +155,7 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
voiceOnTouchStart()//Do Something
}
MotionEvent.ACTION_UP -> {
voiceOnTouchStop()//Do Something
}
MotionEvent.ACTION_CANCEL -> {
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_OUTSIDE -> {
voiceOnTouchStop()//Do Something
}
}
@ -338,7 +366,9 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
}
}
R.id.evaluation_camera -> {
takePhoto()
}
else -> {}
}
}
@ -362,4 +392,16 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
return true
}
private fun takePhoto() {
try {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (takePictureIntent.resolveActivity(requireActivity().packageManager) != null) {
mCameraLauncher!!.launch(takePictureIntent)
}
} catch (e: Exception) {
Log.d("TTTT", e.toString())
}
}
}

View File

@ -3,6 +3,7 @@ package com.navinfo.omqs.ui.fragment.evaluationresult
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.AnimationDrawable
import android.graphics.drawable.BitmapDrawable
import android.os.Build
@ -35,17 +36,13 @@ import com.navinfo.omqs.util.DateTimeUtil
import com.navinfo.omqs.util.SoundMeter
import com.navinfo.omqs.util.SpeakMode
import dagger.hilt.android.lifecycle.HiltViewModel
import io.realm.OrderedCollectionChangeSet
import io.realm.Realm
import io.realm.RealmList
import io.realm.RealmModel
import io.realm.RealmResults
import io.realm.kotlin.addChangeListener
import io.realm.kotlin.where
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.oscim.core.GeoPoint
import java.io.File
import java.io.FileOutputStream
import java.util.*
import javax.inject.Inject
@ -78,9 +75,20 @@ class EvaluationResultViewModel @Inject constructor(
*/
val liveDataRightTypeList = MutableLiveData<List<RightBean>>()
var liveDataQsRecordBean = MutableLiveData<QsRecordBean>()
/**
*
*/
val liveDataQsRecordBean = MutableLiveData<QsRecordBean>()
var listDataChatMsgEntityList = MutableLiveData<MutableList<ChatMsgEntity>>()
/**
* 语音列表
*/
val listDataChatMsgEntityList = MutableLiveData<MutableList<ChatMsgEntity>>()
/**
* 照片列表
*/
val liveDataPictureList = MutableLiveData<MutableList<String>>()
var oldBean: QsRecordBean? = null
@ -201,7 +209,8 @@ class EvaluationResultViewModel @Inject constructor(
var classCode = list[0].elementCode
liveDataLeftTypeList.postValue(it)
if (bean != null) {
val classType2 = roomAppDatabase.getScProblemTypeDao().findClassTypeByCode(bean.renderEntity.code)
val classType2 = roomAppDatabase.getScProblemTypeDao()
.findClassTypeByCode(bean.renderEntity.code)
if (classType2 != null) {
classType = classType2
}
@ -364,13 +373,19 @@ class EvaluationResultViewModel @Inject constructor(
Realm.getDefaultInstance().use { realm ->
realm.executeTransactionAsync { bgRealm ->
// find the item
val objects = bgRealm.where(QsRecordBean::class.java).equalTo("id", id).findFirst()
val objects =
bgRealm.where(QsRecordBean::class.java).equalTo("id", id).findFirst()
if (objects != null) {
oldBean = bgRealm.copyFromRealm(objects)
oldBean?.let {
liveDataQsRecordBean.postValue(it.copy())
val p = GeometryTools.createGeoPoint(it.geometry)
mapController.markerHandle.addMarker(GeoPoint(p.latitude, p.longitude), markerTitle)
mapController.markerHandle.addMarker(
GeoPoint(
p.latitude,
p.longitude
), markerTitle
)
//获取linkid
if (it.linkId.isNotEmpty()) {
@ -381,7 +396,8 @@ class EvaluationResultViewModel @Inject constructor(
}
}
}
liveDataQsRecordBean.value?.attachmentBeanList = it.attachmentBeanList
liveDataQsRecordBean.value?.attachmentBeanList =
it.attachmentBeanList
// 显示语音数据到界面
getChatMsgEntityList()
}
@ -508,9 +524,42 @@ class EvaluationResultViewModel @Inject constructor(
fun stopSoundMeter() {
//先重置标识,防止按钮抬起时触发语音结束
Constant.IS_VIDEO_SPEED = false
if (mSoundMeter != null && mSoundMeter!!.isStartSound()) {
if (mSoundMeter != null && mSoundMeter!!.isStartSound) {
mSoundMeter!!.stop()
}
if (pop != null && pop!!.isShowing) pop!!.dismiss()
pop?.let {
if (it.isShowing) {
it.dismiss()
}
}
}
fun savePhoto(bitmap: Bitmap) {
viewModelScope.launch(Dispatchers.IO) {
// 创建一个名为 "MyApp" 的文件夹
val myAppDir = File(Constant.USER_DATA_ATTACHEMNT_PATH)
if (!myAppDir.exists())
myAppDir.mkdirs() // 确保文件夹已创建
// 创建一个名为 fileName 的文件
val file = File(myAppDir, "${UUID.randomUUID()}.png")
file.createNewFile() // 创建文件
// 将 Bitmap 压缩为 JPEG 格式,并将其写入文件中
val out = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)
out.flush()
out.close()
var picList = mutableListOf<String>()
if (liveDataPictureList.value == null) {
picList.add(file.absolutePath)
} else {
picList.addAll(liveDataPictureList.value!!)
picList.add(file.absolutePath)
}
liveDataPictureList.postValue(picList)
}
}
}

View File

@ -0,0 +1,154 @@
package com.navinfo.omqs.ui.fragment.note
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.FragmentCanvasBinding
import com.navinfo.omqs.databinding.FragmentNoteBinding
import com.navinfo.omqs.databinding.FragmentProblemLinkBinding
import com.navinfo.omqs.ui.fragment.BaseFragment
import com.navinfo.omqs.ui.fragment.note.CanvasView.CanvasStyle
import com.navinfo.omqs.ui.fragment.note.CanvasView.OnCanvasChangeListener
import com.navinfo.omqs.ui.other.shareViewModels
/**
* @author zhjch
* @version V1.0
* @ClassName: CanvasFragment
* @Date 2016/5/10
* @Description: ${TODO}(绘制画布)
*/
class CanvasFragment : BaseFragment() {
/**
* 获取画布
*
* @return
*/
/**
* 画布
*/
private val canvasView by lazy { binding.canvasView }
/**
* 画笔线型
*/
private var mStyle = CanvasStyle.FREE_LINE
/**
* 画笔颜色
*/
private var mColor = -1
/**
* 画笔粗细
*/
private var width = 5
/**
* 画布回调接口
*/
private var listener: OnCanvasChangeListener? = null
private var _binding: FragmentCanvasBinding? = null
private val binding get() = _binding!!
private val viewModel by shareViewModels<NoteViewModel>("note")
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
_binding = FragmentCanvasBinding.inflate(inflater, container, false)
viewModel.initCanvasView(canvasView)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
canvasView.setStyle(mStyle)
if (mColor == -1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mColor = resources.getColor(R.color.black, null)
}
}
canvasView.setPaintColor(mColor)
canvasView.setPaintWidth(width)
if (listener != null) {
canvasView.setOnCanvasChangeListener(listener)
}
// * 开关橡皮擦
// */
// viewModel.liveEraserData.observe(viewLifecycleOwner) {
// canvasView.setEraser(it)
// }
// /**
// * 清除
// */
// viewModel.liveClearData.observe(viewLifecycleOwner) {
// canvasView.removeAllPaint()
// }
// /**
// * 回退上一笔
// */
// viewModel.liveBackData.observe(viewLifecycleOwner) {
// canvasView.back()
// }
// /**
// * 撤销回退
// */
// viewModel.liveForward.observe(viewLifecycleOwner) {
// canvasView.forward()
// }
//
}
/**
* 将数据转化并绘制在画板上
*
* @param value
*/
fun setDrawPathList(value: MutableList<CanvasView.DrawPath>) {
if (value != null && value.isNotEmpty()) {
canvasView.setDrawPathList(value)
}
}
/**
* 设置草图画笔线型
*/
fun setStyle(style: CanvasStyle) {
mStyle = style
canvasView.setStyle(style)
}
/**
* 设置画笔颜色
*/
fun setPaintColor(color: Int) {
mColor = color
canvasView.setPaintColor(mColor)
}
/**
* 设置画笔粗细
*/
fun setPaintWidth(width: Int) {
this.width = width
canvasView.setPaintWidth(width)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,424 @@
package com.navinfo.omqs.ui.fragment.note
import android.graphics.Path
import android.graphics.Point
import android.graphics.Rect
import android.graphics.RectF
import android.text.TextUtils
import com.navinfo.collect.library.data.entity.NoteBean
import com.navinfo.collect.library.data.entity.SketchAttachContent
import com.navinfo.collect.library.map.NIMapController
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.omqs.ui.fragment.note.CanvasView.CanvasStyle
import io.realm.RealmList
import org.locationtech.jts.geom.Coordinate
import org.oscim.backend.canvas.Color
import org.oscim.core.GeoPoint
import java.util.UUID
import kotlin.math.abs
import kotlin.math.cos
import kotlin.math.sin
/**
* @author zhjch
* @version V1.0
* @ClassName: CanvasViewHelper
* @Date 2016/5/16
* @Description: ${TODO}(用一句话描述该文件做什么)
*/
object CanvasViewHelper {
private const val mD2I = 3600000
fun createNoteBean(
controller: NIMapController,
mCurrentPaths: List<CanvasView.DrawPath>,
): NoteBean {
val noteBean = NoteBean(UUID.randomUUID().toString())
if (mCurrentPaths.isNotEmpty()) {
val list: RealmList<SketchAttachContent> = RealmList<SketchAttachContent>()
noteBean.list = list
for (index in mCurrentPaths.indices) {
val dp: CanvasView.DrawPath = mCurrentPaths[index]
val geo = SketchAttachContent(UUID.randomUUID().toString())
val pointList = dp.pointList ?: continue
if (dp.style === CanvasStyle.GREENLAND_LINE || dp.style === CanvasStyle.WATER_LINE || dp.style === CanvasStyle.PARKING_LINE) {
val geoPointList = mutableListOf<GeoPoint>()
for (i in pointList.indices) {
val point = pointList[i]
val geoPoint: GeoPoint = controller.viewportHandler.fromScreenPoint(
point
)
geoPointList.add(geoPoint)
if (index == 0 && i == 0) {
noteBean.guideGeometry =
GeometryTools.createGeometry(geoPoint).toText()
}
}
geo.style = createLineStyle(dp.style, dp.width, dp.color)
geo.geometry = GeometryTools.createPolygon(geoPointList).toText()
} else if (dp.style === CanvasStyle.CIRCULAR_POINT) {
val point = pointList[0]
val geoPoint: GeoPoint = controller.viewportHandler.fromScreenPoint(point)
geo.style = createLineStyle(dp.style, dp.width, dp.color)
geo.geometry = GeometryTools.createGeometry(geoPoint).toText()
noteBean.guideGeometry = geo.geometry
} else if (dp.style === CanvasStyle.ELLIPSE_LINE) {
dp.rect?.let {
val pointLT = Point(it.left, it.top)
val pointRB = Point(it.right, it.bottom)
val geoPointLT: GeoPoint =
controller.viewportHandler.fromScreenPoint(pointLT)
val geoPointRB: GeoPoint =
controller.viewportHandler.fromScreenPoint(pointRB)
val minX: Double
val maxX: Double
val minY: Double
val maxY: Double
if (geoPointLT.longitude < geoPointRB.longitude) {
minX = (geoPointLT.longitude * mD2I)
maxX = (geoPointRB.longitude * mD2I)
} else {
minX = (geoPointRB.longitude * mD2I)
maxX = (geoPointLT.longitude * mD2I)
}
if (geoPointLT.latitude < geoPointRB.latitude) {
minY = (geoPointLT.latitude * mD2I)
maxY = (geoPointRB.latitude * mD2I)
} else {
minY = (geoPointRB.latitude * mD2I)
maxY = (geoPointLT.latitude * mD2I)
}
val xR = (maxX - minX) / 2
val yR = (maxY - minY) / 2
var a = 0.0
var tempX = xR * cos(a) + xR + minX
val tempY = yR * sin(a) + yR + minY
val firstX = tempX
val geoPointList = mutableListOf<GeoPoint>()
geoPointList.add(GeoPoint(tempX / mD2I, tempY / mD2I))
var bLeft = false
var bRight = false
var zeng = 0.1
if (controller.mMapView.mapLevel >= 20) {
zeng = 0.2
}
while (!bLeft || !bRight) {
a += zeng
val x1 = (xR * cos(a) + xR + minX).toInt().toDouble()
val y1 = (yR * sin(a) + yR + minY).toInt().toDouble()
if (!bLeft && x1 > tempX) {
bLeft = true
}
if (!bRight && bLeft && x1 <= tempX) {
bRight = true
geoPointList.add(
GeoPoint(
firstX / mD2I,
tempY / mD2I
)
)
} else {
tempX = x1
geoPointList.add(GeoPoint(x1 / mD2I, y1 / mD2I))
}
}
if (index == 0) {
noteBean.guideGeometry =
GeometryTools.createGeometry(geoPointList[0]).toText()
}
geo.style = createLineStyle(dp.style, dp.width, dp.color)
geo.geometry = GeometryTools.createLineString(geoPointList).toText()
}
} else {
val geoPointList = mutableListOf<GeoPoint>()
for (i in pointList.indices) {
val point = pointList[i]
val geoPoint: GeoPoint =
controller.viewportHandler.fromScreenPoint(point)
geoPointList.add(geoPoint)
if (index == 0 && i == 0) {
noteBean.guideGeometry =
GeometryTools.createGeometry(geoPoint).toText()
}
}
geo.style = createLineStyle(dp.style, dp.width, dp.color)
geo.geometry = GeometryTools.createLineString(geoPointList).toText()
}
list.add(geo)
}
}
return noteBean
}
fun createDrawPaths(
controller: NIMapController,
att: NoteBean
): MutableList<CanvasView.DrawPath> {
val contents: List<SketchAttachContent> = att.list
val drawPaths: MutableList<CanvasView.DrawPath> = mutableListOf()
var width = 5
var canvasStyle = CanvasStyle.FREE_LINE
var color = Color.BLACK
for (geo in contents) {
var max_x = 0
var max_y = 0
var min_x = 0
var min_y = 0
val style = geo.style
if (!TextUtils.isEmpty(style) && style.length > 3) {
try {
if (style.startsWith("4")) {
canvasStyle = CanvasStyle.RAILWAY_LINE
} else if (style.startsWith("5")) {
if (style.contains("cde3ac")) {
canvasStyle = CanvasStyle.GREENLAND_LINE
} else if (style.contains("abcaff")) {
canvasStyle = CanvasStyle.WATER_LINE
} else if (style.contains("fffe98")) {
canvasStyle = CanvasStyle.PARKING_LINE
}
} else {
val s = style.substring(0, 1)
if (TextUtils.equals(s, "2")) {
canvasStyle = CanvasStyle.STRAIGHT_LINE
} else if (TextUtils.equals(s, "3")) {
canvasStyle = CanvasStyle.RECT_LINE
} else if (TextUtils.equals(s, "6")) {
canvasStyle = CanvasStyle.POLY_LINE
} else if (TextUtils.equals(s, "7")) {
canvasStyle = CanvasStyle.ELLIPSE_LINE
} else if (TextUtils.equals(s, "9")) {
canvasStyle = CanvasStyle.CIRCULAR_POINT
} else if (TextUtils.equals(s, "1")) {
canvasStyle = CanvasStyle.FREE_LINE
}
width = style.substring(1, 3).toInt()
var colorStr = style.substring(3, style.length)
if (colorStr.length == 6) {
colorStr = "ff$colorStr"
} else if (colorStr.length == 8) {
} else {
colorStr = "ff000000"
}
color = colorStr.toLong(16).toInt()
}
} catch (e: Exception) {
e.printStackTrace()
}
val path = Path()
val pointList: MutableList<Point> = ArrayList()
if (canvasStyle === CanvasStyle.GREENLAND_LINE || canvasStyle === CanvasStyle.WATER_LINE || canvasStyle === CanvasStyle.PARKING_LINE) {
// val polygonGeometry: PolygonGeometry = geo.geo as PolygonGeometry
// if (polygonGeometry != null) {
// val xyz: Array<Array<DoubleArray>> = polygonGeometry.getCoordinates()
// if (xyz != null && xyz.isNotEmpty() && xyz[0].size > 1) {
// var geoPoint: GeoPoint? = GeoPoint(xyz[0][0][0], xyz[0][0][1])
// val movePoint: Point = .geoToScreen(geoPoint)
// max_x = movePoint.x
// max_y = movePoint.y
// min_x = movePoint.x
// min_y = movePoint.y
// path.reset()
// path.moveTo(movePoint.x.toFloat(), movePoint.y.toFloat())
// pointList.add(Point(movePoint.x, movePoint.y))
// for (i in 1 until xyz[0].size) {
// val x_y = xyz[0][i]
// if (x_y != null) {
// geoPoint = GeoPoint(x_y[0], x_y[1])
// val point: Point = projection.geoToScreen(geoPoint)
// if (point.x > max_x) {
// max_x = point.x
// }
// if (point.x < min_x) {
// min_x = point.x
// }
// if (point.y > max_y) {
// max_y = point.y
// }
// if (point.y < min_y) {
// min_y = point.y
// }
// path.lineTo(point.x.toFloat(), point.y.toFloat())
// pointList.add(point)
// }
// }
// path.close()
// }
// }
// val drawPath =
// CanvasView.DrawPath(pointList[0], path, width, color, canvasStyle)
// val rect = Rect(min_x, min_y, max_x, max_y)
// drawPath.rect = rect
// drawPath.pointList = pointList
// drawPaths.add(drawPath)
} else if (canvasStyle === CanvasStyle.CIRCULAR_POINT) {
// val pointGeometry: PointGeometry = geo.geo as PointGeometry
// if (pointGeometry != null && pointGeometry.getCoordinates() != null) {
// val geoPoint: GeoPoint = GeoPoint(
// pointGeometry.getCoordinates().get(0),
// pointGeometry.getCoordinates().get(1)
// )
// val movePoint: Point = projection.geoToScreen(geoPoint)
// pointList.add(movePoint)
// val drawPath = DrawPath(movePoint, path, width, color, canvasStyle)
// val rect = Rect(
// movePoint.x - width - 20,
// movePoint.y - width - 20,
// movePoint.x + width + 20,
// movePoint.y + width + 20
// )
// drawPath.rect = rect
// drawPath.pointList = pointList
// drawPaths.add(drawPath)
// }
} else if (canvasStyle === CanvasStyle.ELLIPSE_LINE) {
// val lineGeometry = GeometryTools.createGeometry(geo.geometry)
// if (lineGeometry != null) {
// val xys: Array<out Coordinate> = lineGeometry.coordinates
// if (xys != null && xys.size > 1) {
// var geoPoint: GeoPoint? = GeoPoint(xys[0].y, xys[0].x)
// val movePoint: Point = projection.geoToScreen(geoPoint)
// max_x = movePoint.x
// max_y = movePoint.y
// min_x = movePoint.x
// min_y = movePoint.y
// path.reset()
// path.moveTo(movePoint.x.toFloat(), movePoint.y.toFloat())
// pointList.add(Point(movePoint.x, movePoint.y))
// for (i in 1 until xys.size) {
// val x_y = xys[i]
// geoPoint = GeoPoint(x_y[0], x_y[1])
// val point: Point = projection.geoToScreen(geoPoint)
// if (point.x > max_x) {
// max_x = point.x
// }
// if (point.x < min_x) {
// min_x = point.x
// }
// if (point.y > max_y) {
// max_y = point.y
// }
// if (point.y < min_y) {
// min_y = point.y
// }
// pointList.add(point)
// }
// path.addOval(
// RectF(
// min_x.toFloat(),
// min_y.toFloat(),
// max_x.toFloat(),
// max_y.toFloat()
// ), Path.Direction.CW
// )
// }
// }
// val drawPath =
// CanvasView.DrawPath(pointList[0], path, width, color, canvasStyle)
// val rect = Rect(min_x, min_y, max_x, max_y)
// drawPath.rect = rect
// drawPath.pointList = pointList
// drawPaths.add(drawPath)
} else {
val lineGeometry = GeometryTools.createGeometry(geo.geometry)
if (lineGeometry != null) {
val xys: Array<out Coordinate> = lineGeometry.coordinates
if (xys.size > 1) {
var geoPoint = GeoPoint(xys[0].y, xys[0].x)
val movePoint: Point =
controller.viewportHandler.toScreenPoint(geoPoint)
max_x = movePoint.x
max_y = movePoint.y
min_x = movePoint.x
min_y = movePoint.y
path.reset()
path.moveTo(movePoint.x.toFloat(), movePoint.y.toFloat())
pointList.add(Point(movePoint.x, movePoint.y))
for (i in 1 until xys.size) {
val x_y = xys[i]
geoPoint = GeoPoint(x_y.y, x_y.x)
val point: Point =
controller.viewportHandler.toScreenPoint(geoPoint)
if (point.x > max_x) {
max_x = point.x
}
if (point.x < min_x) {
min_x = point.x
}
if (point.y > max_y) {
max_y = point.y
}
if (point.y < min_y) {
min_y = point.y
}
if (canvasStyle === CanvasStyle.FREE_LINE) {
val dx = abs(point.x - movePoint.x).toFloat()
val dy = abs(point.y - movePoint.y).toFloat()
if (dx >= 4 || dy >= 4) {
path.quadTo(
movePoint.x.toFloat(),
movePoint.y.toFloat(),
((point.x + movePoint.x) / 2).toFloat(),
((point.y + movePoint.y) / 2).toFloat()
) //源代码是这样写的,可是我没有弄明白,为什么要这样?
movePoint.x = point.x
movePoint.y = point.y
}
} else {
path.lineTo(point.x.toFloat(), point.y.toFloat())
}
pointList.add(point)
}
}
}
val drawPath =
CanvasView.DrawPath(pointList[0], path, width, color, canvasStyle)
val rect = Rect(min_x, min_y, max_x, max_y)
drawPath.rect = rect
drawPath.pointList = pointList
drawPaths.add(drawPath)
}
}
}
return drawPaths
}
private fun createLineStyle(canvasStyle: CanvasStyle, width: Int, color: Int): String {
val style = StringBuilder()
if (canvasStyle === CanvasStyle.RAILWAY_LINE) {
return "4060070c004ffffff16"
} else if (canvasStyle === CanvasStyle.GREENLAND_LINE) {
return "50200b050cde3ac"
} else if (canvasStyle === CanvasStyle.WATER_LINE) {
return "50200b050abcaff"
} else if (canvasStyle === CanvasStyle.PARKING_LINE) {
return "502a6a6a6fffe98"
}
if (canvasStyle === CanvasStyle.STRAIGHT_LINE) {
style.append("2")
} else if (canvasStyle === CanvasStyle.RECT_LINE) {
style.append("3")
} else if (canvasStyle === CanvasStyle.POLY_LINE) {
style.append("6")
} else if (canvasStyle === CanvasStyle.ELLIPSE_LINE) {
style.append("7")
} else if (canvasStyle === CanvasStyle.CIRCULAR_POINT) {
style.append("9")
} else {
style.append("1")
}
if (width < 10) {
style.append("0")
}
style.append(width.toString())
try {
var colorString = Integer.toHexString(color).toString()
if (colorString.length == 8) {
colorString = TextUtils.substring(colorString, 2, 8)
}
style.append(colorString)
} catch (e: Exception) {
e.printStackTrace()
}
return style.toString()
}
}

View File

@ -0,0 +1,135 @@
package com.navinfo.omqs.ui.fragment.note
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.FragmentNoteBinding
import com.navinfo.omqs.ui.dialog.FirstDialog
import com.navinfo.omqs.ui.fragment.BaseFragment
import com.navinfo.omqs.ui.other.shareViewModels
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class NoteFragment : BaseFragment(), View.OnClickListener {
private var _binding: FragmentNoteBinding? = null
private val binding get() = _binding!!
private val viewModel by shareViewModels<NoteViewModel>("note")
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
_binding = FragmentNoteBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.sketchEraser.setOnClickListener(this)
binding.sketchClear.setOnClickListener(this)
binding.sketchForward.setOnClickListener(this)
binding.sketchBack.setOnClickListener(this)
binding.noteBarSave.setOnClickListener(this)
binding.noteBarCancel.setOnClickListener(this)
binding.noteBarDelete.setOnClickListener(this)
binding.noteDescription.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
viewModel.noteBeanDescription = s.toString()
}
})
/**
* 数据操作结束
*/
viewModel.liveDataFinish.observe(viewLifecycleOwner) {
if (it)
onBackPressed()
}
/**
* 画布初始化完成
*/
viewModel.liveDataCanvasViewInitFinished.observe(viewLifecycleOwner) {
if (it)
arguments?.let { b ->
val id = b.getString("NoteId", "")
if (id.isNotEmpty()) {
viewModel.initData(id)
}
}
}
}
override fun onStart() {
super.onStart()
activity?.run {
findNavController(
R.id.main_activity_middle_fragment
).navigate(R.id.CanvasFragment)
}
}
override fun onStop() {
super.onStop()
activity?.run {
findNavController(
R.id.main_activity_middle_fragment
).navigateUp()
}
}
override fun onClick(v: View) {
when (v) {
binding.sketchEraser -> {
viewModel.onEraser()
binding.sketchEraser.isSelected = viewModel.isEraser
}
binding.sketchBack -> {
viewModel.onBack()
}
binding.sketchForward -> {
viewModel.onForward()
}
binding.sketchClear -> {
viewModel.onClear()
}
binding.noteBarSave -> {
viewModel.onSaveData()
}
binding.noteBarDelete -> {
viewModel.deleteData(requireContext())
}
binding.noteBarCancel -> {
//返回按钮点击
val mDialog = FirstDialog(context)
mDialog.setTitle("提示?")
mDialog.setMessage("是否退出,请确认!")
mDialog.setPositiveButton(
"确定"
) { _, _ ->
mDialog.dismiss()
onBackPressed()
}
mDialog.setNegativeButton("取消", null)
mDialog.show()
}
}
}
override fun onBackPressed(): Boolean {
findNavController().navigateUp()
return true
}
}

View File

@ -0,0 +1,171 @@
package com.navinfo.omqs.ui.fragment.note
import android.content.Context
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.navinfo.collect.library.data.entity.NoteBean
import com.navinfo.collect.library.map.NIMapController
import com.navinfo.omqs.ui.dialog.FirstDialog
import dagger.hilt.android.lifecycle.HiltViewModel
import io.realm.Realm
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class NoteViewModel @Inject constructor(
val mapController: NIMapController
) : ViewModel() {
lateinit var canvasView: CanvasView
var mNoteBean: NoteBean? = null
var isEraser = false
var noteBeanDescription = ""
// /**
// * 橡皮擦开关
// */
// val liveEraserData = MutableLiveData(false)
//
// /**
// * 清除按钮
// */
// val liveClearData = MutableLiveData(false)
//
// /**
// * 回退按钮
// */
// val liveBackData = MutableLiveData(false)
//
// /**
// * 撤销按钮
// */
// val liveForward = MutableLiveData(false)
/**
* 处理结束关闭fragment
*/
val liveDataFinish = MutableLiveData(false)
/**
* 通知页面画布初始化完成
*/
val liveDataCanvasViewInitFinished = MutableLiveData(false)
fun initCanvasView(canvasView: CanvasView) {
this.canvasView = canvasView
liveDataCanvasViewInitFinished.value = true
}
/**
* 通知橡皮擦开关
*/
fun onEraser() {
isEraser = !isEraser
canvasView.setEraser(isEraser)
// liveEraserData.value = !liveEraserData.value!!
}
/**
* 通知清除
*/
fun onClear() {
canvasView.removeAllPaint()
// liveClearData.value = true
}
/**
* 通知回退
*/
fun onBack() {
canvasView.back()
// liveBackData.value = true
}
/**
* 通知撤销回退
*/
fun onForward() {
canvasView.forward()
// liveForward.value = true
}
/**
* 保存数据
*/
fun onSaveData() {
viewModelScope.launch(Dispatchers.IO) {
if (canvasView.paths != null && canvasView.paths!!.isNotEmpty()) {
var noteBean =
CanvasViewHelper.createNoteBean(mapController, canvasView.paths!!)
if (mNoteBean != null) {
noteBean.id = mNoteBean!!.id
noteBean.description = noteBeanDescription
}
mNoteBean = noteBean
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
it.copyToRealmOrUpdate(noteBean)
}
mapController.markerHandle.addOrUpdateNoteMark(mNoteBean!!)
liveDataFinish.postValue(true)
}
}
}
/**
* 删除数据
*/
fun deleteData(context: Context) {
if (mNoteBean == null) {
liveDataFinish.postValue(true)
return
} else {
val mDialog = FirstDialog(context)
mDialog.setTitle("提示?")
mDialog.setMessage("是否删除标签,请确认!")
mDialog.setPositiveButton(
"确定"
) { dialog, _ ->
dialog.dismiss()
viewModelScope.launch(Dispatchers.IO) {
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
val objects = it.where(NoteBean::class.java)
.equalTo("id", mNoteBean!!.id).findFirst()
objects?.deleteFromRealm()
}
mapController.markerHandle.removeNoteMark(mNoteBean!!)
liveDataFinish.postValue(true)
}
}
mDialog.setNegativeButton("取消", null)
mDialog.show()
}
}
/**
* 初始化数据
*/
fun initData(id: String) {
viewModelScope.launch(Dispatchers.IO) {
val realm = Realm.getDefaultInstance()
realm.executeTransaction { it ->
val objects = it.where(NoteBean::class.java)
.equalTo("id", id).findFirst()
mNoteBean = realm.copyFromRealm(objects)
mNoteBean?.let { bean ->
noteBeanDescription = bean.description
val list = CanvasViewHelper.createDrawPaths(mapController, bean)
canvasView.setDrawPathList(list)
}
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape>
<padding android:bottom="2dp" android:left="@dimen/default_widget_padding" android:right="@dimen/default_widget_padding" android:top="2dp"></padding>
<stroke android:width="1.1dp" android:color="#1ABBFE" />
</shape>
</item>
<item>
<shape>
<padding android:bottom="@dimen/default_widget_padding" android:left="@dimen/default_widget_padding" android:right="@dimen/default_widget_padding" android:top="@dimen/default_widget_padding"></padding>
<solid android:color="@color/transp" />
</shape>
</item>
</selector>

View File

@ -4,7 +4,7 @@
android:left="-300dp"
android:right="-300dp">
<rotate
android:drawable="@drawable/laneinfo_1_2"
android:drawable="@drawable/shape_dashed_line"
android:fromDegrees="90" />
</item>
</layer-list>

View File

@ -79,7 +79,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/top_right_drawer_btns_mr"
app:constraint_referenced_ids="main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_calc_disance,main_activity_menu"
app:constraint_referenced_ids="main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_calc_disance,main_activity_note,main_activity_menu"
app:flow_horizontalGap="6dp"
app:flow_wrapMode="aligned"
app:layout_constraintRight_toLeftOf="@id/main_activity_right_fragment"
@ -90,7 +90,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
app:constraint_referenced_ids="main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_calc_disance" />
app:constraint_referenced_ids="main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_note,main_activity_calc_disance" />
<ImageButton
android:id="@+id/main_activity_serach"
@ -122,6 +122,12 @@
android:onClick="@{()->mainActivity.onClickCalcDisance()}"
android:src="@drawable/icon_calc_disance" />
<ImageButton
android:id="@+id/main_activity_note"
style="@style/top_right_drawer_btns_style"
android:onClick="@{()->mainActivity.onClickNewNote()}"
android:src="@drawable/icon_calc_disance" />
<ImageButton
android:id="@+id/main_activity_menu"
android:layout_width="@dimen/top_right_drawer_wh"
@ -224,16 +230,6 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@id/main_activity_sign_recyclerview" />
<fragment
android:id="@+id/main_activity_right_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:elevation="3dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/right_fragment_nav_graph" />
<TextView
android:id="@+id/main_activity_geometry"
@ -250,7 +246,18 @@
android:text="经纬度:116.99388424,38.8403844"
android:textSize="10sp"
app:layout_constraintBottom_toTopOf="@id/main_activity_bottom_sheet_bg"
app:layout_constraintRight_toLeftOf="@id/main_activity_middle_fragment" />
app:layout_constraintRight_toLeftOf="@id/main_activity_right_fragment" />
<fragment
android:id="@+id/main_activity_right_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:elevation="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/right_fragment_nav_graph" />
<TextView
android:id="@+id/main_activity_road_name"
@ -336,16 +343,21 @@
android:layout_height="wrap_content"
app:constraint_referenced_ids="main_activity_select_line,main_activity_voice,main_activity_add_new" />
<androidx.constraintlayout.widget.Group
android:id="@+id/main_activity_right_visibility_buttons_group2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="main_activity_select_line,main_activity_voice,main_activity_add_new,main_activity_zoom_in,main_activity_zoom_out,main_activity_geometry,main_activity_location" />
<fragment
android:id="@+id/main_activity_middle_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="6dp"
android:layout_marginRight="-1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/main_activity_right_fragment"
app:layout_constraintTop_toBottomOf="@id/main_activity_flow"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/middle_fragment_nav_graph" />
<androidx.constraintlayout.widget.Group

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<com.navinfo.omqs.ui.fragment.note.CanvasView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/canvas_view"
android:elevation="4dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#94fcfbfb"
android:clickable="true" />

View File

@ -0,0 +1,235 @@
<?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="@dimen/right_fragment_w"
android:layout_height="match_parent"
android:background="@drawable/shape_right_fragment_bg"
tools:context=".ui.fragment.note.NoteFragment">
<TextView
android:id="@+id/note_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginTop="14dp"
android:drawableLeft="@drawable/selector_btn_back_xml"
android:text="Mark"
android:textColor="@color/default_blue_text_color"
android:textSize="16sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/note_bar_save"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="9dp"
android:layout_marginRight="14dp"
android:background="@drawable/ripple_fragment_save_botton_bg"
android:src="@drawable/icon_save"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/note_bar_cancel"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginRight="10dp"
android:background="@color/transparent"
android:src="@drawable/icon_fragment_close"
android:visibility="gone"
app:layout_constraintRight_toLeftOf="@id/note_bar_save"
app:layout_constraintTop_toTopOf="@id/note_bar_save" />
<ImageButton
android:id="@+id/note_bar_delete"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:layout_marginRight="5dp"
android:background="@color/transparent"
android:src="@drawable/icon_delete"
app:layout_constraintRight_toLeftOf="@id/note_bar_cancel"
app:layout_constraintTop_toTopOf="@id/note_bar_save" />
<androidx.core.widget.NestedScrollView
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="6dp"
android:paddingLeft="11dp"
android:paddingTop="6dp"
android:paddingRight="9dp"
android:paddingBottom="6dp"
app:layout_constraintBottom_toTopOf="@id/note_camera"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/note_bar_save">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="7dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingTop="5dp"
android:paddingBottom="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="橡皮擦&#8195;" />
<ImageView
android:id="@+id/sketch_eraser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/selector_sketch_eraser_bg"
android:src="@drawable/sketch_eraser" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/sketch_back"
style="@style/sketch_operation_style"
android:src="@drawable/sketch_back" />
<View
style="@style/link_gray_style"
android:layout_margin="2dp" />
<ImageView
android:id="@+id/sketch_forward"
style="@style/sketch_operation_style"
android:src="@drawable/sketch_forward" />
<View
style="@style/link_gray_style"
android:layout_margin="2dp" />
<TextView
android:id="@+id/sketch_clear"
style="@style/sketch_operation_style"
android:text="重绘" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
style="@style/evaluation_fragment_title_text_style"
android:layout_gravity="top"
android:layout_marginTop="3dp"
android:text="备注" />
<com.navinfo.omqs.ui.widget.MyEditeText
android:id="@+id/note_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_rect_white_2dp_bg"
android:elevation="2dp"
android:gravity="start"
android:hint="请输入备注信息"
android:inputType="textMultiLine"
android:lines="3"
android:maxLines="3"
android:paddingLeft="12dp"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:textSize="12sp" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="多媒体"
android:textColor="@color/default_blue_text_color"
android:textSize="16sp" />
<!--
这种效果也好实现,主要的关键点是 Android:clipChildren=”false” 这个属性。
1.配置ViewPager 和其父布局的 android:clipChildren属性为”false”.
(android:clipChildren表示是否限制子View在其范围内默认为true. 代码设置setClipChildren(false))
因为如果clipChildren属性设置为true,就表明我们要将children给clip掉就是说对于子元素来说超出当前view的部分都会被切掉那我们在这里把它设置成false就表明超出view的部分不要切掉依然显示。
注意setClipChildren(false)在3.0以上版本中,开启了硬件加速后将不能正常工作,所以需要将其设置为软件加速。设置软硬件加速使用 setLayerType(View.LAYER_TYPE_SOFTWARE, null); 也可以在布局文件中添加 android:layerType=”software”
-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="@+id/note_picture_left"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginRight="4dp"
android:background="@drawable/icon_picture_left"
android:padding="5dp" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/note_picture_viewpager"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_weight="1"
android:clipChildren="false" />
<ImageView
android:id="@+id/note_picture_right"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="4dp"
android:background="@drawable/icon_picture_right"
android:padding="5dp" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/note_voice_recyclerview"
android:layout_width="match_parent"
android:layout_height="120dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<ImageView
android:id="@+id/note_camera"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="10dp"
android:src="@drawable/baseline_camera_alt_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/note_voice" />
<ImageView
android:id="@+id/note_voice"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="10dp"
android:src="@drawable/baseline_keyboard_voice_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toRightOf="@id/note_camera"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,26 +1,32 @@
<?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:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/fragment_phenomenon_width"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/shape_middle_fragment_bg"
android:gravity="right"
tools:context="com.navinfo.omqs.ui.fragment.evaluationresult.PhenomenonFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/phenomenon_left_recyclerview"
android:layout_width="148dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="@dimen/fragment_phenomenon_width"
android:layout_height="match_parent"
android:layout_marginTop="55dp"
android:background="@drawable/shape_middle_fragment_bg"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/phenomenon_right_recyclerview"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/phenomenon_left_recyclerview"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/phenomenon_left_recyclerview"
android:layout_width="148dp"
android:layout_height="match_parent"
android:layout_toLeftOf="@id/phenomenon_right_recyclerview" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/phenomenon_right_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentRight="true" />
</LinearLayout>
</LinearLayout>

View File

@ -2,13 +2,15 @@
<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="@dimen/fragment_problem_link_width"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/shape_middle_fragment_bg"
tools:context="com.navinfo.omqs.ui.fragment.evaluationresult.ProblemLinkFragment">
<androidx.recyclerview.widget.RecyclerView
android:layout_marginTop="55dp"
android:id="@+id/link_right_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_width="@dimen/fragment_problem_link_width"
android:layout_height="match_parent"
android:background="@drawable/shape_middle_fragment_bg"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -20,4 +20,10 @@
android:name="com.navinfo.omqs.ui.fragment.evaluationresult.ProblemLinkFragment"
android:label="评测页面"
tools:layout="@layout/fragment_problem_link"></fragment>
<fragment
android:id="@+id/CanvasFragment"
android:name="com.navinfo.omqs.ui.fragment.note.CanvasFragment"
android:label="绘图页面"
tools:layout="@layout/fragment_canvas"></fragment>
</navigation>

View File

@ -30,4 +30,11 @@
tools:layout="@layout/fragment_evaluation_result">
</fragment>
<fragment
android:id="@+id/NoteFragment"
android:name="com.navinfo.omqs.ui.fragment.note.NoteFragment"
android:label="便签页面"
tools:layout="@layout/fragment_note">
</fragment>
</navigation>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CanvasView">
<attr name="isSavePoint" format="boolean" />
</declare-styleable>
</resources>

View File

@ -1,5 +1,20 @@
<resources>
<style name="sketch_operation_style">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item>
<item name="android:gravity">center</item>
<item name="android:paddingTop">5dp</item>
<item name="android:paddingBottom">5dp</item>
</style>
<style name="link_gray_style" comment="竖着的灰色分隔线">
<item name="android:layout_width">1dp</item>
<item name="android:layout_height">match_parent</item>
<item name="android:background">#C3C3C3</item>
</style>
<style name="main_activity_bottom_sheet_icon" comment="主控页面下方按钮样式">
<item name="android:layout_width">36dp</item>
<item name="android:layout_height">36dp</item>

View File

@ -79,7 +79,7 @@ dependencies {
implementation "net.sf.kxml:kxml2:2.3.0"
implementation 'org.slf4j:slf4j-api:2.0.7'
implementation project(":vtm-themes")
api project(":vtm-android")
implementation project(":vtm-android")
implementation project(':vtm-extras')
implementation project(":vtm-http")
// implementation "org.mapsforge:vtm-themes:$vtmVersion"

View File

@ -0,0 +1,13 @@
package com.navinfo.collect.library.data.entity
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
open class NoteBean @JvmOverloads constructor(
@PrimaryKey
var id: String = "",
var guideGeometry: String = "",
var description: String = "",
var list: RealmList<SketchAttachContent> = RealmList<SketchAttachContent>(),
) : RealmObject()

View File

@ -0,0 +1,40 @@
package com.navinfo.collect.library.data.entity
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
/**
* @author zhjch
* @version V1.0
* @ClassName: SketchAttachContent
* @Date 2016/5/19
* @Description: ${TODO}(草图内容 )
*/
open class SketchAttachContent @JvmOverloads constructor(
@PrimaryKey
var id: String = "",
/**
* 获取geo
*
* @return geo
*/
/**
* 设置geo
*
* @param geo geo
*/
//几何
var geometry: String = "",
/**
* 获取style
*
* @return style
*/
/**
* 设置style
*
* @param style style
*/
//样式
var style: String = ""
) : RealmObject()

View File

@ -20,6 +20,8 @@ abstract class BaseHandler(context: AppCompatActivity, mapView: NIMapView) {
mMapView.vtmMap.layers().remove(layer)
}
// fun setOnMapClickListener(listener: NIMapView.OnMapClickListener) {
// mMapView.setOnMapClickListener(listener)
// }

View File

@ -8,10 +8,10 @@ import androidx.appcompat.app.AppCompatActivity
import com.navinfo.collect.library.R
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.layers.MultiLinesLayer
import com.navinfo.collect.library.map.layers.NoteLineLayer
import com.navinfo.collect.library.map.layers.OmdbTaskLinkLayer
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.StringUtil
import org.locationtech.jts.geom.LineString
import org.oscim.android.canvas.AndroidBitmap
import org.oscim.backend.canvas.Bitmap
import org.oscim.core.GeoPoint
@ -23,7 +23,6 @@ import org.oscim.layers.marker.MarkerInterface
import org.oscim.layers.marker.MarkerItem
import org.oscim.layers.marker.MarkerSymbol
import org.oscim.layers.vector.PathLayer
import org.oscim.layers.vector.VectorLayer
import org.oscim.layers.vector.geometries.Style
import org.oscim.map.Map
@ -69,6 +68,9 @@ class LineHandler(context: AppCompatActivity, mapView: NIMapView) : BaseHandler(
layer
}
/**
* 任务线图层
*/
val omdbTaskLinkLayer by lazy {
val omdbTaskLinkLayer = OmdbTaskLinkLayer(
mMapView.vtmMap,
@ -84,6 +86,7 @@ class LineHandler(context: AppCompatActivity, mapView: NIMapView) : BaseHandler(
omdbTaskLinkLayer
}
init {
mMapView.vtmMap.events.bind(this)

View File

@ -4,16 +4,17 @@ import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat
import androidx.lifecycle.lifecycleScope
import com.navinfo.collect.library.R
import com.navinfo.collect.library.data.entity.NoteBean
import com.navinfo.collect.library.data.entity.QsRecordBean
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.cluster.ClusterMarkerItem
import com.navinfo.collect.library.map.cluster.ClusterMarkerRenderer
import com.navinfo.collect.library.map.layers.MyItemizedLayer
import com.navinfo.collect.library.map.layers.NoteLineLayer
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.StringUtil
import io.realm.Realm
@ -22,6 +23,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.locationtech.jts.geom.Geometry
import org.locationtech.jts.geom.LineString
import org.locationtech.jts.geom.Polygon
import org.oscim.android.canvas.AndroidBitmap
import org.oscim.backend.CanvasAdapter
import org.oscim.backend.canvas.Bitmap
@ -29,9 +32,9 @@ import org.oscim.backend.canvas.Paint
import org.oscim.core.GeoPoint
import org.oscim.layers.marker.*
import org.oscim.layers.marker.ItemizedLayer.OnItemGestureListener
import org.oscim.layers.vector.geometries.*
import org.oscim.map.Map
import java.util.*
import kotlin.collections.ArrayList
/**
* marker 操作
@ -56,8 +59,10 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
//画布
private lateinit var canvas: org.oscim.backend.canvas.Canvas
private lateinit var itemizedLayer: MyItemizedLayer
private lateinit var markerRendererFactory: MarkerRendererFactory
private var resId = R.mipmap.map_icon_report
private val resId = R.mipmap.map_icon_report
private val noteResId = R.drawable.icon_note_marker
private var itemListener: OnQsRecordItemClickListener? = null
/**
@ -65,6 +70,56 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
*/
private val NUM_13 = 13
/**
* 便签线图层
*/
private val noteLineLayer: NoteLineLayer by lazy {
val layer = NoteLineLayer(mMapView.vtmMap)
addLayer(layer, NIMapView.LAYER_GROUPS.VECTOR)
layer
}
private val noteLayer: MyItemizedLayer by lazy {
val layer = MyItemizedLayer(
mMapView.vtmMap,
mutableListOf(),
markerRendererFactory,
object : MyItemizedLayer.OnItemGestureListener {
override fun onItemSingleTapUp(
list: MutableList<Int>,
nearest: Int
): Boolean {
itemListener?.let {
val idList = mutableListOf<String>()
if (list.size == 0) {
} else {
for (i in list) {
val markerInterface: MarkerInterface =
noteLayer.itemList[i]
if (markerInterface is MarkerItem) {
idList.add(markerInterface.title)
}
}
it.onNoteList(idList.distinct().toMutableList())
}
}
return true
}
override fun onItemLongPress(
list: MutableList<Int>?,
nearest: Int
): Boolean {
return true
}
})
addLayer(layer, NIMapView.LAYER_GROUPS.OPERATE_MARKER)
layer
}
init {
//新增marker图标样式
val mDefaultBitmap =
@ -100,6 +155,7 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
itemizedLayer.isEnabled = mapPosition.getZoomLevel() >= 12
}
})
initNoteData()
mMapView.updateMap()
}
@ -141,6 +197,9 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
}
}
/**
* 移除marker
*/
fun removeMarker(title: String) {
var marker: MarkerItem? = null
for (e in mDefaultMarkerLayer.itemList) {
@ -172,12 +231,53 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
withContext(Dispatchers.Main) {
mMapView.updateMap(true)
}
}
/**
* 删除marker
* 增加或更新便签
*/
suspend fun addOrUpdateNoteMark(data: NoteBean) {
for (item in noteLayer.itemList) {
if (item is MarkerItem) {
if (item.title == data.id) {
noteLayer.itemList.remove(item)
break
}
}
}
noteLineLayer.removeNoteBeanLines(data)
createNoteMarkerItem(data)
withContext(Dispatchers.Main) {
mMapView.updateMap(true)
}
}
private fun convertGeometry2Drawable(geometry: Geometry, vectorLayerStyle: Style): Drawable? {
var resultDrawable: Drawable? = null
if ("POINT" == geometry.geometryType.uppercase(Locale.getDefault())) {
val geoPoint = GeoPoint(geometry.coordinate.y, geometry.coordinate.x)
if (geoPoint != null) {
resultDrawable = PointDrawable(geoPoint, vectorLayerStyle)
}
} else if ("LINESTRING" == geometry.geometryType.uppercase(Locale.getDefault())) {
val lineString = geometry as LineString
if (lineString != null) {
resultDrawable = LineDrawable(lineString, vectorLayerStyle)
}
} else if ("POLYGON" == geometry.geometryType.uppercase(Locale.getDefault())) {
val polygon = geometry as Polygon
if (polygon != null) {
resultDrawable = PolygonDrawable(polygon, vectorLayerStyle)
}
}
return resultDrawable
}
/**
* 删除质检数据
*/
suspend fun removeQsRecordMark(data: QsRecordBean) {
for (item in itemizedLayer.itemList) {
@ -191,6 +291,43 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
}
}
/**
* 删除标签
*/
suspend fun removeNoteMark(data: NoteBean) {
for (item in noteLayer.itemList) {
if (item is MarkerItem) {
if (item.title == data.id) {
noteLayer.itemList.remove(item)
noteLineLayer.removeNoteBeanLines(data)
noteLayer.populate()
withContext(Dispatchers.Main) {
mMapView.updateMap(true)
}
return
}
}
}
}
/**
* 初始化便签
*/
private fun initNoteData() {
mContext.lifecycleScope.launch(Dispatchers.IO) {
var list = mutableListOf<NoteBean>()
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
val objects = realm.where<NoteBean>().findAll()
list = realm.copyFromRealm(objects)
}
for (item in list) {
createNoteMarkerItem(item)
}
}
}
/**
* 初始话质检数据图层
*/
@ -276,6 +413,39 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
}
/**
* 添加质检数据marker
*/
private suspend fun createNoteMarkerItem(item: NoteBean) {
val bitmap: Bitmap = createTextMarkerBitmap(mContext, item.description, noteResId)
val geometry: Geometry? = GeometryTools.createGeometry(item.guideGeometry)
if (geometry != null) {
var geoPoint: org.oscim.core.GeoPoint? = null
if (geometry.geometryType != null) {
when (geometry.geometryType.uppercase(Locale.getDefault())) {
"POINT" -> geoPoint =
org.oscim.core.GeoPoint(geometry.coordinate.y, geometry.coordinate.x)
}
}
if (geoPoint != null) {
var geoMarkerItem: MarkerItem
geoMarkerItem = ClusterMarkerItem(
1, item.id, item.description, geoPoint
)
val markerSymbol =
MarkerSymbol(bitmap, MarkerSymbol.HotspotPlace.CENTER)
geoMarkerItem.marker = markerSymbol
noteLayer.itemList.add(geoMarkerItem)
}
}
noteLineLayer.showNoteBeanLines(item)
noteLayer.populate()
}
/**
* 添加质检数据marker
*/
private suspend fun createMarkerItem(item: QsRecordBean) {
val bitmap: Bitmap = createTextMarkerBitmap(mContext, item.description, resId)
if (item.t_lifecycle != 2) {
@ -554,4 +724,5 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
interface OnQsRecordItemClickListener {
fun onQsRecordList(list: MutableList<String>)
fun onNoteList(list: MutableList<String>)
}

View File

@ -1,13 +1,13 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import android.graphics.Point
import androidx.appcompat.app.AppCompatActivity
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.utils.GeometryTools
import org.oscim.core.GeoPoint
import org.oscim.core.Point
open class ViewportHandler(context: AppCompatActivity, mapView: NIMapView) : BaseHandler(context, mapView) {
open class ViewportHandler(context: AppCompatActivity, 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.
@ -54,32 +54,47 @@ open class ViewportHandler(context: AppCompatActivity, mapView: NIMapView) : Bas
* @param snapType 扩展外接矩形的方式用屏幕像素还是距离
* @param distance 距离大小 像素
*/
// fun toScreenPoint(
// geoPoint: GeoPoint
// ): String {
// val point = Point()
//
// mMapView.vtmMap.viewport().toScreenPoint(geoPoint, false, point)
//
// return "${point.x},${point.y}"
// }
fun toScreenPoint(
geoPoint: GeoPoint
): String {
val point = Point()
): Point {
val point = org.oscim.core.Point()
mMapView.vtmMap.viewport().toScreenPoint(geoPoint, false, point)
return "${point.x},${point.y}"
return Point(point.x.toInt(), point.y.toInt())
}
/**
* 获取几何的外接矩形,返回矩形的左上右下两个坐标
* @param snapType 扩展外接矩形的方式用屏幕像素还是距离
* @param distance 距离大小 像素
*/
fun fromScreenPoint(
px: Float, py: Float
): Map<String, Any> {
val geo = mMapView.vtmMap.viewport().fromScreenPoint(px, py)
// /**
// * 获取几何的外接矩形,返回矩形的左上,右下两个坐标
// * @param snapType 扩展外接矩形的方式,用屏幕像素还是距离
// * @param distance 距离大小 像素 或 米
// */
// fun fromScreenPointMap(
// px: Float, py: Float
// ): Map<String, Any> {
//
// val geo = mMapView.vtmMap.viewport().fromScreenPoint(px, py)
//
// return mapOf(
// "latitude" to geo.latitude,
// "longitude" to geo.longitude,
// "longitudeE6" to geo.longitudeE6,
// "latitudeE6" to geo.latitudeE6,
// )
// }
return mapOf(
"latitude" to geo.latitude,
"longitude" to geo.longitude,
"longitudeE6" to geo.longitudeE6,
"latitudeE6" to geo.latitudeE6,
)
fun fromScreenPoint(point: android.graphics.Point): GeoPoint {
return mMapView.vtmMap.viewport().fromScreenPoint(point.x.toFloat(), point.y.toFloat())
}
}

View File

@ -0,0 +1,98 @@
package com.navinfo.collect.library.map.layers
import android.graphics.Color
import com.navinfo.collect.library.data.entity.NoteBean
import com.navinfo.collect.library.utils.GeometryTools
import org.oscim.layers.vector.VectorLayer
import org.oscim.layers.vector.geometries.Drawable
import org.oscim.layers.vector.geometries.LineDrawable
import org.oscim.layers.vector.geometries.Style
import org.oscim.map.Map
class NoteLineLayer(map: Map) : VectorLayer(map) {
private val lineMap = HashMap<String, MutableList<Drawable>>()
private var selectDrawable: Drawable? = null
private val selectStyle =
Style.builder().fillColor(Color.GREEN).strokeColor(Color.GREEN)
.strokeWidth(10f).fixed(false).build()
@Synchronized
fun showNoteBeanLines(noteBean: NoteBean) {
removeNoteBeanLines(noteBean)
val list = mutableListOf<Drawable>()
for (item in noteBean.list) {
val lineDrawable =
LineDrawable(GeometryTools.createGeometry(item.geometry), getStyle(item.style))
add(lineDrawable)
list.add(lineDrawable)
}
lineMap[noteBean.id] = list
update()
}
@Synchronized
fun removeNoteBeanLines(noteBean: NoteBean) {
if (lineMap.containsKey(noteBean.id)) {
for (drawable in lineMap[noteBean.id]!!) {
remove(drawable)
}
lineMap.remove(noteBean.id)
}
update()
}
private fun getStyle(style: String): Style {
// if (style.startsWith("4")) {
// canvasStyle = CanvasView.CanvasStyle.RAILWAY_LINE
// } else if (style.startsWith("5")) {
// if (style.contains("cde3ac")) {
// canvasStyle = CanvasView.CanvasStyle.GREENLAND_LINE
// } else if (style.contains("abcaff")) {
// canvasStyle = CanvasView.CanvasStyle.WATER_LINE
// } else if (style.contains("fffe98")) {
// canvasStyle = CanvasView.CanvasStyle.PARKING_LINE
// }
// } else {
// val s: String = style.substring(0, 1)
// if (TextUtils.equals(s, "2")) {
// canvasStyle = CanvasView.CanvasStyle.STRAIGHT_LINE
// } else if (TextUtils.equals(s, "3")) {
// canvasStyle = CanvasView.CanvasStyle.RECT_LINE
// } else if (TextUtils.equals(s, "6")) {
// canvasStyle = CanvasView.CanvasStyle.POLY_LINE
// } else if (TextUtils.equals(s, "7")) {
// canvasStyle = CanvasView.CanvasStyle.ELLIPSE_LINE
// } else if (TextUtils.equals(s, "9")) {
// canvasStyle = CanvasView.CanvasStyle.CIRCULAR_POINT
// } else if (TextUtils.equals(s, "1")) {
// canvasStyle = CanvasView.CanvasStyle.FREE_LINE
// }
val width = style.substring(1, 3).toFloat()
var colorStr: String = style.substring(3, style.length)
colorStr = if (colorStr.length == 6) {
"#ff$colorStr"
} else {
"#ff000000"
}
// val color = colorStr.toLong(16).toInt()
return Style.builder().fillColor(colorStr).fillAlpha(0.5f).strokeColor(colorStr)
.strokeWidth(width).fixed(true).build()
}
fun removeAll() {
for ((_, value) in lineMap) {
for (item in value) {
remove(item)
}
}
lineMap.clear()
update()
}
}

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="54.723"
android:viewportHeight="40">
<path
android:pathData="M7.442,28.743S26.236,7.002 42.58,4.502C23.513,11.5 1.721,39.987 1.721,39.987L22.968,39.987a1.589,1.589 0,0 0,-1.631 -1L4.445,38.987A78.915,78.915 0,0 1,10.438 33.243c10.9,-0.5 20.43,-1.5 26.968,-10 1.089,-2 -0.815,-1.749 -1.362,-1.749 5.176,-2 16.344,-9.495 14.709,-13.245 -0.815,-0.748 -1.362,-0.251 -1.362,-0.251s8.444,-5 4.077,-7.247S38.214,2.003 38.214,2.003s0.815,-1.5 -1.631,-1.5A31.679,31.679 0,0 0,20.521 7.002s0,-2 -1.362,-1.249C0.359,16.497 7.442,28.743 7.442,28.743Z"
android:fillColor="#EA6B00"/>
<path
android:pathData="M4.6,35.624a2.016,2.016 0,0 0,-1.157 -0.481,2.3 2.3,0 0,0 -1.19,0.164 4.085,4.085 0,0 0,-1.3 1.189,4.031 4.031,0 0,0 -0.8,1.174s-0.478,1.749 0.229,2.1a3.616,3.616 0,0 0,2.484 0.067,4.594 4.594,0 0,0 1.373,-0.5 2.832,2.832 0,0 0,0.973 -0.978A2.291,2.291 0,0 0,4.6 35.624Z"
android:fillColor="#EA6B00"/>
</vector>

View File

@ -1,23 +1,21 @@
pluginManagement {
repositories {
google()
gradlePluginPortal()
mavenCentral()
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://maven.aliyun.com/repository/central' }
maven { url 'https://jitpack.io' }
mavenCentral()
google()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
gradlePluginPortal()
maven { url "https://maven.aliyun.com/repository/google" }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
@ -26,6 +24,9 @@ dependencyResolutionManagement {
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://jitpack.io' }
mavenCentral()
google()
gradlePluginPortal()
}
}