feat: 增加车信图标及渲染配置

This commit is contained in:
xiaoyan 2023-07-05 10:13:24 +08:00
commit df3a32a07d
228 changed files with 5123 additions and 410 deletions

View File

@ -115,6 +115,18 @@ dependencies {
//kotlin反射
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.7.0"
implementation "org.jetbrains.kotlin:kotlin-reflect:1.7.0"
implementation 'com.permissionx.guolindev:permissionx:1.4.0'
def camerax_version = "1.1.0-alpha04"
// The following line is optional, as the core library is included indirectly by camera-camera2
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
// If you want to additionally use the CameraX Lifecycle library
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
// If you want to additionally use the CameraX View class
implementation "androidx.camera:camera-view:1.0.0-alpha24"
implementation 'com.google.mlkit:barcode-scanning:16.1.1'
}
//
kapt {

View File

@ -4,6 +4,11 @@
android:versionCode="3"
android:versionName="1.4"
package="com.navinfo.omqs">
<!-- 这个权限用于相机权限-->
<uses-feature android:name="android.hardware.camera.any" />
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<!-- 这个权限用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 这个权限用于访问GPS定位-->
@ -31,7 +36,13 @@
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 读取缓存数据 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 相机权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 音频权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!--闹钟和提醒-->
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<!--android:largeHeap="true" 大内存 128M -->
<application
android:name=".OMQSApplication"
@ -57,12 +68,24 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.activity.map.MainActivity"
android:exported="false"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:theme="@style/Theme.OMQualityInspection" />
<activity
android:name=".ui.activity.scan.QrCodeActivity"
android:theme="@style/Theme.OMQualityInspection"
android:screenOrientation="portrait" />
<activity
android:name=".ui.activity.scan.QRCodeResultActivity"
android:theme="@style/Theme.OMQualityInspection"
android:screenOrientation="portrait" />
<meta-data
android:name="ScopedStorage"
android:value="true" />

View File

@ -52,6 +52,11 @@ class Constant {
* */
var LAYER_CONFIG_LIST: List<ImportConfig>? = null
/**
* 室内整理工具IP
*/
lateinit var INDOOR_IP: String
const val DEBUG = true
var IS_VIDEO_SPEED by kotlin.properties.Delegates.notNull<Boolean>()

View File

@ -38,8 +38,8 @@ data class EvaluationInfo(
@SerializedName("problemLink")
val problemLink: String = "",//问题环节
@SerializedName("problemReason")
val problemReason: String = "",//问题原因
@SerializedName("preliminaryAnalysis")
val preliminaryAnalysis: String = "",//初步分析
@SerializedName("evaluatorName")
val evaluatorName: String = "",//测评人名称

View File

@ -0,0 +1,11 @@
package com.navinfo.omqs.bean
data class IndoorConnectionInfoBean(
var username: String = "",
var uname: String = "",
var userid: String = "",
var token: String = "",
var baseurl: String = "",
var plate: String = "",
var platform: String = "Android",
)

View File

@ -0,0 +1,6 @@
package com.navinfo.omqs.bean
data class QRCodeBean(
var errcode: Int = -1,
var msg: String = ""
)

View File

@ -0,0 +1,49 @@
package com.navinfo.omqs.bean
data class RoadNameBean(
/**
* 道路名称
*/
val name: String = "",
/**
* 0 普通
* 1 立交桥名连接路
* 2 立交桥名 主路
* 3 风景线路
* 5 隧道
* 6 虚拟名称
*/
val type: Int = 0,
/**
* 1 不论名称分类是官方名别名还是曾用名都统一从1开始递增
* 2 若取第一官方名时需判断名称分类 [nameClass]=="官方名"[seqNum] 最小的
*/
val seqNum: Int = 1,
/**
* 1 官方名
* 2 别名
* 3 曾用名
*/
val nameClass: Int = 1,
) {
fun getNameClassStr(): String {
when (nameClass) {
1 -> return "官方名"
2 -> return "别名"
3 -> return "曾用名"
}
return ""
}
fun getTypeStr(): String {
when (type) {
0 -> return "普通"
1 -> return "立交桥名(连接路)"
2 -> return "立交桥名(主路)"
3 -> return "风景线路"
5 -> return "隧道"
6 -> return "虚拟名称"
}
return ""
}
}

View File

@ -1,6 +1,7 @@
package com.navinfo.omqs.bean
import android.os.Parcelable
import com.navinfo.collect.library.data.entity.RenderEntity
import kotlinx.parcelize.Parcelize
@Parcelize
@ -11,20 +12,16 @@ data class SignBean(
val distance: Int = 0,
//左上图标中的文字
val iconText: String = "",
//绑定的要素id
val elementId: String = "",
//绑定的linkid
val linkId: String,
//坐标
val geometry: String,
//名称
val name: String,
//是否要展示详细信息
val isMoreInfo: Boolean = false,
//底部右侧文字
val bottomRightText: String = "",
//要素code类型
val elementCode: Int,
//需要展示更多的内容
val moreText: String = "",
//左上角信息
val topRightText: String = ""
//捕捉数据
val renderEntity: RenderEntity,
//道路信息排序用的字段
val index: Int = 0
) : Parcelable

View File

@ -27,9 +27,9 @@ class ImportPreProcess {
Log.d("checkCircleRoad", "LinkInEntity: ${linkInId}- ${linkInEntity?.properties?.get("snodePid")}LinkOutEntity: ${linkOutId}- ${linkOutEntity?.properties?.get("enodePid")}")
// 查询linkIn的sNode和linkOut的eNode是否相同如果相同认为数据是环形路口返回false
if (linkInEntity!=null&&linkOutEntity!=null) {
if (linkInEntity.properties["snodePid"] == linkOutEntity.properties["enodePid"] || linkInEntity.properties["enodePid"] == linkOutEntity.properties["snodePid"]
|| linkInEntity.properties["snodePid"] == linkOutEntity.properties["snodePid"]|| linkInEntity.properties["enodePid"] == linkOutEntity.properties["enodePid"])
return false
if (linkInEntity.properties["snodePid"] == linkOutEntity.properties["enodePid"] || linkInEntity.properties["enodePid"] == linkOutEntity.properties["snodePid"] || linkInEntity.properties["snodePid"] == linkOutEntity.properties["snodePid"]|| linkInEntity.properties["enodePid"] == linkOutEntity.properties["enodePid"]) {
return false
}
}
return true
}
@ -290,6 +290,8 @@ class ImportPreProcess {
referenceEntity.properties["qi_table"] = renderEntity.table
referenceEntity.properties["currentDirect"] = laneInfoDirectArray[i].toString().split(",").distinct().joinToString("_")
referenceEntity.properties["currentType"] = laneInfoTypeArray[i].toString().split(",").distinct().joinToString("_")
referenceEntity.properties["symbol"] = "assets:omdb/4601/bus/1301_"+referenceEntity.properties["currentDirect"]+".svg"
Log.d("unpackingLaneInfo", referenceEntity.properties["symbol"].toString())
Realm.getDefaultInstance().insert(referenceEntity)
}
}

View File

@ -44,7 +44,7 @@ class RealmOperateHelper() {
)
// 根据polygon查询相交的tile号
val tileXSet = mutableSetOf<Int>()
tileXSet.toString()
GeometryToolsKt.getTileXByGeometry(polygon.toString(), tileXSet)
val tileYSet = mutableSetOf<Int>()
GeometryToolsKt.getTileYByGeometry(polygon.toString(), tileYSet)

View File

@ -30,8 +30,8 @@ interface ScProblemTypeDao {
/**
* 获取问题分类并去重
*/
@Query("select DISTINCT CLASS_TYPE from ScProblemType order by CLASS_TYPE")
suspend fun findClassTypeList(): List<String>?
@Query("select * from ScProblemType group by CLASS_TYPE")
suspend fun findClassTypeList(): List<ScProblemTypeBean>?
@Query("select DISTINCT CLASS_TYPE from ScProblemType where ELEMENT_CODE=:code")
suspend fun findClassTypeByCode(code: Int): String?

View File

@ -2,7 +2,9 @@ package com.navinfo.omqs.http
import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.collect.library.data.entity.TaskBean
import com.navinfo.omqs.bean.IndoorConnectionInfoBean
import com.navinfo.omqs.bean.LoginUserBean
import com.navinfo.omqs.bean.QRCodeBean
import com.navinfo.omqs.bean.SysUserBean
import okhttp3.ResponseBody
import retrofit2.Response
@ -15,14 +17,25 @@ interface NetworkService {
/**
* 获取离线地图城市列表
*/
suspend fun getOfflineMapCityList():NetResult<List<OfflineMapCityBean>>
suspend fun getOfflineMapCityList(): NetResult<List<OfflineMapCityBean>>
/**
* 获取任务列表
*/
suspend fun getTaskList(evaluatorNo:String): NetResult<DefaultResponse<List<TaskBean>>>
suspend fun getTaskList(evaluatorNo: String): NetResult<DefaultResponse<List<TaskBean>>>
/**
* 登录接口
*/
suspend fun loginUser(loginUserBean: LoginUserBean): NetResult<DefaultResponse<SysUserBean>>
/**
* 连接室内整理工具
*/
suspend fun connectIndoorTools(url: String): NetResult<QRCodeBean>
/**
* 更新用户信息
*/
suspend fun updateServerInfo(url: String,indoorConnectionInfoBean: IndoorConnectionInfoBean): NetResult<QRCodeBean>
}

View File

@ -2,7 +2,9 @@ package com.navinfo.omqs.http
import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.collect.library.data.entity.TaskBean
import com.navinfo.omqs.bean.IndoorConnectionInfoBean
import com.navinfo.omqs.bean.LoginUserBean
import com.navinfo.omqs.bean.QRCodeBean
import com.navinfo.omqs.bean.SysUserBean
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@ -75,4 +77,42 @@ class NetworkServiceImpl @Inject constructor(
NetResult.Error<Any>(e)
}
}
override suspend fun connectIndoorTools(url: String): NetResult<QRCodeBean> =
//在IO线程中运行
withContext(Dispatchers.IO) {
return@withContext try {
val result = netApi.retrofitConnectIndoorTools(url = url)
if (result.isSuccessful) {
if (result.code() == 200) {
NetResult.Success(result.body())
} else {
NetResult.Failure<Any>(result.code(), result.message())
}
} else {
NetResult.Failure<Any>(result.code(), result.message())
}
} catch (e: Exception) {
NetResult.Error<Any>(e)
}
}
override suspend fun updateServerInfo(url: String,indoorConnectionInfoBean: IndoorConnectionInfoBean): NetResult<QRCodeBean> =
//在IO线程中运行
withContext(Dispatchers.IO) {
return@withContext try {
val result = netApi.retrofitUpdateServerInfo(url,indoorConnectionInfoBean)
if (result.isSuccessful) {
if (result.code() == 200) {
NetResult.Success(result.body())
} else {
NetResult.Failure<Any>(result.code(), result.message())
}
} else {
NetResult.Failure<Any>(result.code(), result.message())
}
} catch (e: Exception) {
NetResult.Error<Any>(e)
}
}
}

View File

@ -3,7 +3,9 @@ package com.navinfo.omqs.http
import com.navinfo.omqs.bean.EvaluationInfo
import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.collect.library.data.entity.TaskBean
import com.navinfo.omqs.bean.IndoorConnectionInfoBean
import com.navinfo.omqs.bean.LoginUserBean
import com.navinfo.omqs.bean.QRCodeBean
import com.navinfo.omqs.bean.SysUserBean
import okhttp3.ResponseBody
import retrofit2.Response
@ -64,6 +66,22 @@ interface RetrofitNetworkServiceAPI {
@Query("evaluatorNo") evaluatorNo: String,
): Response<DefaultResponse<List<TaskBean>>>
/**
* 连接室内整理工具
*/
@Streaming
@GET
suspend fun retrofitConnectIndoorTools(@Url url: String): Response<QRCodeBean>
/**
* 登录接口
*/
@Headers("Content-Type: application/json")
@POST
suspend fun retrofitUpdateServerInfo(@Url url: String,@Body indoorConnectionInfoBean: IndoorConnectionInfoBean): Response<QRCodeBean>
@Headers("Content-Type: application/json")
@POST("/devcp/uploadSceneProblem")
suspend fun postRequest(@Body listEvaluationInfo: List<EvaluationInfo>?): Response<DefaultResponse<*>>

View File

@ -146,12 +146,12 @@ class TaskUploadScope(
markId = hadLinkDvoBean.mesh,//"20065597"
trackPhotoNumber = "",
markGeometry = it.geometry,
featureName = it.classType,
featureName = it.classCode,
problemType = problemType,
problemPhenomenon = it.phenomenon,
problemDesc = it.description,
problemLink = it.problemLink,
problemReason = it.cause,
preliminaryAnalysis = it.cause,
evaluatorName = it.checkUserId,
evaluationDate = it.checkTime,
evaluationWay = evaluationWay,
@ -166,10 +166,17 @@ class TaskUploadScope(
bodyList.add(evaluationInfo)
}
}else{
val linkStatus = 1
//存在原因标记未测评
if(hadLinkDvoBean.reason.isNotEmpty()){
val linkStatus = 0
}else{
val linkStatus = 1
}
val evaluationInfo = EvaluationInfo(
evaluationTaskId = taskBean.id.toString(),
linkPid = hadLinkDvoBean.linkPid,//"84207223282277331"
linkStatus = 0,
linkStatus = linkStatus,
markId = hadLinkDvoBean.mesh,//"20065597"
trackPhotoNumber = "",
markGeometry = "",
@ -178,13 +185,13 @@ class TaskUploadScope(
problemPhenomenon = "",
problemDesc = "",
problemLink = "",
problemReason = "",
preliminaryAnalysis = "",
evaluatorName = "",
evaluationDate = "",
evaluationWay = 2,
roadClassfcation = "",
roadFunctionGrade = "",
noEvaluationreason = "",
noEvaluationreason = hadLinkDvoBean.reason,
linkLength = 0.0,
dataLevel = "",
linstringLength = 0.0,

View File

@ -0,0 +1,131 @@
package com.navinfo.omqs.server
import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.SystemClock
/**
* date:2023/6/18
* author:qj
* description:定时器
*/
class TimeTask<T : TimeTask.Task?>(context: Context, actionName: String, task: T) {
private var mContext: Context?
private val mActionName: String
private var mReceiver: TimeTaskReceiver? = null
private val mTask: T?
companion object {
private var mPendingIntent: PendingIntent? = null
}
init {
mContext = context
mActionName = actionName
mTask = task
initReceiver(context, actionName)
}
fun startLooperTask() {
if (null != mTask) {
mTask.exeTask()
configureAlarmManager(mTask.period())
}
}
fun stopLooperTask() {
cancelAlarmManager()
}
fun onClose() {
mContext!!.unregisterReceiver(mReceiver)
mContext = null
}
@SuppressLint("ObsoleteSdkInt")
private fun configureAlarmManager(time: Long) {
val manager = mContext!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val pendIntent = pendingIntent
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
manager.setExactAndAllowWhileIdle(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + time,
pendIntent
)
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT -> {
manager.setExact(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + time,
pendIntent
)
}
else -> {
manager[AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + time] = pendIntent
}
}
}
@get:SuppressLint("UnspecifiedImmutableFlag")
private val pendingIntent: PendingIntent?
get() {
if (mPendingIntent == null) {
val requestCode = 0
val intent = Intent()
intent.action = mActionName
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
mPendingIntent = PendingIntent.getBroadcast(
mContext, requestCode, intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
)
}
else -> {
mPendingIntent = PendingIntent.getBroadcast(
mContext,
requestCode,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
}
}
}
return mPendingIntent
}
private fun cancelAlarmManager() {
val manager = mContext!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager
manager.cancel(pendingIntent)
}
private fun initReceiver(context: Context, actionName: String) {
mReceiver = TimeTaskReceiver()
val intentFilter = IntentFilter()
intentFilter.addAction(actionName)
context.registerReceiver(mReceiver, intentFilter)
}
internal inner class TimeTaskReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
startLooperTask()
}
}
interface Task {
fun period(): Long {
// 默认时间5S
return 5000L
}
fun exeTask()
}
}

View File

@ -37,7 +37,8 @@ public class CheckPermissionsActivity extends BaseActivity {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA,
};
private static final int PERMISSON_REQUESTCODE = 0;
@ -53,6 +54,7 @@ public class CheckPermissionsActivity extends BaseActivity {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA,
BACKGROUND_LOCATION_PERMISSION
};
}

View File

@ -31,6 +31,7 @@ import com.navinfo.omqs.ui.activity.BaseActivity
import com.navinfo.omqs.ui.fragment.console.ConsoleFragment
import com.navinfo.omqs.ui.fragment.offlinemap.OfflineMapFragment
import com.navinfo.omqs.ui.fragment.qsrecordlist.QsRecordListFragment
import com.navinfo.omqs.ui.fragment.signMoreInfo.SignMoreInfoFragment
import com.navinfo.omqs.ui.fragment.tasklist.TaskManagerFragment
import com.navinfo.omqs.ui.widget.RecyclerViewSpacesItemDecoration
import com.navinfo.omqs.util.FlowEventBus
@ -56,10 +57,11 @@ class MainActivity : BaseActivity() {
*/
private var leftFragment: Fragment? = null
/**
* 是否开启右侧面板
*/
var switchFragment = false
private var switchFragment = false
/**
* 检测是否含有tts插件
@ -88,6 +90,7 @@ class MainActivity : BaseActivity() {
*/
private val signAdapter by lazy {
SignAdapter(object : OnSignAdapterClickListener {
//点击看板进去问题反馈面板
override fun onItemClick(signBean: SignBean) {
rightController.currentDestination?.let {
if (it.id == R.id.RightEmptyFragment) {
@ -99,14 +102,15 @@ class MainActivity : BaseActivity() {
}
}
//点击详细信息
override fun onMoreInfoClick(selectTag: String, tag: String, signBean: SignBean) {
if (binding.mainActivitySignMoreInfoGroup.visibility != View.VISIBLE || selectTag != tag) {
binding.mainActivitySignMoreInfoGroup.visibility = View.VISIBLE
binding.mainActivitySignMoreInfoTitle.text = signBean.name
binding.mainActivitySignMoreInfoText1.text = signBean.bottomRightText
binding.mainActivitySignMoreInfoText2.text = signBean.moreText
} else {
binding.mainActivitySignMoreInfoGroup.visibility = View.GONE
viewModel.showSignMoreInfo(signBean.renderEntity)
val fragment =
supportFragmentManager.findFragmentById(R.id.main_activity_sign_more_info_fragment)
if (fragment == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.main_activity_sign_more_info_fragment, SignMoreInfoFragment())
.commit()
}
}
@ -120,10 +124,6 @@ class MainActivity : BaseActivity() {
}
}
}
override fun onHideMoreInfoView() {
binding.mainActivitySignMoreInfoGroup.visibility = View.GONE
}
})
}
@ -150,8 +150,6 @@ class MainActivity : BaseActivity() {
checkIntent.action = TextToSpeech.Engine.ACTION_CHECK_TTS_DATA
someActivityResultLauncher.launch(checkIntent)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
//初始化地图
@ -184,12 +182,12 @@ class MainActivity : BaseActivity() {
}
v?.onTouchEvent(event) ?: true
}
//捕捉列表变化回调
viewModel.liveDataQsRecordIdList.observe(this) {
//处理页面跳转
viewModel.navigationRightFragment(this, it)
}
//右上角菜单是否被点击
viewModel.liveDataMenuState.observe(this) {
binding.mainActivityMenu.isSelected = it
if (it == true) {
@ -198,6 +196,17 @@ class MainActivity : BaseActivity() {
binding.mainActivityMenuGroup.visibility = View.INVISIBLE
}
}
//道路绑定,名称变化
viewModel.liveDataRoadName.observe(this) {
if (it != null) {
binding.mainActivityRoadName.text = it.properties["name"]
if (binding.mainActivityRoadName.visibility != View.VISIBLE) binding.mainActivityRoadName.visibility =
View.VISIBLE
} else {
if (binding.mainActivityRoadName.visibility != View.GONE) binding.mainActivityRoadName.visibility =
View.GONE
}
}
//道路属性面板
binding.mainActivityTopSignRecyclerview.layoutManager = LinearLayoutManager(
@ -228,15 +237,14 @@ class MainActivity : BaseActivity() {
viewModel.liveDataTopSignList.observe(this) {
topSignAdapter.refreshData(it)
}
//监听地图中点变化
viewModel.liveDataCenterPoint.observe(this) {
// Log.e("qj", "${it.longitude}")
try {
if (it != null && it.longitude != null && it.latitude != null) {
binding.mainActivityGeometry.text = "经纬度:${
BigDecimal(it.longitude).setScale(
7,
RoundingMode.HALF_UP
7, RoundingMode.HALF_UP
)
},${BigDecimal(it.latitude).setScale(7, RoundingMode.HALF_UP)}"
}
@ -245,6 +253,16 @@ class MainActivity : BaseActivity() {
}
}
viewModel.liveDataSignMoreInfo.observe(this){
val fragment =
supportFragmentManager.findFragmentById(R.id.main_activity_sign_more_info_fragment)
if (fragment == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.main_activity_sign_more_info_fragment, SignMoreInfoFragment())
.commit()
}
}
lifecycleScope.launch {
// 初始化地图图层控制接收器
FlowEventBus.subscribe<List<ImportConfig>>(
@ -475,8 +493,7 @@ class MainActivity : BaseActivity() {
}
leftFragment = TaskManagerFragment {
binding.mainActivityLeftFragment.visibility = View.GONE
supportFragmentManager.beginTransaction()
.remove(leftFragment!!).commit()
supportFragmentManager.beginTransaction().remove(leftFragment!!).commit()
leftFragment = null
null
}
@ -496,8 +513,7 @@ class MainActivity : BaseActivity() {
}
leftFragment = QsRecordListFragment {
binding.mainActivityLeftFragment.visibility = View.GONE
supportFragmentManager.beginTransaction()
.remove(leftFragment!!).commit()
supportFragmentManager.beginTransaction().remove(leftFragment!!).commit()
leftFragment = null
null
}
@ -524,8 +540,7 @@ class MainActivity : BaseActivity() {
}
leftFragment = OfflineMapFragment {
binding.mainActivityLeftFragment.visibility = View.GONE
supportFragmentManager.beginTransaction()
.remove(leftFragment!!).commit()
supportFragmentManager.beginTransaction().remove(leftFragment!!).commit()
leftFragment = null
null
}
@ -533,4 +548,13 @@ class MainActivity : BaseActivity() {
.replace(R.id.main_activity_left_fragment, leftFragment!!).commit()
}
}
/**
* 打开道路名称属性看板选择的道路在viewmodel里记录不用
*/
fun openRoadNameFragment() {
if (viewModel.liveDataRoadName.value != null) {
viewModel.showSignMoreInfo(viewModel.liveDataRoadName.value!!)
}
}
}

View File

@ -31,6 +31,7 @@ import com.navinfo.collect.library.utils.GeometryToolsKt
import com.navinfo.omqs.Constant
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.ImportConfig
import com.navinfo.omqs.bean.RoadNameBean
import com.navinfo.omqs.bean.SignBean
import com.navinfo.omqs.db.RealmOperateHelper
import com.navinfo.omqs.ui.dialog.CommonDialog
@ -76,6 +77,14 @@ class MainViewModel @Inject constructor(
//顶部看板数据
val liveDataTopSignList = MutableLiveData<List<SignBean>>()
//道路名
val liveDataRoadName = MutableLiveData<RenderEntity?>()
/**
* 当前选中的要展示的详细信息的要素
*/
val liveDataSignMoreInfo = MutableLiveData<RenderEntity>()
// var testPoint = GeoPoint(0, 0)
//uuid标识用于记录轨迹组
@ -93,6 +102,7 @@ class MainViewModel @Inject constructor(
var menuState: Boolean = false
val liveDataMenuState = MutableLiveData<Boolean>()
val liveDataCenterPoint = MutableLiveData<MapPosition>()
@ -107,8 +117,8 @@ class MainViewModel @Inject constructor(
init {
mapController.mMapView.vtmMap.events.bind(Map.UpdateListener { e, mapPosition ->
when (e) {
Map.SCALE_EVENT, Map.MOVE_EVENT, Map.ROTATE_EVENT ->
liveDataCenterPoint.value = mapPosition
Map.SCALE_EVENT, Map.MOVE_EVENT, Map.ROTATE_EVENT -> liveDataCenterPoint.value =
mapPosition
}
})
@ -213,6 +223,7 @@ class MainViewModel @Inject constructor(
val linkList = realmOperateHelper.queryLink(
point = point,
)
var hisRoadName = false
if (linkList.isNotEmpty()) {
//看板数据
val signList = mutableListOf<SignBean>()
@ -225,11 +236,17 @@ class MainViewModel @Inject constructor(
if (linkIdCache != linkId) {
Log.e("jingo", "捕捉到的linkid $linkId ${link.geometry}")
mapController.lineHandler.showLine(link.geometry)
linkId?.let {
var elementList = realmOperateHelper.queryLinkByLinkPid(it)
for (element in elementList) {
if (element.code == 2011) {
hisRoadName = true
liveDataRoadName.postValue(element)
continue
}
val distance = GeometryTools.distanceToDouble(
point, GeometryTools.createGeoPoint(element.geometry)
)
@ -238,20 +255,20 @@ class MainViewModel @Inject constructor(
iconId = SignUtil.getSignIcon(element),
iconText = SignUtil.getSignIconText(element),
distance = distance.toInt(),
elementId = element.id,
linkId = linkId,
geometry = element.geometry,
name = SignUtil.getSignNameText(element),
bottomRightText = SignUtil.getSignBottomRightText(element),
elementCode = element.code,
moreText = SignUtil.getMoreInfoText(element)
renderEntity = element,
isMoreInfo = SignUtil.isMoreInfo(element),
index = SignUtil.getRoadInfoIndex(element)
)
Log.e("jingo", "捕捉到的数据code ${element.code}")
when (element.code) {
2002, 2008, 2010, 2041 -> topSignList.add(
//车道数,种别,功能等级,线限速,道路方向
2041, 2008, 2002, 2019, 2010 -> topSignList.add(
signBean
)
4002, 4003, 4004, 4022 -> signList.add(
4002, 4003, 4004, 4010, 4022, 4601 -> signList.add(
signBean
)
}
@ -260,33 +277,27 @@ class MainViewModel @Inject constructor(
val realm = Realm.getDefaultInstance()
val entity = realm.where(RenderEntity::class.java)
.equalTo("table", "OMDB_RESTRICTION")
.and()
.equalTo(
"properties['linkIn']",
it
.equalTo("table", "OMDB_RESTRICTION").and().equalTo(
"properties['linkIn']", it
).findFirst()
if (entity != null) {
val outLink = entity.properties["linkOut"]
val linkOutEntity = realm.where(RenderEntity::class.java)
.equalTo("table", "OMDB_RD_LINK")
.and()
.equalTo(
.equalTo("table", "OMDB_RD_LINK").and().equalTo(
"properties['${RenderEntity.Companion.LinkTable.linkPid}']",
outLink
).findFirst()
if (linkOutEntity != null) {
mapController.lineHandler.linksLayer.addLine(
linkOutEntity.geometry,
0x7DFF0000
linkOutEntity.geometry, 0x7DFF0000
)
Log.e("jingo", "捕捉到的linkid $outLink ${linkOutEntity.geometry}")
}
}
}
liveDataTopSignList.postValue(topSignList.distinctBy { it.elementCode })
liveDataSignList.postValue(signList.distinctBy { it.elementCode })
liveDataTopSignList.postValue(topSignList.distinctBy { it.name }.sortedBy { it.index })
liveDataSignList.postValue(signList.sortedBy { it.distance })
val speechText = SignUtil.getRoadSpeechText(topSignList)
withContext(Dispatchers.Main) {
speakMode?.speakText(speechText)
@ -297,6 +308,10 @@ class MainViewModel @Inject constructor(
mapController.lineHandler.removeLine()
linkIdCache = ""
}
//如果没有捕捉到道路名
if (!hisRoadName) {
liveDataRoadName.postValue(null)
}
}
}
@ -488,8 +503,19 @@ class MainViewModel @Inject constructor(
}
}
/**
* 是否开启了线选择
*/
fun isSelectRoad(): Boolean {
return bSelectRoad
}
/**
* 要展示的要素详细信息
*/
fun showSignMoreInfo(data: RenderEntity) {
liveDataSignMoreInfo.value = data
}
}

View File

@ -1,63 +1,137 @@
package com.navinfo.omqs.ui.activity.map
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.SignBean
import com.navinfo.omqs.databinding.AdapterSignBinding
import com.navinfo.omqs.databinding.AdapterSignLaneinfoBinding
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder
import com.navinfo.omqs.ui.widget.SignUtil
interface OnSignAdapterClickListener {
fun onItemClick(signBean: SignBean)
fun onMoreInfoClick(selectTag: String, tag: String, signBean: SignBean)
fun onErrorClick(signBean: SignBean)
fun onHideMoreInfoView()
}
data class LaneInfoItem(val id: Int, val type: Int)
class SignAdapter(private var listener: OnSignAdapterClickListener?) :
BaseRecyclerViewAdapter<SignBean>() {
/**
* 选中的详细信息按钮的tag标签
*/
private var selectMoreInfoTag: String = ""
override fun getItemViewRes(position: Int): Int {
return R.layout.adapter_sign
override fun getItemViewType(position: Int): Int {
if (data.isNotEmpty() && data[position].renderEntity.code == 4601) {
return 4601
}
return 0
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
val viewBinding =
AdapterSignBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return BaseViewHolder(viewBinding)
return if (viewType == 4601) {
val viewBinding =
AdapterSignLaneinfoBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
BaseViewHolder(viewBinding)
} else {
val viewBinding =
AdapterSignBinding.inflate(LayoutInflater.from(parent.context), parent, false)
BaseViewHolder(viewBinding)
}
}
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
val bd = holder.viewBinding as AdapterSignBinding
val context = holder.viewBinding.root.context
val item = data[position]
if (item.iconId != 0) bd.signMainIconBg.setImageResource(item.iconId)
bd.signMainIcon.text = item.iconText
bd.signBottomText.text = item.name
holder.tag = item.name + position
//点击错误按钮
bd.signMainFastError.setOnClickListener {
listener?.onErrorClick(item)
}
bd.signBottomRightText.text = item.bottomRightText
if (holder.viewBinding is AdapterSignBinding) {
val bd = holder.viewBinding
bd.root.setOnClickListener {
listener?.onItemClick(item)
}
if (item.moreText.isNotEmpty()) {
bd.signMainInfo.visibility = View.VISIBLE
//点击更多信息按钮
bd.signMainInfo.setOnClickListener {
listener?.onMoreInfoClick(selectMoreInfoTag, holder.tag, item)
selectMoreInfoTag = holder.tag
if (item.iconId != 0) bd.signMainIconBg.setImageResource(item.iconId)
bd.signMainIcon.text = item.iconText
bd.signBottomText.text = item.name
//点击错误按钮
bd.signMainFastError.setOnClickListener {
listener?.onErrorClick(item)
}
} else bd.signMainInfo.visibility = View.GONE
bd.signBottomRightText.text = item.bottomRightText
if (item.isMoreInfo) {
bd.signMainInfo.visibility = View.VISIBLE
bd.signMainInfo.setOnClickListener {
listener?.onMoreInfoClick(selectMoreInfoTag, holder.tag, item)
selectMoreInfoTag = holder.tag
}
} else {
bd.signMainInfo.visibility = View.GONE
}
bd.signSecondIcon.text = ""
if (item.renderEntity.code == 4002) {
val minSpeed = SignUtil.getSpeedLimitMinText(item.renderEntity)
if (minSpeed != "0") {
bd.signSecondIcon.text = minSpeed
}
}
bd.signMainBg.setOnClickListener {
listener?.onItemClick(item)
}
} else if (holder.viewBinding is AdapterSignLaneinfoBinding) {
val bd = holder.viewBinding
bd.signMoreIconsLayout.removeAllViews()
bd.signBottomText.text = item.name
bd.signBottomRightText.text = item.distance.toString()
val list = SignUtil.getLineInfoIcons(item.renderEntity)
val lineViewS = View(context)
lineViewS.layoutParams = ViewGroup.LayoutParams(24, 80)
lineViewS.background = context.getDrawable(R.drawable.shape_vertical_dashed_line)
bd.signMoreIconsLayout.addView(lineViewS, lineViewS.layoutParams)
for (i in list.indices) {
val laneInfo = list[i]
val imageView = ImageView(context)
val drawable = context.getDrawable(laneInfo.id)
var color = when (laneInfo.type) {
1 -> bd.root.resources.getColor(R.color.lane_info_1)
2 -> bd.root.resources.getColor(R.color.lane_info_2)
else -> bd.root.resources.getColor(R.color.white)
}
// 创建 PorterDuffColorFilter 对象
val colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)
// 将 PorterDuffColorFilter 设置给 Drawable
drawable!!.colorFilter = colorFilter
// 将 Drawable 设置给 ImageView
imageView.background = drawable
// 将 ImageView 的颜色设置为红色
imageView.setColorFilter(color, PorterDuff.Mode.SRC_IN)
imageView.layoutParams = ViewGroup.LayoutParams(35, 100)
bd.signMoreIconsLayout.addView(imageView, imageView.layoutParams)
if (i < list.size - 1) {
val lineView = View(context)
lineView.layoutParams = ViewGroup.LayoutParams(24, 80)
lineView.background = context.getDrawable(R.drawable.shape_vertical_dashed_line)
bd.signMoreIconsLayout.addView(lineView, lineView.layoutParams)
}
}
val lineViewE = View(context)
lineViewE.layoutParams = ViewGroup.LayoutParams(24, 80)
lineViewE.background = context.getDrawable(R.drawable.shape_vertical_dashed_line)
bd.signMoreIconsLayout.addView(lineViewE, lineViewE.layoutParams)
bd.root.setOnClickListener {
listener?.onItemClick(item)
}
}
holder.tag = item.name + position
}
override fun refreshData(newData: List<SignBean>) {
@ -67,7 +141,6 @@ class SignAdapter(private var listener: OnSignAdapterClickListener?) :
return
}
}
listener?.onHideMoreInfoView()
}
}

View File

@ -11,9 +11,6 @@ import com.navinfo.omqs.ui.other.BaseViewHolder
class TopSignAdapter(private var itemListener: ((Int, SignBean) -> Unit?)? = null) :
BaseRecyclerViewAdapter<SignBean>() {
override fun getItemViewRes(position: Int): Int {
return R.layout.adapter_top_sign
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
val viewBinding =

View File

@ -0,0 +1,256 @@
package com.navinfo.omqs.ui.activity.scan
import android.content.Context
import android.text.TextUtils
import android.widget.Toast
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.navinfo.omqs.Constant
import com.navinfo.omqs.bean.IndoorConnectionInfoBean
import com.navinfo.omqs.bean.QRCodeBean
import com.navinfo.omqs.bean.SysUserBean
import com.navinfo.omqs.http.DefaultResponse
import com.navinfo.omqs.http.NetResult
import com.navinfo.omqs.http.NetworkService
import com.navinfo.omqs.ui.activity.login.LoginStatus
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.IOException
import javax.inject.Inject
enum class QrCodeStatus {
/**
* 网络访问失败
*/
QR_CODE_STATUS_NET_FAILURE,
/**
* 成功
*/
QR_CODE_STATUS_SUCCESS,
/**
* 信息更新成功
*/
QR_CODE_STATUS_SERVER_INFO_SUCCESS,
}
@HiltViewModel
class QrCodeViewModel @Inject constructor(
private val networkService: NetworkService
) : ViewModel() {
//用户信息
val qrCodeBean: MutableLiveData<QRCodeBean> = MutableLiveData()
//是不是连接成功
val qrCodeStatus: MutableLiveData<QrCodeStatus> = MutableLiveData()
init {
qrCodeBean.value = QRCodeBean()
}
/**
* 扫一扫按钮
*/
fun connect(context: Context, ips: String) {
if (TextUtils.isEmpty(ips)) {
Toast.makeText(context, "获取ip失败", Toast.LENGTH_LONG).show()
return
}
val ipArray = ips.split(";".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
//测试代码
//final String[] ipArray = new String[]{"172.21.2.137"};
if (ipArray.isEmpty()) {
Toast.makeText(context, "获取ip失败", Toast.LENGTH_SHORT).show()
return
}
ipArray.forEach { ip ->
if (!TextUtils.isEmpty(ip)) {
viewModelScope.launch(Dispatchers.Default) {
val ipTemp: String = ip
val url = "http://$ipTemp:8080/sensor/service/keepalive"
when (val result = networkService.connectIndoorTools(url)) {
is NetResult.Success<*> -> {
if (result.data != null) {
try {
val defaultUserResponse = result.data as QRCodeBean
if (defaultUserResponse.errcode == 0) {
Constant.INDOOR_IP = ipTemp
qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_SUCCESS)
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"连接室内整理工具成功。",
Toast.LENGTH_LONG
).show()
}
} else {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"${defaultUserResponse.msg}",
Toast.LENGTH_SHORT
)
.show()
}
}
} catch (e: IOException) {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"${e.message}",
Toast.LENGTH_SHORT
).show()
}
}
}
}
is NetResult.Error<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"${result.exception.message}",
Toast.LENGTH_SHORT
)
.show()
}
qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_NET_FAILURE)
}
is NetResult.Failure<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"${result.code}:${result.msg}",
Toast.LENGTH_SHORT
)
.show()
}
qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_NET_FAILURE)
}
else -> {}
}
}
}
}
}
/**
* 扫一扫按钮
*/
fun updateServerInfo(context: Context) {
if (TextUtils.isEmpty(Constant.INDOOR_IP)) {
Toast.makeText(context, "获取ip失败", Toast.LENGTH_LONG).show()
return
}
viewModelScope.launch(Dispatchers.Default) {
val url = "http://${Constant.INDOOR_IP}:8080/sensor/service/connection"
when (val result = networkService.updateServerInfo(
url = url,
indoorConnectionInfoBean = IndoorConnectionInfoBean(
Constant.USER_ID,
Constant.USER_ID,
Constant.USER_ID,
Constant.USER_ID,
com.navinfo.collect.library.system.Constant.SERVER_ADDRESS,
Constant.USER_ID,
"Android"
)
)) {
is NetResult.Success<*> -> {
if (result.data != null) {
try {
val defaultUserResponse = result.data as QRCodeBean
if (defaultUserResponse.errcode == 0) {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"信息更新成功。",
Toast.LENGTH_LONG
).show()
qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_SERVER_INFO_SUCCESS)
}
} else {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"${defaultUserResponse.msg}",
Toast.LENGTH_SHORT
)
.show()
}
}
} catch (e: IOException) {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"${e.message}",
Toast.LENGTH_SHORT
).show()
}
}
}
}
is NetResult.Error<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"${result.exception.message}",
Toast.LENGTH_SHORT
)
.show()
}
qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_NET_FAILURE)
}
is NetResult.Failure<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"${result.code}:${result.msg}",
Toast.LENGTH_SHORT
)
.show()
}
qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_NET_FAILURE)
}
else -> {}
}
}
}
override fun onCleared() {
super.onCleared()
}
}

View File

@ -0,0 +1,147 @@
package com.navinfo.omqs.ui.activity.scan
import android.annotation.SuppressLint
import android.graphics.Rect
import android.graphics.RectF
import android.os.Bundle
import android.util.Log
import androidx.activity.viewModels
import androidx.camera.core.ImageCapture
import androidx.camera.view.LifecycleCameraController
import androidx.databinding.DataBindingUtil
import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.ActivityQrCodeBinding
import com.navinfo.omqs.ui.activity.BaseActivity
import com.navinfo.omqs.ui.listener.QRCodeAnalyser
import dagger.hilt.android.AndroidEntryPoint
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import androidx.lifecycle.Observer
import com.navinfo.omqs.ui.activity.login.LoginStatus
/**
* date:2023/6/18
* author:qj
* description:二维码扫描
*/
@AndroidEntryPoint
class QrCodeActivity : BaseActivity() {
private lateinit var binding: ActivityQrCodeBinding
private lateinit var lifecycleCameraController: LifecycleCameraController
private lateinit var cameraExecutor: ExecutorService
private val viewModel by viewModels<QrCodeViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_qr_code)
binding.qrCodeModel = viewModel
binding.lifecycleOwner = this
binding.activity = this
initView()
initController()
}
private fun initView() {
//登录校验,初始化成功
viewModel.qrCodeStatus.observe(this, qrCodeObserve)
}
/*
* 监听扫描结果
* */
private val qrCodeObserve = Observer<QrCodeStatus> {
when (it) {
QrCodeStatus.QR_CODE_STATUS_SUCCESS -> {
finish()
}
QrCodeStatus.QR_CODE_STATUS_NET_FAILURE -> {
}
QrCodeStatus.QR_CODE_STATUS_SERVER_INFO_SUCCESS -> {
}
}
}
@SuppressLint("ClickableViewAccessibility", "UnsafeOptInUsageError")
private fun initController() {
cameraExecutor = Executors.newSingleThreadExecutor()
lifecycleCameraController = LifecycleCameraController(this)
lifecycleCameraController.bindToLifecycle(this)
lifecycleCameraController.imageCaptureFlashMode = ImageCapture.FLASH_MODE_AUTO
lifecycleCameraController.setImageAnalysisAnalyzer(
cameraExecutor,
QRCodeAnalyser { barcodes, imageWidth, imageHeight ->
if (barcodes.isEmpty()) {
return@QRCodeAnalyser
}
initScale(imageWidth, imageHeight)
val list = ArrayList<RectF>()
val strList = ArrayList<String>()
barcodes.forEach { barcode ->
barcode.boundingBox?.let { rect ->
val translateRect = translateRect(rect)
list.add(translateRect)
Log.e(
"ztzt", "left${translateRect.left} +" +
" top${translateRect.top} + right${translateRect.right}" +
" + bottom${translateRect.bottom}"
)
Log.e("ztzt", "barcode.rawValue${barcode.rawValue}")
strList.add(barcode.rawValue ?: "No Value")
}
}
judgeIntent(strList)
binding.scanView.setRectList(list)
})
binding.previewView.controller = lifecycleCameraController
}
fun judgeIntent(list: ArrayList<String>) {
val sb = StringBuilder()
list.forEach {
sb.append(it)
sb.append("\n")
}
intentToResult(sb.toString())
}
private fun intentToResult(result: String) {
Log.e("qj", "QRCodeActivity === $result")
viewModel.connect(this, result)
/* val intent = Intent(this, QRCodeResultActivity::class.java)
intent.putExtra(QRCodeResultActivity.RESULT_KEY, result)
startActivity(intent)
finish()*/
}
private var scaleX = 0f
private var scaleY = 0f
private fun translateX(x: Float): Float = x * scaleX
private fun translateY(y: Float): Float = y * scaleY
//将扫描的矩形换算为当前屏幕大小
private fun translateRect(rect: Rect) = RectF(
translateX(rect.left.toFloat()),
translateY(rect.top.toFloat()),
translateX(rect.right.toFloat()),
translateY(rect.bottom.toFloat())
)
//初始化缩放比例
private fun initScale(imageWidth: Int, imageHeight: Int) {
Log.e("ztzt", "imageWidth${imageWidth} + imageHeight${imageHeight}")
scaleY = binding.scanView.height.toFloat() / imageWidth.toFloat()
scaleX = binding.scanView.width.toFloat() / imageHeight.toFloat()
Log.e("ztzt", "scaleX${scaleX} + scaleY${scaleY}")
}
}

View File

@ -0,0 +1,30 @@
package com.navinfo.omqs.ui.activity.scan
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.navinfo.omqs.databinding.ActivityResultBinding
/**
* date:2021/6/18
* author:zhangteng
* description:
*/
class QRCodeResultActivity : AppCompatActivity() {
private lateinit var binding: ActivityResultBinding
companion object {
const val RESULT_KEY = "result_key";
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityResultBinding.inflate(layoutInflater)
setContentView(binding.root)
val intent = intent
binding.text.text = intent.getStringExtra(RESULT_KEY)
binding.button.setOnClickListener {
finish()
}
}
}

View File

@ -1,13 +1,8 @@
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(
@ -49,8 +44,8 @@ abstract class BaseFragment : Fragment() {
// savedInstanceState: Bundle?
// ): View
fun onBackPressed(): Boolean{
findNavController().navigateUp()
open fun onBackPressed(): Boolean{
// findNavController().navigateUp()
return true
}

View File

@ -1,6 +1,5 @@
package com.navinfo.omqs.ui.fragment.evaluationresult
import android.app.Dialog
import android.os.Build
import android.os.Bundle
import android.util.Log
@ -8,19 +7,22 @@ import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.databinding.DataBindingUtil
import androidx.navigation.NavOptions
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.navinfo.omqs.Constant
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.SignBean
import com.navinfo.omqs.databinding.FragmentEvaluationResultBinding
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 androidx.navigation.findNavController
import com.navinfo.omqs.ui.dialog.FirstDialog
import org.videolan.vlc.Util
@AndroidEntryPoint
class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
@ -31,6 +33,10 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
*/
private val viewModel by shareViewModels<EvaluationResultViewModel>("QsRecode")
private val pictureAdapter by lazy {
PictureAdapter()
}
// private val args:EmptyFragmentArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
@ -56,6 +62,8 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
adapter.refreshData(it)
}
binding.evaluationPictureViewpager
return binding.root
}
@ -70,12 +78,12 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
val mDialog = FirstDialog(context)
mDialog.setTitle("提示?")
mDialog.setMessage("是否退出,请确认!")
mDialog.setPositiveButton("确定", object : FirstDialog.OnClickListener {
override fun onClick(dialog: Dialog?, which: Int) {
mDialog.dismiss()
onBackPressed()
}
})
mDialog.setPositiveButton(
"确定"
) { _, _ ->
mDialog.dismiss()
onBackPressed()
}
mDialog.setNegativeButton("取消", null)
mDialog.show()
}
@ -91,6 +99,21 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
viewModel.deleteData(requireContext())
}
/**
* 照片view
*/
binding.evaluationPictureViewpager.adapter = pictureAdapter
val list = mutableListOf("1", "2", "3")
pictureAdapter.refreshData(list)
binding.evaluationPictureLeft.setOnClickListener(this)
binding.evaluationPictureRight.setOnClickListener(this)
val recyclerView = binding.evaluationPictureViewpager.getChildAt(0) as RecyclerView
recyclerView.setPadding(0, 0, Util.convertDpToPx(requireContext(), 50), 0)
recyclerView.clipToPadding = false
binding.evaluationVoice.setOnTouchListener { _, event ->
@ -111,6 +134,7 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
true
}
/**
* 读取元数据
*/
@ -249,6 +273,24 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
override fun onClick(v: View?) {
v?.let {
when (v.id) {
//照片左侧按钮
R.id.evaluation_picture_left -> {
val currentItem = binding.evaluationPictureViewpager.currentItem
if (currentItem > 0) {
binding.evaluationPictureViewpager.currentItem = currentItem - 1
} else {
}
}
//照片右侧按钮
R.id.evaluation_picture_right -> {
val currentItem = binding.evaluationPictureViewpager.currentItem
if (currentItem < pictureAdapter.data.size - 1) {
binding.evaluationPictureViewpager.currentItem = currentItem + 1
} else {
}
}
//上三项,打开面板
R.id.evaluation_class_type, R.id.evaluation_problem_type, R.id.evaluation_phenomenon -> {
activity?.run {
@ -315,4 +357,9 @@ class EvaluationResultFragment : BaseFragment(), View.OnClickListener {
}
}
override fun onBackPressed(): Boolean {
findNavController().navigateUp()
return true
}
}

View File

@ -26,6 +26,7 @@ import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.omqs.Constant
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.ChatMsgEntity
import com.navinfo.omqs.bean.ScProblemTypeBean
import com.navinfo.omqs.bean.SignBean
import com.navinfo.omqs.db.RealmOperateHelper
import com.navinfo.omqs.db.RoomAppDatabase
@ -65,7 +66,7 @@ class EvaluationResultViewModel @Inject constructor(
/**
* 问题分类 liveData[LeftAdapter]展示的数据
*/
val liveDataLeftTypeList = MutableLiveData<List<String>>()
val liveDataLeftTypeList = MutableLiveData<List<ScProblemTypeBean>>()
/**
* 问题类型 liveData [MiddleAdapter]展示的数据
@ -95,6 +96,8 @@ class EvaluationResultViewModel @Inject constructor(
var classTypeTemp: String = ""
var classCodeTemp: String = ""
init {
liveDataQsRecordBean.value = QsRecordBean(id = UUID.randomUUID().toString())
viewModelScope.launch {
@ -137,7 +140,7 @@ class EvaluationResultViewModel @Inject constructor(
}
} else {
liveDataQsRecordBean.value?.run {
elementId = bean.elementId
elementId = bean.renderEntity.code.toString()
linkId = bean.linkId
if (linkId.isNotEmpty()) {
viewModelScope.launch {
@ -149,7 +152,7 @@ class EvaluationResultViewModel @Inject constructor(
}
}
}
val point = GeometryTools.createGeoPoint(bean.geometry)
val point = GeometryTools.createGeoPoint(bean.renderEntity.geometry)
this.geometry = GeometryTools.createGeometry(point).toText()
mapController.animationHandler.animationByLatLon(point.latitude, point.longitude)
mapController.markerHandle.addMarker(point, markerTitle)
@ -194,22 +197,24 @@ class EvaluationResultViewModel @Inject constructor(
list?.let {
if (list.isNotEmpty()) {
//通知页面更新
var classType = list[0]
var classType = list[0].classType
var classCode = list[0].elementCode
liveDataLeftTypeList.postValue(it)
if (bean != null) {
val classType2 = roomAppDatabase.getScProblemTypeDao()
.findClassTypeByCode(bean.elementCode)
val classType2 = roomAppDatabase.getScProblemTypeDao().findClassTypeByCode(bean.renderEntity.code)
if (classType2 != null) {
classType = classType2
}
}
//如果右侧栏没数据,给个默认值
if (liveDataQsRecordBean.value!!.classType.isEmpty()) {
liveDataQsRecordBean.value!!.classType = classType
liveDataQsRecordBean.value!!.classCode = classCode
classTypeTemp = classType
classCodeTemp = classCode
} else {
classType = liveDataQsRecordBean.value!!.classType
classCode = liveDataQsRecordBean.value!!.classCode
}
getProblemList(classType)
}
@ -298,6 +303,7 @@ class EvaluationResultViewModel @Inject constructor(
*/
fun setPhenomenonMiddleBean(adapterBean: RightBean) {
liveDataQsRecordBean.value!!.classType = classTypeTemp
liveDataQsRecordBean.value!!.classCode = classCodeTemp
liveDataQsRecordBean.value!!.phenomenon = adapterBean.text
liveDataQsRecordBean.value!!.problemType = adapterBean.title
liveDataQsRecordBean.postValue(liveDataQsRecordBean.value)

View File

@ -5,17 +5,15 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.ScProblemTypeBean
import com.navinfo.omqs.databinding.TextItemSelectBinding
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder
class LeftAdapter(private var itemListener: ((Int, String) -> Unit?)? = null) :
BaseRecyclerViewAdapter<String>() {
BaseRecyclerViewAdapter<ScProblemTypeBean>() {
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 =
@ -27,18 +25,18 @@ class LeftAdapter(private var itemListener: ((Int, String) -> Unit?)? = null) :
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
val bd = holder.viewBinding as TextItemSelectBinding
val title = data[position]
bd.itemId.text = title
holder.viewBinding.root.isSelected = selectTitle == title
bd.itemId.text = title.classType
holder.viewBinding.root.isSelected = selectTitle == title.classType
bd.root.setOnClickListener {
if (selectTitle != title) {
selectTitle = title
if (selectTitle != title.classType) {
selectTitle = title.classType
notifyDataSetChanged()
}
itemListener?.invoke(position, title)
itemListener?.invoke(position, title.classType)
}
}
override fun refreshData(newData: List<String>) {
override fun refreshData(newData: List<ScProblemTypeBean>) {
data = newData
notifyDataSetChanged()
}

View File

@ -13,9 +13,6 @@ class MiddleAdapter(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 =

View File

@ -0,0 +1,21 @@
package com.navinfo.omqs.ui.fragment.evaluationresult
import android.view.LayoutInflater
import android.view.ViewGroup
import com.navinfo.omqs.databinding.AdapterPictureBinding
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder
class PictureAdapter : BaseRecyclerViewAdapter<String>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
val viewBinding =
AdapterPictureBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return BaseViewHolder(viewBinding)
}
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
val bd = holder.viewBinding as AdapterPictureBinding
bd.button.text = data[position]
}
}

View File

@ -11,9 +11,6 @@ class RightGroupHeaderAdapter(private var itemListener: ((Int, RightBean) -> Uni
BaseRecyclerViewAdapter<RightBean>() {
private var selectTitle = ""
private var groupTitleList = mutableListOf<String>()
override fun getItemViewRes(position: Int): Int {
return R.layout.text_item_select2
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
val viewBinding =

View File

@ -224,10 +224,6 @@ class SoundtListAdapter(
}
}
override fun getItemViewRes(position: Int): Int {
return R.layout.adapter_sound_list
}
}

View File

@ -131,10 +131,6 @@ class OfflineMapCityListAdapter(
}
}
}
override fun getItemViewRes(position: Int): Int {
return R.layout.adapter_offline_map_city
}
}

View File

@ -1,13 +1,14 @@
package com.navinfo.omqs.ui.fragment.personalcenter
import android.Manifest
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.blankj.utilcode.util.ToastUtils
import com.blankj.utilcode.util.UriUtils
@ -21,6 +22,8 @@ import com.navinfo.omqs.db.ImportOMDBHelper
import com.navinfo.omqs.hilt.ImportOMDBHiltFactory
import com.navinfo.omqs.tools.CoroutineUtils
import com.navinfo.omqs.ui.fragment.BaseFragment
import com.navinfo.omqs.ui.activity.scan.QrCodeActivity
import com.permissionx.guolindev.PermissionX
import dagger.hilt.android.AndroidEntryPoint
import org.oscim.core.GeoPoint
import javax.inject.Inject
@ -123,6 +126,16 @@ class PersonalCenterFragment(private var backListener: (() -> Unit?)? = null) :
// R.id.personal_center_menu_layer_manager -> { // 图层管理
// findNavController().navigate(R.id.QsLayerManagerFragment)
// }
/* R.id.personal_center_menu_qs_record_list -> {
findNavController().navigate(R.id.QsRecordListFragment)
}
R.id.personal_center_menu_layer_manager -> { // 图层管理
findNavController().navigate(R.id.QsLayerManagerFragment)
}*/
R.id.personal_center_menu_scan_qr_code -> {
//跳转二维码扫描界面
checkPermission()
}
}
true
}
@ -134,6 +147,11 @@ class PersonalCenterFragment(private var backListener: (() -> Unit?)? = null) :
fileChooser.setCallbacks(this@PersonalCenterFragment)
}
private fun intentTOQRCode() {
var intent = Intent(context, QrCodeActivity::class.java);
startActivity(intent)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
@ -147,4 +165,18 @@ class PersonalCenterFragment(private var backListener: (() -> Unit?)? = null) :
super.onActivityResult(requestCode, resultCode, data)
fileChooser.onActivityResult(requestCode, resultCode, data)
}
private fun checkPermission() {
PermissionX.init(this)
.permissions(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
.request { allGranted, grantedList, deniedList ->
if (allGranted) {
//所有权限已经授权
Toast.makeText(context,"授权成功",Toast.LENGTH_LONG).show()
intentTOQRCode()
} else {
Toast.makeText(context, "拒绝权限: $deniedList", Toast.LENGTH_LONG).show()
}
}
}
}

View File

@ -58,9 +58,6 @@ class QsRecordListAdapter(
binding.qsRecordTime.text = qsRecordBean.checkTime
}
override fun getItemViewRes(position: Int): Int {
return R.layout.adapter_qs_record_list
}
// 提供set方法
fun setOnKotlinItemClickListener(itemClickListener: IKotlinItemClickListener) {

View File

@ -0,0 +1,30 @@
package com.navinfo.omqs.ui.fragment.signMoreInfo
import android.view.LayoutInflater
import android.view.ViewGroup
import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.AdapterElectronicEyeBinding
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder
data class ElectronicEyeMoreInfoAdapterItem(
val title: String,
val text: String
)
class ElectronicEyeInfoAdapter : BaseRecyclerViewAdapter<ElectronicEyeMoreInfoAdapterItem>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
val viewBinding =
AdapterElectronicEyeBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return BaseViewHolder(viewBinding)
}
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
val binding: AdapterElectronicEyeBinding =
holder.viewBinding as AdapterElectronicEyeBinding
val item = data[position]
binding.title.text = item.title
binding.text.text = item.text
}
}

View File

@ -0,0 +1,27 @@
package com.navinfo.omqs.ui.fragment.signMoreInfo
import android.view.LayoutInflater
import android.view.ViewGroup
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.RoadNameBean
import com.navinfo.omqs.databinding.AdapterRoadNameBinding
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder
class RoadNameInfoAdapter : BaseRecyclerViewAdapter<RoadNameBean>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
val viewBinding =
AdapterRoadNameBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return BaseViewHolder(viewBinding)
}
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
val binding: AdapterRoadNameBinding =
holder.viewBinding as AdapterRoadNameBinding
val bean = data[position]
binding.title.text = bean.getNameClassStr()
binding.name.text = bean.name
binding.type.text = bean.getTypeStr()
}
}

View File

@ -0,0 +1,100 @@
package com.navinfo.omqs.ui.fragment.signMoreInfo
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.FragmentSignInfoBinding
import com.navinfo.omqs.ui.activity.map.MainViewModel
import com.navinfo.omqs.ui.fragment.BaseFragment
import com.navinfo.omqs.ui.widget.SignUtil
class SignMoreInfoFragment : BaseFragment() {
private var _binding: FragmentSignInfoBinding? = null
private val binding get() = _binding!!
private val viewModel by activityViewModels<MainViewModel>()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
_binding = FragmentSignInfoBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val layoutManager = LinearLayoutManager(context)
//// 设置 RecyclerView 的固定大小,避免在滚动时重新计算视图大小和布局,提高性能
binding.signInfoRecyclerview.setHasFixedSize(true)
binding.signInfoRecyclerview.layoutManager = layoutManager
viewModel.liveDataSignMoreInfo.observe(viewLifecycleOwner) {
binding.signInfoTitle.text = it.name
val drawable = resources.getDrawable(R.drawable.icon_main_moreinfo_text_left, null);
drawable.setBounds(
0,
0,
drawable.minimumWidth,
drawable.minimumHeight
);//必须设置图片大小,否则不显示
binding.signInfoTitle.setCompoundDrawables(
drawable, null, null, null
)
when (it.code) {
//道路名
2011 -> {
val adapter = RoadNameInfoAdapter()
binding.signInfoRecyclerview.adapter = adapter
adapter.refreshData(SignUtil.getRoadNameList(it))
}
//常规点限速
4002->{
val adapter = ElectronicEyeInfoAdapter()
binding.signInfoRecyclerview.adapter = adapter
adapter.refreshData(SignUtil.getSpeedLimitMoreInfoText(it))
}
//条件点限速
4003 -> {
val adapter = ElectronicEyeInfoAdapter()
binding.signInfoRecyclerview.adapter = adapter
adapter.refreshData(SignUtil.getConditionLimitMoreInfoText(it))
}
//电子眼
4010
-> {
val drawable = resources.getDrawable(R.drawable.icon_electronic_eye_left, null);
drawable.setBounds(
0,
0,
drawable.minimumWidth,
drawable.minimumHeight
);//必须设置图片大小,否则不显示
binding.signInfoTitle.setCompoundDrawables(
drawable, null, null, null
)
val adapter = ElectronicEyeInfoAdapter()
binding.signInfoRecyclerview.adapter = adapter
adapter.refreshData(SignUtil.getElectronicEyeMoreInfo(it))
}
}
}
binding.signInfoCancel.setOnClickListener {
activity?.run {
supportFragmentManager.beginTransaction().remove(this@SignMoreInfoFragment)
.commit()
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -58,9 +58,6 @@ class TaskAdapter(
}
}
override fun getItemViewRes(position: Int): Int {
return R.layout.adapter_task
}
fun resetSelect() {
selectPosition = -1

View File

@ -282,10 +282,6 @@ class TaskListAdapter(
}
}
}
override fun getItemViewRes(position: Int): Int {
return R.layout.adapter_task_list
}
}

View File

@ -15,7 +15,8 @@ import dagger.hilt.android.AndroidEntryPoint
* 评测任务viewpager管理页面
*/
@AndroidEntryPoint
class TaskManagerFragment(private var backListener: ((TaskManagerFragment) -> Unit?)? = null) : BaseFragment() {
class TaskManagerFragment(private var backListener: ((TaskManagerFragment) -> Unit?)? = null) :
BaseFragment() {
private var _binding: FragmentTaskManagerBinding? = null
private val binding get() = _binding!!

View File

@ -4,6 +4,7 @@ import android.content.Context
import android.graphics.Color
import android.os.Build
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
@ -95,18 +96,21 @@ class TaskViewModel @Inject constructor(
}
}
}
is NetResult.Error<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(context, "${result.exception.message}", Toast.LENGTH_SHORT)
.show()
}
}
is NetResult.Failure<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(context, "${result.code}:${result.msg}", Toast.LENGTH_SHORT)
.show()
}
}
is NetResult.Loading -> {}
}
val realm = Realm.getDefaultInstance()
@ -139,41 +143,42 @@ class TaskViewModel @Inject constructor(
/**
* 设置当前选择的任务并高亮当前任务的所有link
*/
@RequiresApi(Build.VERSION_CODES.M)
fun setSelectTaskBean(taskBean: TaskBean) {
currentSelectTaskBean = taskBean
liveDataTaskLinks.value = taskBean.hadLinkDvoList
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mapController.lineHandler.omdbTaskLinkLayer.removeAll()
if(taskBean.hadLinkDvoList.isNotEmpty()){
mapController.lineHandler.omdbTaskLinkLayer.addLineList(taskBean.hadLinkDvoList)
var maxX = 0.0
var maxY = 0.0
var minX = 0.0
var minY = 0.0
for (item in taskBean.hadLinkDvoList) {
val geometry = GeometryTools.createGeometry(item.geometry)
if(geometry!=null){
val envelope = geometry.envelopeInternal
if (envelope.maxX > maxX) {
maxX = envelope.maxX
}
if (envelope.maxY > maxY) {
maxY = envelope.maxY
}
if (envelope.minX < minX || minX == 0.0) {
minX = envelope.minX
}
if (envelope.minY < minY || minY == 0.0) {
minY = envelope.minY
}
mapController.lineHandler.omdbTaskLinkLayer.removeAll()
if (taskBean.hadLinkDvoList.isNotEmpty()) {
mapController.lineHandler.omdbTaskLinkLayer.addLineList(taskBean.hadLinkDvoList)
var maxX = 0.0
var maxY = 0.0
var minX = 0.0
var minY = 0.0
for (item in taskBean.hadLinkDvoList) {
val geometry = GeometryTools.createGeometry(item.geometry)
if (geometry != null) {
val envelope = geometry.envelopeInternal
if (envelope.maxX > maxX) {
maxX = envelope.maxX
}
if (envelope.maxY > maxY) {
maxY = envelope.maxY
}
if (envelope.minX < minX || minX == 0.0) {
minX = envelope.minX
}
if (envelope.minY < minY || minY == 0.0) {
minY = envelope.minY
}
}
//增加异常数据判断
if(maxX!=0.0&&maxY!=0.0&&minX!=0.0&&minY!=0.0){
mapController.animationHandler.animateToBox(
maxX = maxX, maxY = maxY, minX = minX, minY = minY
)
}
}
//增加异常数据判断
if (maxX != 0.0 && maxY != 0.0 && minX != 0.0 && minY != 0.0) {
mapController.animationHandler.animateToBox(
maxX = maxX, maxY = maxY, minX = minX, minY = minY
)
}
}
}
@ -181,20 +186,20 @@ class TaskViewModel @Inject constructor(
/**
* 高亮当前选中的link
*/
@RequiresApi(Build.VERSION_CODES.M)
fun showCurrentLink(link: HadLinkDvoBean) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mapController.lineHandler.omdbTaskLinkLayer.showSelectLine(link)
val geometry = GeometryTools.createGeometry(link.geometry)
if(geometry!=null){
val envelope = geometry.envelopeInternal
mapController.animationHandler.animateToBox(
maxX = envelope.maxX,
maxY = envelope.maxY,
minX = envelope.minX,
minY = envelope.minY
)
}
mapController.lineHandler.omdbTaskLinkLayer.showSelectLine(link)
val geometry = GeometryTools.createGeometry(link.geometry)
if (geometry != null) {
val envelope = geometry.envelopeInternal
mapController.animationHandler.animateToBox(
maxX = envelope.maxX,
maxY = envelope.maxY,
minX = envelope.minX,
minY = envelope.minY
)
}
}
override fun onCleared() {

View File

@ -0,0 +1,43 @@
package com.navinfo.omqs.ui.listener
import android.annotation.SuppressLint
import android.util.Log
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import com.google.mlkit.vision.barcode.Barcode
import com.google.mlkit.vision.barcode.BarcodeScannerOptions
import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.common.InputImage
class QRCodeAnalyser(private val listener: (List<Barcode>, Int, Int) -> Unit) :
ImageAnalysis.Analyzer {
//配置当前扫码格式
private val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(
Barcode.FORMAT_QR_CODE,
Barcode.FORMAT_AZTEC
).build()
//获取解析器
private val detector = BarcodeScanning.getClient(options)
@SuppressLint("UnsafeExperimentalUsageError", "UnsafeOptInUsageError")
override fun analyze(imageProxy: ImageProxy) {
val mediaImage = imageProxy.image ?: kotlin.run {
imageProxy.close()
return
}
val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
detector.process(image)
.addOnSuccessListener { barCodes ->
Log.e("ztzt", "barCodes: ${barCodes.size}")
if (barCodes.size > 0) {
listener.invoke(barCodes, imageProxy.width, imageProxy.height)
//接收到结果后,就关闭解析
detector.close()
}
}
.addOnFailureListener { Log.e("ztzt", "Error: ${it.message}") }
.addOnCompleteListener { imageProxy.close() }
}
}

View File

@ -1,11 +1,6 @@
package com.navinfo.omqs.ui.other
import android.view.LayoutInflater
import android.view.View.OnClickListener
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.RecyclerView
import com.navinfo.omqs.R
/**
* RecyclerView 适配器基础类
@ -27,10 +22,10 @@ abstract class BaseRecyclerViewAdapter<T>(var data: List<T> = listOf()) :
// )
// }
abstract fun getItemViewRes(position: Int): Int
override fun getItemViewType(position: Int): Int {
return getItemViewRes(position)
// abstract fun getItemViewRes(position: Int): Int
//
open override fun getItemViewType(position: Int): Int {
return 0
}
override fun getItemCount(): Int {

View File

@ -0,0 +1,54 @@
//package com.navinfo.omqs.ui.other
//
//import androidx.lifecycle.*
//
//val vMStoreMap = HashMap<String, VMStoreClass>()
//
//inline fun <reified VM : ViewModel> LifecycleOwner.shareViewModels(
// scopeName: String,
// factory: ViewModelProvider.Factory? = null
//): Lazy<VM> {
// val store: VMStoreClass
// if (vMStoreMap.keys.contains(scopeName)) {
// store = vMStoreMap[scopeName]!!
// } else {
// store = VMStoreClass()
// vMStoreMap[scopeName] = store
// }
// store.register(this)
// return ViewModelLazy(VM::class,
// { store.viewModelStore },
// { factory ?: ViewModelProvider.NewInstanceFactory() })
//}
//
//class VMStoreClass : ViewModelStoreOwner {
//
// private val bindTargets = ArrayList<LifecycleOwner>()
// private var vmStore: ViewModelStore? = null
//
// 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()) {//如果当前商店没有关联对象,则释放资源
// vMStoreMap.entries.find { it.value == this@VMStoreClass }?.also {
// vmStore?.clear()
// vMStoreMap.remove(it.key)
// }
// }
// }
// }
// })
// }
// }
//
// override fun getViewModelStore(): ViewModelStore {
// if (vmStore == null)
// vmStore = ViewModelStore()
// return vmStore!!
// }
//}

View File

@ -0,0 +1,88 @@
package com.navinfo.omqs.ui.widget
import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat
import com.navinfo.omqs.R
/**
* Author:zhangteng
* description:
* date2021/6/19
*/
class ScanView(context: Context, attrs: AttributeSet) : View(context, attrs) {
private val circlePaint = Paint() //二维码圆圈画笔
private var rectList: ArrayList<RectF>? = null //二维码数组
private var scanLine: Bitmap//横线
private var isShowLine = true//是否显示扫描线
private var animator: ObjectAnimator? = null
private var floatYFraction = 0f
set(value) {
field = value
invalidate()
}
init {
circlePaint.apply {
this.style = Paint.Style.FILL
this.color = ContextCompat.getColor(
context, android.R.color.holo_green_dark
)
}
scanLine = BitmapFactory.decodeResource(resources, R.drawable.scan_light)
getAnimator().start()
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
parseResult(canvas)
if (isShowLine) {
canvas?.drawBitmap(scanLine, (width - scanLine.width) / 2f, height * floatYFraction, circlePaint)
}
}
private fun getAnimator(): ObjectAnimator {
if (animator == null) {
animator = ObjectAnimator.ofFloat(
this,
"floatYFraction",
0f,
1f
)
animator?.duration = 5000
animator?.repeatCount = -1 //-1代表无限循环
}
return animator!!
}
private fun parseResult(canvas: Canvas?) {
rectList?.let { list ->
if (list.isEmpty()) {
return
}
list.forEach {
canvas?.drawCircle(
it.left + (it.right - it.left) / 2f,
it.top + (it.bottom - it.top) / 2f,
50f,
circlePaint
)
}
}
}
fun setRectList(list: ArrayList<RectF>?) {
rectList = list
rectList?.let {
if (it.isNotEmpty()) {
isShowLine = false
getAnimator().cancel()
invalidate()
}
}
}
}

View File

@ -3,7 +3,12 @@ package com.navinfo.omqs.ui.widget
import android.util.Log
import com.navinfo.collect.library.data.entity.RenderEntity
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.RoadNameBean
import com.navinfo.omqs.bean.SignBean
import com.navinfo.omqs.ui.activity.map.LaneInfoItem
import com.navinfo.omqs.ui.fragment.signMoreInfo.ElectronicEyeMoreInfoAdapterItem
import org.json.JSONArray
import java.lang.reflect.Field
class SignUtil {
companion object {
@ -19,14 +24,23 @@ class SignUtil {
2008 -> getKindText(data)
//道路方向
2010 -> getRoadDirectionText(data)
//常规线限速
2019 -> getLineSpeedLimitText(data)
//车道数
2041 -> getLaneNumText(data)
//常规点限速,条件点限速
4002, 4003 -> getSpeedLimitText(data)
4002, 4003 -> getSpeedLimitMaxText(data)
else -> ""
}
}
/**
* 常规线限速值
*/
private fun getLineSpeedLimitText(data: RenderEntity): String {
return "${data.properties["maxSpeed"]}"
}
/**
*获取道路功能等级文字
*/
@ -66,6 +80,8 @@ class SignUtil {
2008 -> "种别"
//道路方向
2010 -> "方向"
//常规线限速
2019 -> "线限速"
//车道数
2041 -> "车道数"
//常规点限速
@ -76,8 +92,12 @@ class SignUtil {
4004 -> "可变点限速"
//普通交限
4006 -> "普通交限"
//电子眼
4010 -> "电子眼"
//交通灯
4022 -> "交通灯"
//交限
4601 -> "车信"
else -> ""
}
}
@ -87,19 +107,11 @@ class SignUtil {
*/
fun getSignBottomRightText(data: RenderEntity): String {
return when (data.code) {
//条件点限速
4003 -> getConditionLimitText(data)
else -> ""
}
}
/**
* 更多信息展示文字
*/
fun getMoreInfoText(data: RenderEntity): String {
return when (data.code) {
//条件点限速
4003 -> getConditionLimitMoreInfoText(data)
//电子眼
4010 -> data.properties["name"].toString()
else -> ""
}
}
@ -107,10 +119,42 @@ class SignUtil {
/**
* 条件点限速更多信息
*/
private fun getConditionLimitMoreInfoText(data: RenderEntity): String {
return data.properties["validPeriod"].toString()
fun getConditionLimitMoreInfoText(renderEntity: RenderEntity): List<ElectronicEyeMoreInfoAdapterItem> {
val list = mutableListOf<ElectronicEyeMoreInfoAdapterItem>()
val maxSpeed = renderEntity.properties["maxSpeed"]
if (maxSpeed != null) {
list.add(
ElectronicEyeMoreInfoAdapterItem(
title = "最高限速值(km/h)", text = maxSpeed
)
)
}
list.add(
ElectronicEyeMoreInfoAdapterItem(
title = "限速条件", text = getConditionLimitText(renderEntity)
)
)
val carType = renderEntity.properties["vehicleType"]
if (carType != "0") {
list.add(
ElectronicEyeMoreInfoAdapterItem(
title = "车辆类型", text = getElectronicEyeVehicleType(carType!!.toInt())
)
)
}
val time = renderEntity.properties["validPeriod"]
if (time?.isNotEmpty() == true) {
list.add(
ElectronicEyeMoreInfoAdapterItem(
title = "时间段", text = time
)
)
}
return list
}
/**
* 条件点限速文字
*/
@ -160,21 +204,31 @@ class SignUtil {
/**
* 获取限速值文字
*/
private fun getSpeedLimitText(data: RenderEntity): String {
private fun getSpeedLimitMaxText(data: RenderEntity): String {
try {
//限速标志 0 限速开始 1 限速解除
val maxSpeed = data.properties["maxSpeed"]
val minSpeed = data.properties["minSpeed"]
return if (maxSpeed != "0")
maxSpeed.toString()
else
minSpeed.toString()
return maxSpeed.toString()
} catch (e: Exception) {
Log.e("jingo", "获取限速面板ICON出错1 $e")
}
return ""
}
/**
* 获取限速值文字
*/
fun getSpeedLimitMinText(data: RenderEntity): String {
try {
//限速标志 0 限速开始 1 限速解除
val minSpeed = data.properties["minSpeed"]
return minSpeed.toString()
} catch (e: Exception) {
Log.e("jingo", "获取限速面板ICON出错1 $e")
}
return "0"
}
/**
* 获取种别名称
*/
@ -182,6 +236,25 @@ class SignUtil {
return data.properties["kind"].toString()
}
/**
* 常规点限速更多信息
*/
fun getSpeedLimitMoreInfoText(renderEntity: RenderEntity): List<ElectronicEyeMoreInfoAdapterItem> {
val list = mutableListOf<ElectronicEyeMoreInfoAdapterItem>()
list.add(
ElectronicEyeMoreInfoAdapterItem(
title = "最高限速值(km/h)", text = getSpeedLimitMaxText(renderEntity)
)
)
list.add(
ElectronicEyeMoreInfoAdapterItem(
title = "最低限速值(km/h)", text = getSpeedLimitMinText(renderEntity)
)
)
return list
}
/**
* 限速图标
*/
@ -232,6 +305,8 @@ class SignUtil {
4003 -> getConditionalSpeedLimitIcon(data)
//可变点限速
4004 -> R.drawable.icon_change_limit
//电子眼
4010 -> R.drawable.icon_electronic_eye
//交通灯
4022 -> R.drawable.icon_traffic_light
else -> 0
@ -315,12 +390,11 @@ class SignUtil {
* 获取道路播报语音文字
*/
fun getRoadSpeechText(topSignList: MutableList<SignBean>): String {
if (topSignList.size == 0)
return ""
if (topSignList.size == 0) return ""
val stringBuffer = StringBuffer()
stringBuffer.append("当前道路")
for (item in topSignList) {
when (item.elementCode) {
when (item.renderEntity.code) {
2002 -> stringBuffer.append("功能等级${item.iconText.substring(2)}级,")
2008 -> stringBuffer.append("种别${item.iconText},")
2010 -> stringBuffer.append("${item.iconText},")
@ -329,5 +403,242 @@ class SignUtil {
}
return stringBuffer.toString()
}
fun getRoadNameList(data: RenderEntity): MutableList<RoadNameBean> {
val list = mutableListOf<RoadNameBean>()
if (data.code == 2011) {
try {
val shapeStr = data.properties["shapeList"]
val array = JSONArray(shapeStr)
for (i in 0 until array.length()) {
val jsonObject = array.getJSONObject(0)
val name = jsonObject.optString("name", "")
val type = jsonObject.optInt("nameType", 0)
val seqNum = jsonObject.optInt("seqNum", 1)
val nameClass = jsonObject.optInt("nameClass", 1)
val bean = RoadNameBean(
name = name, type = type, seqNum = seqNum, nameClass = nameClass
)
list.add(bean)
}
/**
* 排序
*/
list.sortWith { n1, n2 ->
if (n1.nameClass != n2.nameClass) {
n1.nameClass.compareTo(n2.nameClass)
} else {
n1.seqNum.compareTo(n2.seqNum)
}
}
} catch (e: Exception) {
}
}
return list
}
/**
* 是否要有详细信息需要展示
*/
fun isMoreInfo(element: RenderEntity): Boolean {
val isMore = when (element.code) {
//常规点限速
4002 -> getSpeedLimitMinText(element) != "0"
//条件点限速
4003 -> true
//电子眼
4010 -> true
else -> false
}
return isMore
}
/**
* 获取电子眼详细信息
*/
fun getElectronicEyeMoreInfo(renderEntity: RenderEntity): List<ElectronicEyeMoreInfoAdapterItem> {
val list = mutableListOf<ElectronicEyeMoreInfoAdapterItem>()
val kindCode = renderEntity.properties["kind"]!!.toInt()
val kind = ElectronicEyeMoreInfoAdapterItem(
title = "电子眼类型", text = getElectronicEyeKindType(kindCode)
)
list.add(kind)
when (kindCode) {
1, 2, 3, 4, 5, 6, 20, 21 -> {
list.add(
ElectronicEyeMoreInfoAdapterItem(
title = "限速值(km/h)",
text = renderEntity.properties["speedLimit"].toString()
)
)
}
}
val carType = renderEntity.properties["vehicleType"]
if (carType != null && carType != "0") {
list.add(
ElectronicEyeMoreInfoAdapterItem(
title = "车辆类型",
text = getElectronicEyeVehicleType(carType.toInt())
)
)
}
val time = renderEntity.properties["validPeriod"]
if (time?.isNotEmpty() == true) {
list.add(
ElectronicEyeMoreInfoAdapterItem(
title = "时间段", text = time
)
)
}
if (kindCode == 20 || kindCode == 21) {
list.add(
ElectronicEyeMoreInfoAdapterItem(
title = "区间测试配对", text = renderEntity.properties["pairEleceyeId"].toString()
)
)
}
return list
}
/**
* 获取电子眼车辆类型
*/
private fun getElectronicEyeVehicleType(type: Int): String {
var stringBuffer = StringBuffer()
for (i in 31 downTo 0) {
val bit = (type shr i) and 1
if (bit == 1) {
when (i) {
0 -> stringBuffer.append("其他 ")
1 -> stringBuffer.append("小汽车 ")
2 -> stringBuffer.append("公交车 ")
3 -> stringBuffer.append("多人乘坐车辆 ")
4 -> stringBuffer.append("配送车 ")
5 -> stringBuffer.append("摩托车 ")
6 -> stringBuffer.append("行人 ")
7 -> stringBuffer.append("自行车 ")
8 -> stringBuffer.append("出租车 ")
10 -> stringBuffer.append("紧急车辆 ")
11 -> stringBuffer.append("运输卡车 ")
}
}
}
return stringBuffer.toString()
}
/**
* 获取电子眼类型
*/
private fun getElectronicEyeKindType(kind: Int): String {
return when (kind) {
0 -> "未调查"
1 -> "超高速"
2 -> "超低速"
3 -> "移动式测速"
4 -> "可变限速"
5 -> "分车道限速"
6 -> "分车种限速"
7 -> "违规用灯"
8 -> "违规占车道"
9 -> "违规过路口"
10 -> "机动车闯红灯"
11 -> "路况监控"
12 -> "单行线"
13 -> "占用非机动车道"
14 -> "出入口"
15 -> "占用公交车专用道"
16 -> "禁止左右转"
17 -> "禁止掉头"
18 -> "占用应急车道"
19 -> "违反禁止标线"
20 -> "区间测速开始"
21 -> "区间测速结束"
22 -> "违章停车"
23 -> "尾号限行"
24 -> "环保限行"
25 -> "不系安全带"
26 -> "开车打手机"
27 -> "礼让行人"
28 -> "违反禁令标志"
29 -> "禁止鸣笛"
30 -> "车辆未按规定年检"
31 -> "车辆尾气超标"
32 -> "ETC拍照计费电子眼"
33 -> "专用车道电子眼预留"
34 -> "交通标线电子眼预留"
35 -> "违章电子眼预留"
36 -> "卡车超限电子眼"
37 -> "限时长停车电子眼"
else -> "无效类型"
}
}
/**
* 获取车信图标
*/
fun getLineInfoIcons(renderEntity: RenderEntity): List<LaneInfoItem> {
val list = mutableListOf<LaneInfoItem>()
try {
var laneinfoGroup = renderEntity.properties["laneinfoGroup"]
if (laneinfoGroup != null) {
laneinfoGroup = laneinfoGroup.substring(1, laneinfoGroup.length - 1)
laneinfoGroup = "[$laneinfoGroup]"
}
val jsonArray = JSONArray(laneinfoGroup)
if (jsonArray.length() == 2) {
val itemArray = jsonArray[0]
val typeArray = jsonArray[1]
if ((itemArray is JSONArray) && (typeArray is JSONArray) && itemArray.length() == typeArray.length()) {
for (i in 0 until itemArray.length()) {
val itemObject = itemArray[i]
val type = typeArray[i]
var laneInfo = "laneinfo_${itemObject.toString().replace(",", "_")}"
list.add(
LaneInfoItem(
id = getResId(
laneInfo, R.drawable::class.java
), type = type!!.toString().toInt()
)
)
}
}
}
} catch (e: Exception) {
Log.e("jingo", "json 解析失败")
}
return list
}
/**
* 通过字符串名称获取资源id
*/
private fun getResId(variableName: String, c: Class<*>): Int {
return try {
val idField: Field = c.getDeclaredField(variableName)
idField.getInt(idField)
} catch (e: java.lang.Exception) {
e.printStackTrace()
R.drawable.laneinfo_0
}
}
/**
* 道路信息排序用的
*/
fun getRoadInfoIndex(element: RenderEntity): Int {
return when (element.code) {
2041 -> 0
2008 -> 1
2002 -> 2
2019 -> 3
2010 -> 4
else -> 999
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#91909A"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M13,7zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z,M12,2zM17,15.59L15.59,17 12,13.41 8.41,17 7,15.59 10.59,12 7,8.41 8.41,7 12,10.59 15.59,7 17,8.41 13.41,12 17,15.59z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<path
android:pathData="M0,16A16,16 0,1 1,16 32,16.018 16.018,0 0,1 0,16ZM3.049,16A12.951,12.951 0,1 0,16 3.049,12.966 12.966,0 0,0 3.049,16ZM16.243,21.84 L11.806,17.4a2,2 0,0 1,0 -2.819l4.432,-4.432a2,2 0,0 1,2.824 2.826L16.04,15.994l3.022,3.022a2,2 0,0 1,0.166 2.636l-0.166,0.188a2,2 0,0 1,-2.819 0Z"
android:fillColor="#4954ee"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<path
android:pathData="M32,16A16,16 0,1 1,16 0,16.018 16.018,135 0,1 32,16ZM28.951,16A12.951,12.951 0,1 0,16 28.951,12.966 12.966,0 0,0 28.951,16ZM15.757,10.16 L20.194,14.6a2,2 0,0 1,-0 2.819l-4.432,4.432a2,2 0,0 1,-2.824 -2.826L15.96,16.006l-3.022,-3.022a2,2 0,0 1,-0.166 -2.636l0.166,-0.188a2,2 0,0 1,2.819 -0Z"
android:fillColor="#6917c2"/>
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="10dp"
android:height="30dp"
android:viewportWidth="10"
android:viewportHeight="30">
<path
android:pathData="M0.604,0.667h8.792v28.667h-8.792z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M2.604,2.833h4.899v24.395h-4.899z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="10dp"
android:height="28dp"
android:viewportWidth="12"
android:viewportHeight="30">
<path
android:pathData="M7.341,29.432l-0.03,-24.586l4.399,3.566l0.079,-3.273l-5.723,-4.571l-5.856,4.564l0.088,3.485l4.672,-3.972l0.015,24.785z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="30dp"
android:viewportWidth="18"
android:viewportHeight="30">
<path
android:pathData="M13.399,29.168l0.015,-25.164l3.677,3.127l0.069,-2.744l-4.61,-3.594l-4.504,3.599l0.063,2.577l3.463,-2.855l-0.012,25.094z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M11.776,17.839C11.797,17.422 11.543,15.976 10.416,15.185C9.29,14.393 7.37,14.529 7.37,14.529L4.05,14.544L7.178,18.221L4.437,18.291L0.84,13.68L4.441,9.176L7.019,9.238L4.164,12.701L7.17,12.689C7.17,12.689 9.013,12.637 10.061,13.123C11.106,13.608 12.461,14.723 12.606,15.132C12.885,15.948 11.751,18.237 11.776,17.839Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="26dp"
android:height="30dp"
android:viewportWidth="26"
android:viewportHeight="30">
<path
android:pathData="M12.653,16.041C12.51,15.631 11.395,14.759 10.348,14.273C9.302,13.787 7.094,13.84 7.094,13.84L4.084,13.852L6.942,10.387L4.362,10.325L0.761,14.831L4.357,19.444L7.103,19.375L3.974,15.696L7.294,15.68C7.294,15.68 9.158,15.43 10.285,16.222C11.412,17.014 12.669,18.363 12.676,18.749C12.689,19.521 12.94,16.859 12.653,16.041Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M14.058,29.084l-0.026,-24.425l3.847,3.12l0.069,-2.864l-5.002,-3.999l-5.122,3.994l0.078,3.049l4.084,-3.475l0.014,24.6z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.348,16.041C13.492,15.631 14.606,14.759 15.653,14.273C16.699,13.787 18.906,13.84 18.906,13.84L21.915,13.852L19.058,10.387L21.637,10.325L25.239,14.831L21.643,19.444L18.897,19.375L22.026,15.696L18.705,15.68C18.705,15.68 16.843,15.43 15.714,16.222C14.587,17.014 13.33,18.363 13.324,18.749C13.312,19.521 13.061,16.859 13.348,16.041Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="30dp"
android:viewportWidth="18"
android:viewportHeight="30">
<path
android:pathData="M12.059,12.145C11.915,11.735 10.799,10.862 9.752,10.375C8.705,9.889 6.495,9.942 6.495,9.942L3.484,9.953L6.343,6.485L3.762,6.422L0.158,10.932L3.758,15.55L6.506,15.48L3.374,11.797L6.698,11.782C6.698,11.782 8.563,11.532 9.691,12.324C10.819,13.117 12.077,14.467 12.083,14.854C12.095,15.629 12.346,12.965 12.059,12.145Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.74,20.555C13.472,15.211 3.833,15.203 3.932,20.672L3.958,26.174L0.455,23.086L0.389,25.144L5.016,29.037L9.436,25.17L9.442,22.912L5.951,26.08L5.968,21.073C6.051,17.487 11.694,17.618 11.879,20.979L13.74,20.555Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.95,29.096l-0.026,-24.447l3.851,3.124l0.068,-2.867l-5.007,-4.002l-5.126,3.998l0.078,3.051l4.088,-3.478l0.014,24.621z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="30dp"
android:viewportWidth="18"
android:viewportHeight="30">
<path
android:pathData="M14.042,29.168l0.015,-25.164l3.678,3.127l0.068,-2.744l-4.609,-3.594l-4.504,3.598l0.063,2.577l3.463,-2.855l-0.012,25.094z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M12.42,22.839C12.442,22.422 12.187,20.976 11.06,20.185C9.934,19.393 8.014,19.529 8.014,19.529L4.695,19.544L7.823,23.221L5.081,23.291L1.485,18.68L5.085,14.176L7.663,14.238L4.808,17.701L7.815,17.689C7.815,17.689 9.657,17.637 10.705,18.123C11.75,18.608 13.105,19.723 13.25,20.132C13.529,20.947 12.396,23.236 12.42,22.839Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.922,14.333l-10.542,-6.516l4.596,-1.476l-2.296,-1.506l-5.483,2.023l0.684,5.724l2.222,1.305l-0.6,-4.448l10.823,6.681z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="26dp"
android:height="30dp"
android:viewportWidth="26"
android:viewportHeight="30">
<path
android:pathData="M13.37,29.208l-0.012,-25.095l3.463,2.855l0.063,-2.577l-4.504,-3.599l-4.609,3.595l0.068,2.744l3.678,-3.127l0.015,25.164z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M12.249,16.121l10.823,-6.681l-0.6,4.448l2.222,-1.305l0.684,-5.724l-5.483,-2.023l-2.296,1.506l4.596,1.476l-10.542,6.516z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M11.558,16.964C11.579,16.547 11.325,15.101 10.198,14.31C9.072,13.518 7.152,13.654 7.152,13.654L3.832,13.669L6.96,17.346L4.218,17.416L0.622,12.805L4.223,8.301L6.8,8.363L3.946,11.826L6.952,11.814C6.952,11.814 8.794,11.762 9.842,12.248C10.887,12.733 12.243,13.848 12.387,14.257C12.668,15.071 11.533,17.361 11.558,16.964Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="30dp"
android:viewportWidth="18"
android:viewportHeight="30">
<path
android:pathData="M6.439,29.208l-0.014,-25.095l3.465,2.855l0.063,-2.577l-4.504,-3.599l-4.61,3.594l0.069,2.744l3.677,-3.127l0.017,25.164z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M5.398,15.129C5.541,14.72 6.898,13.605 7.943,13.12C8.99,12.634 10.832,12.686 10.832,12.686L13.838,12.698L10.984,9.235L13.562,9.173L17.161,13.677L13.566,18.288L10.823,18.218L13.951,14.541L10.63,14.525C10.63,14.525 8.71,14.389 7.584,15.181C6.457,15.972 6.2,17.418 6.226,17.835C6.245,18.236 5.111,15.946 5.398,15.129Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="30dp"
android:viewportWidth="24"
android:viewportHeight="30">
<path
android:pathData="M12.909,29.208l-0.014,-25.095l3.465,2.855l0.062,-2.577l-4.504,-3.599l-4.61,3.594l0.069,2.744l3.677,-3.127l0.017,25.164z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M11.867,15.131C12.011,14.722 13.367,13.607 14.413,13.122C15.459,12.636 17.301,12.688 17.301,12.688L20.307,12.7L17.453,9.237L20.031,9.175L23.63,13.679L20.036,18.29L17.292,18.22L20.419,14.543L17.1,14.528C17.1,14.528 15.18,14.392 14.054,15.184C12.927,15.975 12.67,17.421 12.696,17.838C12.716,18.237 11.581,15.948 11.867,15.131Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M12.728,16.487C12.462,11.151 3.809,11.142 3.909,16.603L3.934,24.524L0.437,21.441L0.37,23.496L4.991,27.383L9.404,23.523L9.409,21.268L5.924,24.432L5.943,17.005C6.026,13.423 10.929,13.555 11.117,16.911L12.728,16.487Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="26dp"
android:height="30dp"
android:viewportWidth="26"
android:viewportHeight="30">
<path
android:pathData="M14.467,29.168l0.016,-25.164l3.677,3.127l0.069,-2.744l-4.61,-3.594l-4.504,3.599l0.063,2.577l3.463,-2.855l-0.013,25.094z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M14.347,14.333l-10.542,-6.516l4.596,-1.476l-2.296,-1.506l-5.484,2.023l0.685,5.724l2.222,1.305l-0.601,-4.448l10.823,6.681z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.615,14.256C13.759,13.847 15.115,12.732 16.16,12.247C17.208,11.761 19.05,11.813 19.05,11.813L22.057,11.825L19.202,8.362L21.779,8.3L25.379,12.804L21.782,17.416L19.04,17.346L22.168,13.669L18.849,13.654C18.849,13.654 16.929,13.518 15.802,14.31C14.675,15.101 14.419,16.547 14.443,16.964C14.465,17.361 13.331,15.072 13.615,14.256Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="30dp"
android:viewportWidth="18"
android:viewportHeight="30">
<path
android:pathData="M5.796,29.208l-0.012,-25.095l3.463,2.855l0.063,-2.577l-4.504,-3.599l-4.609,3.595l0.068,2.744l3.678,-3.127l0.015,25.164z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M4.754,20.131C4.899,19.722 6.254,18.607 7.299,18.122C8.347,17.636 10.19,17.688 10.19,17.688L13.196,17.7L10.341,14.237L12.919,14.175L16.519,18.679L12.923,23.29L10.181,23.22L13.309,19.543L9.99,19.528C9.99,19.528 8.07,19.392 6.944,20.184C5.817,20.975 5.56,22.421 5.584,22.838C5.604,23.236 4.469,20.946 4.754,20.131Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M4.674,16.121l10.823,-6.681l-0.6,4.448l2.222,-1.305l0.684,-5.724l-5.483,-2.024l-2.296,1.506l4.596,1.476l-10.542,6.516z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="30dp"
android:viewportWidth="18"
android:viewportHeight="30">
<path
android:pathData="M13.663,17.172C13.392,11.782 3.671,11.773 3.772,17.289L3.796,22.839L0.263,19.724L0.198,21.8L4.865,25.726L9.322,21.826L9.328,19.548L5.807,22.744L5.826,17.693C5.909,14.076 11.597,14.209 11.788,17.598L13.663,17.172Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.875,29.218l-0.026,-24.657l3.885,3.15l0.067,-2.892l-5.05,-4.037l-5.17,4.031l0.078,3.078l4.124,-3.508l0.014,24.833z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="30dp"
android:viewportWidth="18"
android:viewportHeight="30">
<path
android:pathData="M14.042,29.168l0.015,-25.164l3.678,3.127l0.068,-2.744l-4.609,-3.594l-4.504,3.599l0.063,2.577l3.463,-2.855l-0.012,25.094z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.921,14.333l-10.542,-6.516l4.596,-1.476l-2.295,-1.506l-5.484,2.023l0.684,5.724l2.222,1.305l-0.6,-4.448l10.823,6.681z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="30dp"
android:viewportWidth="18"
android:viewportHeight="30">
<path
android:pathData="M5.796,29.208l-0.012,-25.095l3.463,2.855l0.063,-2.577l-4.504,-3.599l-4.609,3.595l0.068,2.744l3.678,-3.127l0.015,25.164z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M4.674,16.119l10.823,-6.681l-0.6,4.448l2.222,-1.305l0.684,-5.724l-5.483,-2.024l-2.296,1.506l4.596,1.476l-10.542,6.516z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="17dp"
android:height="30dp"
android:viewportWidth="17"
android:viewportHeight="30">
<path
android:pathData="M5.909,29.208l-0.014,-25.095l3.465,2.855l0.062,-2.577l-4.504,-3.599l-4.61,3.594l0.069,2.744l3.677,-3.127l0.017,25.164z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M5.81,17.908C5.85,16.247 7.134,15.699 8.5,15.699C9.075,15.699 9.806,15.785 10.261,16C10.753,16.232 10.89,16.497 10.934,16.756C11.006,17.178 11.006,19.768 10.934,24.524L7.437,21.441L7.37,23.496L11.991,27.383L16.404,23.523L16.409,21.268L12.924,24.432L12.943,17.005C11.991,12.082 3.929,13.555 4.117,16.911L5.81,17.908Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="14dp"
android:height="30dp"
android:viewportWidth="14"
android:viewportHeight="30">
<path
android:pathData="M11.215,29.041l-0.015,-20.829l2.037,0.136l0.029,20.687z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.148,8.08C13.525,8.766 11.227,10.283 11.222,9.895C11.214,9.508 11.171,7.913 10.04,7.118C8.909,6.323 7.285,6.33 7.285,6.33L3.955,6.346L7.094,10.036L4.34,10.105L0.734,5.479L4.346,0.959L6.933,1.021L4.067,4.496L7.085,4.484C7.085,4.484 8.883,4.561 9.982,4.919C11.559,5.428 12.494,6.524 13.148,8.08Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="26dp"
android:height="30dp"
android:viewportWidth="26"
android:viewportHeight="30">
<path
android:pathData="M11.82,29.099l0.027,-21.84l2.354,-0.14l-0.018,21.987z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.017,7.058C12.87,6.634 11.462,5.48 10.38,4.978C9.298,4.476 7.391,4.53 7.391,4.53L4.282,4.542L7.237,0.958L4.569,0.894L0.842,5.556L4.563,10.329L7.405,10.257L4.169,6.451L7.605,6.434C7.605,6.434 9.283,6.428 10.449,7.247C11.615,8.067 11.91,9.713 11.917,10.112C11.923,10.91 13.312,7.904 13.017,7.058Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M12.985,7.058C13.131,6.634 14.538,5.48 15.62,4.978C16.702,4.476 18.609,4.53 18.609,4.53L21.719,4.542L18.763,0.958L21.431,0.894L25.159,5.556L21.439,10.329L18.596,10.257L21.833,6.451L18.397,6.434C18.397,6.434 16.719,6.428 15.552,7.247C14.386,8.067 14.091,9.713 14.085,10.112C14.077,10.91 12.685,7.904 12.985,7.058Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="26dp"
android:height="30dp"
android:viewportWidth="26"
android:viewportHeight="30">
<path
android:pathData="M11.82,29.099l0.028,-21.84l2.354,-0.14l-0.018,21.987z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.017,7.058C12.87,6.634 11.463,5.48 10.381,4.978C9.299,4.476 7.392,4.53 7.392,4.53L4.283,4.542L7.238,0.958L4.57,0.894L0.842,5.556L4.563,10.329L7.405,10.257L4.168,6.451L7.604,6.434C7.604,6.434 9.282,6.428 10.448,7.247C11.614,8.067 11.908,9.713 11.915,10.112C11.923,10.91 13.313,7.904 13.017,7.058Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M12.984,7.058C13.13,6.634 14.537,5.48 15.619,4.978C16.701,4.476 18.608,4.53 18.608,4.53L21.718,4.542L18.762,0.958L21.43,0.894L25.158,5.556L21.436,10.329L18.595,10.258L21.832,6.452L18.395,6.434C18.395,6.434 16.719,6.428 15.553,7.247C14.387,8.067 14.092,9.713 14.086,10.112C14.076,10.91 12.686,7.904 12.984,7.058Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.875,17.759C13.6,12.236 4.64,12.227 4.744,17.879L4.768,26.079L1.151,22.887L1.082,25.014L5.864,29.037L10.429,25.041L10.435,22.707L6.83,25.982L6.848,18.294C6.933,14.587 11.759,14.724 11.952,18.197L13.875,17.759Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="14dp"
android:height="30dp"
android:viewportWidth="14"
android:viewportHeight="30">
<path
android:pathData="M11.217,29.181l0.029,-20.904l2.058,-0.137l-0.015,21.047z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M10.055,4.814C8.943,4.452 7.126,4.376 7.126,4.376L4.078,4.387L6.974,0.876L4.361,0.813L0.713,5.38L4.357,10.055L7.14,9.985L3.97,6.256L7.334,6.24C7.334,6.24 8.978,6.234 10.119,7.036C11.262,7.839 11.305,9.452 11.308,9.843C11.314,10.234 13.636,8.7 13.255,8.008C12.593,6.434 11.645,5.329 10.055,4.814Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.229,18.072C12.96,12.661 4.183,12.653 4.286,18.19L4.31,26.223L0.765,23.096L0.696,25.18L5.384,29.121L9.858,25.206L9.864,22.918L6.332,26.127L6.349,18.595C6.433,14.963 11.162,15.096 11.349,18.5L13.229,18.072Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="14dp"
android:height="30dp"
android:viewportWidth="14"
android:viewportHeight="30">
<path
android:pathData="M11.429,29.262l0.032,-18.901l2.048,-0.838l-0.034,19.755z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.51,9.521l-9.535,-5.817l4.597,-1.476l-2.297,-1.506l-5.483,2.023l0.684,5.724l2.223,1.305l-0.601,-4.448l10.101,6.226z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M11.425,19.516C11.447,19.099 11.192,17.653 10.065,16.862C8.939,16.07 7.019,16.206 7.019,16.206L3.7,16.221L6.828,19.898L4.086,19.968L0.49,15.357L4.09,10.853L6.668,10.915L3.813,14.378L6.82,14.366C6.82,14.366 8.662,14.314 9.71,14.8C10.755,15.285 12.111,16.4 12.255,16.809C12.536,17.626 11.401,19.915 11.425,19.516Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="30dp"
android:viewportWidth="24"
android:viewportHeight="30">
<path
android:pathData="M11.116,29.278l-0.033,-19.755l2.048,0.838l0.032,18.901z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M11.393,11.553l10.101,-6.226l-0.601,4.448l2.223,-1.305l0.684,-5.724l-5.483,-2.023l-2.297,1.505l4.597,1.476l-9.535,5.817z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M11.135,19.578C11.158,19.161 10.903,17.715 9.776,16.924C8.649,16.132 6.729,16.268 6.729,16.268L3.41,16.283L6.538,19.96L3.796,20.03L0.2,15.419L3.8,10.915L6.378,10.977L3.523,14.44L6.53,14.428C6.53,14.428 8.372,14.376 9.42,14.862C10.465,15.347 11.821,16.462 11.965,16.871C12.248,17.688 11.112,19.976 11.135,19.578Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="14dp"
android:height="30dp"
android:viewportWidth="14"
android:viewportHeight="30">
<path
android:pathData="M0.734,29.033l0.028,-20.686l2.036,-0.136l-0.016,20.829z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M4.019,4.92C5.119,4.562 6.915,4.485 6.915,4.485L9.935,4.497L7.069,1.022L9.656,0.96L13.267,5.48L9.661,10.106L6.907,10.037L10.046,6.347L6.716,6.331C6.716,6.331 5.091,6.324 3.96,7.119C2.829,7.914 2.786,9.509 2.78,9.896C2.775,10.284 0.475,8.767 0.853,8.081C1.505,6.524 2.443,5.428 4.019,4.92Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="30dp"
android:viewportWidth="24"
android:viewportHeight="30">
<path
android:pathData="M10.947,29.277l-0.034,-19.755l2.048,0.838l0.032,18.901z"
android:fillColor="#00C800"/>
<path
android:pathData="M11.226,11.553l10.101,-6.226l-0.601,4.448l2.223,-1.305l0.684,-5.724l-5.484,-2.023l-2.296,1.506l4.597,1.476l-9.535,5.817z"
android:fillColor="#00C800"/>
<path
android:pathData="M12.769,18.262C12.502,12.908 3.819,12.899 3.917,18.379L3.943,26.328L0.432,23.234L0.367,25.297L5.004,29.196L9.432,25.322L9.439,23.058L5.942,26.233L5.96,18.779C6.043,15.185 10.721,15.318 10.908,18.685L12.769,18.262Z"
android:fillColor="#00C800"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="30dp"
android:viewportWidth="24"
android:viewportHeight="30">
<path
android:pathData="M10.836,29.262l0.032,-18.901l2.048,-0.838l-0.034,19.755z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M12.917,9.521l-9.535,-5.817l4.597,-1.476l-2.297,-1.506l-5.483,2.023l0.684,5.724l2.223,1.305l-0.601,-4.448l10.101,6.226z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M12.036,16.871C12.18,16.462 13.536,15.347 14.581,14.862C15.629,14.376 17.471,14.428 17.471,14.428L20.478,14.44L17.623,10.977L20.201,10.915L23.801,15.419L20.205,20.03L17.463,19.96L20.591,16.283L17.272,16.268C17.272,16.268 15.352,16.132 14.225,16.924C13.098,17.715 12.842,19.161 12.866,19.578C12.886,19.977 11.751,17.688 12.036,16.871Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="14dp"
android:height="30dp"
android:viewportWidth="14"
android:viewportHeight="30">
<path
android:pathData="M0.523,29.278l-0.033,-19.755l2.048,0.838l0.032,18.901z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M0.801,11.553l10.1,-6.227l-0.601,4.448l2.223,-1.305l0.684,-5.724l-5.483,-2.023l-2.297,1.506l4.597,1.476l-9.534,5.817z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M1.745,16.809C1.889,16.4 3.245,15.285 4.29,14.8C5.338,14.314 7.18,14.366 7.18,14.366L10.187,14.378L7.332,10.915L9.91,10.853L13.51,15.357L9.914,19.968L7.172,19.898L10.3,16.221L6.981,16.206C6.981,16.206 5.061,16.07 3.935,16.862C2.808,17.653 2.552,19.099 2.575,19.516C2.597,19.915 1.463,17.626 1.745,16.809Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="28dp"
android:viewportWidth="20"
android:viewportHeight="28">
<path
android:pathData="M19.104,5.358C19.1,-1.893 5.711,-1.692 5.629,5.504L5.661,23.316L0.979,19.457L0.896,22.94L6.984,27.804L13.218,22.947L13.122,19.239L8.151,23.199L8.172,6.006C8.315,0.933 16.333,1.474 16.473,5.889L16.428,27.974L19.083,27.987L19.104,5.358Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="14dp"
android:height="30dp"
android:viewportWidth="14"
android:viewportHeight="30">
<path
android:pathData="M11.278,29.261l0.032,-18.901l2.048,-0.838l-0.034,19.755z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.359,9.52l-9.535,-5.817l4.597,-1.476l-2.297,-1.506l-5.483,2.023l0.684,5.724l2.223,1.305l-0.601,-4.448l10.101,6.226z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M13.163,18.345C12.896,12.991 4.213,12.982 4.311,18.462L4.337,26.411L0.826,23.317L0.761,25.38L5.398,29.279L9.826,25.405L9.832,23.141L6.336,26.316L6.354,18.862C6.437,15.268 11.115,15.401 11.302,18.768L13.163,18.345Z"
android:strokeWidth="1"
android:fillColor="#00C800"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="30dp"
android:viewportWidth="24"
android:viewportHeight="30">
<path
android:pathData="M10.947,29.277l-0.034,-19.755l2.048,0.838l0.032,18.901z"
android:fillColor="#00C800"/>
<path
android:pathData="M11.226,11.553l10.101,-6.226l-0.601,4.448l2.223,-1.305l0.684,-5.724l-5.484,-2.023l-2.296,1.506l4.597,1.476l-9.535,5.817z"
android:fillColor="#00C800"/>
<path
android:pathData="M12.769,18.262C12.502,12.908 3.819,12.899 3.917,18.379L3.943,26.328L0.432,23.234L0.367,25.297L5.004,29.196L9.432,25.322L9.439,23.058L5.942,26.233L5.96,18.779C6.043,15.185 10.721,15.318 10.908,18.685L12.769,18.262Z"
android:fillColor="#00C800"/>
</vector>

Some files were not shown because too many files have changed in this diff Show More