1.处理轨迹经纬度飘和圆滑度
2.增加围栏缩放最小值提示 3.增加map和直播显示多宠物设置
This commit is contained in:
@@ -57,6 +57,11 @@ abstract class BaseDialog<T : ViewBinding>
|
||||
initView()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
// ✅ 每次显示都会执行(刷新数据、更新UI等)
|
||||
}
|
||||
|
||||
abstract fun initView()
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,12 +36,14 @@ data class PetBean(
|
||||
var showDFUDialog: Boolean,//是否显示了固件升级弹窗
|
||||
var showNoWifiDialog: Boolean,//是否显示了没有设置wifi弹窗
|
||||
var availableOrder: Int,//判断套餐是否可用或过期,1是可用 0不可用
|
||||
var latitude: Double,
|
||||
var longitude: Double,
|
||||
var deviceId: String
|
||||
) : Parcelable, BaseDiffBean() {
|
||||
constructor() : this(
|
||||
"", "", "", "", 0, 1, MMKVUtil.getString(MMKVKey.UserId), "", 0, Utils.formatTime(
|
||||
System.currentTimeMillis(), Utils.DATE_FORMAT_PATTERN_CN
|
||||
), "", 0f, 0f, "", "", "", 1, 1, "", false, false, 1, ""
|
||||
), "", 0f, 0f, "", "", "", 1, 1, "", false, false, 1, 0.0, 0.0, ""
|
||||
)
|
||||
|
||||
override fun isSameObject(other: Any): Boolean {
|
||||
|
||||
@@ -55,6 +55,7 @@ import androidx.annotation.StringDef
|
||||
ConstantString.Upgrade,
|
||||
ConstantString.Password,
|
||||
ConstantString.PackageUnitDay,
|
||||
ConstantString.Lists,
|
||||
ConstantString.PackageUnitMonth,
|
||||
ConstantString.PackageUnitYear,
|
||||
ConstantString.SetMealIndex
|
||||
@@ -95,6 +96,7 @@ annotation class ConstantString {
|
||||
const val Latitude = "latitude"
|
||||
const val Longitude = "longitude"
|
||||
const val isFirstBind = "isFirstBind"
|
||||
const val Lists = "list"
|
||||
|
||||
const val isCheck = "isCheck"
|
||||
const val Amount = "amount"
|
||||
|
||||
@@ -490,6 +490,10 @@ class FencesAddActivity : BaseActivity<ActivityFencesAddBinding>(ActivityFencesA
|
||||
override fun rectStartDragClick() {
|
||||
}
|
||||
|
||||
override fun rectMinSizeClick() {
|
||||
|
||||
}
|
||||
|
||||
override fun rectEndDragClick() {
|
||||
}
|
||||
|
||||
@@ -504,6 +508,9 @@ class FencesAddActivity : BaseActivity<ActivityFencesAddBinding>(ActivityFencesA
|
||||
|
||||
}
|
||||
|
||||
override fun circleMinSizeClick() {
|
||||
}
|
||||
|
||||
override fun circleEndDragClick() {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.abbidot.tracker.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.widget.CompoundButton
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.list.BaseRecyclerAdapter
|
||||
@@ -20,14 +21,16 @@ import com.abbidot.tracker.util.ViewUtil
|
||||
class SelectMapTypeDialog(
|
||||
context: Context,
|
||||
adapter: BaseRecyclerAdapter<*>,
|
||||
fenceCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null,
|
||||
dashedCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null
|
||||
fenceCheckedListener: CompoundButton.OnCheckedChangeListener? = null,
|
||||
dashedCheckedListener: CompoundButton.OnCheckedChangeListener? = null,
|
||||
showAllPetCheckedListener: CompoundButton.OnCheckedChangeListener? = null
|
||||
) : BaseDialog<DialogSelectMapTypeLayoutBinding>(
|
||||
DialogSelectMapTypeLayoutBinding::inflate, context
|
||||
) {
|
||||
private var mAdapter = adapter
|
||||
private val mFenceCheckedChangeListener = fenceCheckedChangeListener
|
||||
private val mDashedCheckedChangeListener = dashedCheckedChangeListener
|
||||
private val mFenceCheckedListener = fenceCheckedListener
|
||||
private val mDashedCheckedListener = dashedCheckedListener
|
||||
private val mShowAllPetCheckedListener = showAllPetCheckedListener
|
||||
|
||||
override fun initView() {
|
||||
mViewBinding.apply {
|
||||
@@ -35,13 +38,15 @@ class SelectMapTypeDialog(
|
||||
context, rvShowMapTypeList, mAdapter, right = AppUtils.dpToPx(58)
|
||||
)
|
||||
cbDialogMapFencesSwitch.isChecked = Util.getShowFenceSp()
|
||||
cbDialogMapDashedLineSwitch.isChecked =
|
||||
MMKVUtil.getBoolean(MMKVKey.ShowDashedLine, false)
|
||||
cbDialogMapFencesSwitch.setOnCheckedChangeListener(mFenceCheckedChangeListener)
|
||||
cbDialogMapDashedLineSwitch.setOnCheckedChangeListener(mDashedCheckedChangeListener)
|
||||
cbDialogMapDashedLineSwitch.isChecked = MMKVUtil.getBoolean(MMKVKey.ShowDashedLine)
|
||||
cbDialogMapAllPetSwitch.isChecked = MMKVUtil.getBoolean(MMKVKey.ShowAllPet)
|
||||
cbDialogMapFencesSwitch.setOnCheckedChangeListener(mFenceCheckedListener)
|
||||
cbDialogMapDashedLineSwitch.setOnCheckedChangeListener(mDashedCheckedListener)
|
||||
cbDialogMapAllPetSwitch.setOnCheckedChangeListener(mShowAllPetCheckedListener)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检测地图类型有没有改变
|
||||
*/
|
||||
@@ -69,4 +74,12 @@ class SelectMapTypeDialog(
|
||||
fun setDashedSwitch(checked: Boolean) {
|
||||
mViewBinding.cbDialogMapDashedLineSwitch.isChecked = checked
|
||||
}
|
||||
|
||||
fun setShowAllPetSwitch(checked: Boolean) {
|
||||
mViewBinding.cbDialogMapAllPetSwitch.isChecked = checked
|
||||
}
|
||||
|
||||
fun showAllPetSwitch(isShow: Boolean) {
|
||||
mViewBinding.llMapTypeShowAllPetSwitch.visibility = if (isShow) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import android.net.Network
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.NetworkRequest
|
||||
import android.text.TextUtils
|
||||
import android.view.Gravity
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.activity.viewModels
|
||||
@@ -92,7 +93,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
||||
var mSelectPetPosition = 0
|
||||
|
||||
//宠物数据
|
||||
lateinit var mPetList: MutableList<PetBean>
|
||||
val mPetList = mutableListOf<PetBean>()
|
||||
private var isFirst = true
|
||||
|
||||
//是否请求过宠物数据
|
||||
@@ -163,7 +164,6 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
||||
it.itemIconTintList = null
|
||||
it.setOnItemSelectedListener(this)
|
||||
}
|
||||
mPetList = mutableListOf()
|
||||
mChangePetListDialogAdapter = ChangePetListDialogAdapter(mContext, mPetList).apply {
|
||||
setOnChangeClickListener(this@HomeV2Activity)
|
||||
}
|
||||
@@ -175,7 +175,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
||||
val isCrash = MMKVUtil.getBoolean(MMKVKey.isCrash, false)
|
||||
if (isCrash) {
|
||||
MMKVUtil.putBoolean(MMKVKey.isCrash, false)
|
||||
showToast(R.string.txt_show_crash)
|
||||
showToast(R.string.txt_show_crash, gravity = Gravity.CENTER)
|
||||
mCountdownType = ConstantInt.Type0
|
||||
mCountDownTimerViewModel.startCountDown(4)
|
||||
} else {
|
||||
|
||||
@@ -838,6 +838,11 @@ open class AddAndEditFencesZoneBaseActivity :
|
||||
mFencesBean.startDrag = true
|
||||
}
|
||||
|
||||
override fun rectMinSizeClick() {
|
||||
if (isLimitClick()) return
|
||||
showToast(R.string.txt_already_min_size, gravity = Gravity.CENTER)
|
||||
}
|
||||
|
||||
override fun rectEndDragClick() {
|
||||
mFencesBean.startDrag = false
|
||||
mFencesMapCommon.calculateDistanceAndGetPointLatLng(delayMillis = 0)
|
||||
@@ -855,6 +860,11 @@ open class AddAndEditFencesZoneBaseActivity :
|
||||
mFencesMapCommon.calculateDistanceAndGetPointLatLng(delayMillis = 0)
|
||||
}
|
||||
|
||||
override fun circleMinSizeClick() {
|
||||
if (isLimitClick()) return
|
||||
showToast(R.string.txt_already_min_size, gravity = Gravity.CENTER)
|
||||
}
|
||||
|
||||
override fun circleEndDragClick() {
|
||||
mFencesBean.startDrag = false
|
||||
mFencesMapCommon.calculateDistanceAndGetPointLatLng(delayMillis = 0)
|
||||
@@ -868,6 +878,11 @@ open class AddAndEditFencesZoneBaseActivity :
|
||||
mFencesBean.startDrag = true
|
||||
}
|
||||
|
||||
override fun polygonMinSizeClick() {
|
||||
if (isLimitClick()) return
|
||||
showToast(R.string.txt_already_min_size, gravity = Gravity.CENTER)
|
||||
}
|
||||
|
||||
override fun polygonEndDragClick() {
|
||||
mFencesBean.startDrag = false
|
||||
mFencesMapCommon.calculateDistanceAndGetPointLatLng(delayMillis = 0)
|
||||
|
||||
@@ -94,6 +94,9 @@ class LiveActivityV3 : BaseActivity<ActivityLiveV3Binding>(ActivityLiveV3Binding
|
||||
//是否显示虚线
|
||||
private var isShowDashed = true
|
||||
|
||||
//是否显示所有宠物
|
||||
private var isShowAllPet = false
|
||||
|
||||
//地图类型,标准和卫星地图
|
||||
private var mMapType = ConstantInt.Type0
|
||||
private var mShowCenterLocation = ConstantInt.PetLocationType
|
||||
@@ -102,6 +105,7 @@ class LiveActivityV3 : BaseActivity<ActivityLiveV3Binding>(ActivityLiveV3Binding
|
||||
private var isLiveJump = true
|
||||
private var mLiveStatus = 1
|
||||
private var mPetBean: PetBean? = null
|
||||
private var mPetList: MutableList<PetBean>? = null
|
||||
private var mTrackBleDevice: BleTrackDeviceBean? = null
|
||||
|
||||
//直播是否开始
|
||||
@@ -138,10 +142,14 @@ class LiveActivityV3 : BaseActivity<ActivityLiveV3Binding>(ActivityLiveV3Binding
|
||||
isCloseMsg = getBoolean(ConstantString.PetAuthorized)
|
||||
mMapViewModel.mDeviceMsgType = getInt(ConstantString.Type, ConstantInt.SpecialType)
|
||||
mPetBean = Util.getParcelableAdaptive(intent, ConstantString.Pet, PetBean::class.java)
|
||||
mPetList = Util.getParcelableArrayListAdaptive(
|
||||
intent, ConstantString.Lists, PetBean::class.java
|
||||
)
|
||||
}
|
||||
|
||||
isShowFence = Util.getShowFenceSp()
|
||||
isShowDashed = MMKVUtil.getBoolean(MMKVKey.ShowDashedLine, false)
|
||||
isShowDashed = MMKVUtil.getBoolean(MMKVKey.ShowDashedLine)
|
||||
isShowAllPet = MMKVUtil.getBoolean(MMKVKey.ShowAllPet)
|
||||
|
||||
mViewBinding.apply {
|
||||
ViewUtil.instance.viewRotationAnimator(
|
||||
@@ -314,6 +322,10 @@ class LiveActivityV3 : BaseActivity<ActivityLiveV3Binding>(ActivityLiveV3Binding
|
||||
mDeviceStateList,
|
||||
mDeviceStateAdapter
|
||||
)
|
||||
|
||||
if (MMKVUtil.getBoolean(MMKVKey.ShowAllPet)) {
|
||||
setAllPetShow(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,13 +820,43 @@ class LiveActivityV3 : BaseActivity<ActivityLiveV3Binding>(ActivityLiveV3Binding
|
||||
} else {
|
||||
mHomeMapCommon.removeUserAndPetLine()
|
||||
}
|
||||
})
|
||||
},
|
||||
{ _, isChecked ->
|
||||
setAllPetShow(isChecked)
|
||||
}).apply {
|
||||
setOnShowListener {
|
||||
mPetList?.let {
|
||||
if (it.size > 1) mSelectMapTypeDialog?.showAllPetSwitch(true)
|
||||
else mSelectMapTypeDialog?.showAllPetSwitch(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mSelectMapTypeDialog!!.mapTypeSpToUpdate()
|
||||
}
|
||||
mSelectMapTypeDialog?.show()
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置多宠物显示
|
||||
*/
|
||||
private fun setAllPetShow(isShow: Boolean) {
|
||||
isShowAllPet = isShow
|
||||
MMKVUtil.putBoolean(MMKVKey.ShowAllPet, isShow)
|
||||
if (isShow) {
|
||||
lifecycleScope.launch {
|
||||
mPetList?.apply {
|
||||
mPetBean?.let { p ->
|
||||
//删除当前选中宠物
|
||||
mHomeMapCommon.showOtherPetHeadMarker(filter { it != p }.toMutableList())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mHomeMapCommon.clearOtherPetHeadMarker()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置地图相关数据
|
||||
*/
|
||||
@@ -928,7 +970,7 @@ class LiveActivityV3 : BaseActivity<ActivityLiveV3Binding>(ActivityLiveV3Binding
|
||||
it.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0)
|
||||
}
|
||||
mViewBinding.llLiveV2MapTopPet.homeDataPetHeadSmall.appHeadImage.let {
|
||||
ViewUtil.instance.setPetTypeHead(mContext,it, imgurl, petType)
|
||||
ViewUtil.instance.setPetTypeHead(mContext, it, imgurl, petType)
|
||||
ViewUtil.instance.viewAlphaAndRotationObjectAnimator(it)
|
||||
}
|
||||
//重新设置地图宠物头像
|
||||
|
||||
@@ -6,9 +6,11 @@ import androidx.fragment.app.Fragment
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.util.AppUtils
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.base.BaseMapCommon
|
||||
import com.abbidot.tracker.bean.HistoryDataBean
|
||||
import com.abbidot.tracker.bean.MapDeviceBean
|
||||
import com.abbidot.tracker.bean.PetBean
|
||||
import com.abbidot.tracker.constant.ConstantInt
|
||||
import com.abbidot.tracker.databinding.LayoutPetLocationInfoBinding
|
||||
import com.abbidot.tracker.ui.fragment.map.baidumap.HomeMapBaiduMapFragment
|
||||
@@ -206,6 +208,18 @@ class HomeMapCommonV3 @Inject constructor() : BaseMapCommon() {
|
||||
mHomeMapGoogleMapFragment?.removeUserAndPetLine()
|
||||
}
|
||||
|
||||
suspend fun showOtherPetHeadMarker(
|
||||
petList: MutableList<PetBean>, headBgResId: Int = R.drawable.pic_map_gps_avatar
|
||||
) {
|
||||
if (petList.size > 0) {
|
||||
mHomeMapGoogleMapFragment?.showOtherPetHeadMarker(petList, headBgResId)
|
||||
}
|
||||
}
|
||||
|
||||
fun clearOtherPetHeadMarker() {
|
||||
mHomeMapGoogleMapFragment?.clearOtherPetHeadMarker()
|
||||
}
|
||||
|
||||
// fun getAddressShowMarkerInfoWindow(historyDataBean: HistoryDataBean) {
|
||||
// if (null != mHomeMapBaiduMapFragment) {
|
||||
// mHomeMapBaiduMapFragment!!.showMarkerInfoWindow(historyDataBean)
|
||||
|
||||
@@ -17,6 +17,7 @@ import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.commit
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.abbidot.baselibrary.constant.ConState
|
||||
import com.abbidot.baselibrary.constant.EventName
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
@@ -61,6 +62,7 @@ import com.google.android.gms.maps.model.LatLng
|
||||
import com.hjq.permissions.XXPermissions
|
||||
import com.hjq.permissions.permission.PermissionLists
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
@@ -91,8 +93,6 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
|
||||
private lateinit var mDeviceStateList: MutableList<DataBean>
|
||||
private lateinit var mDeviceStateAdapter: HomeMapDeviceStateAdapter
|
||||
// private lateinit var mDeviceMsgList: MutableList<DataBean>
|
||||
// private lateinit var mDeviceMsgAdapter: HomeMapDeviceMsgAdapter
|
||||
|
||||
//启动移动地图摄像机
|
||||
private var isMoveCamera = true
|
||||
@@ -102,7 +102,10 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
private var isShowFence = true
|
||||
|
||||
//是否显示虚线
|
||||
private var isShowDashed = true
|
||||
private var isShowDashed = false
|
||||
|
||||
//是否显示所有宠物
|
||||
private var isShowAllPet = false
|
||||
|
||||
//地图类型,标准和卫星地图
|
||||
private var mMapType = ConstantInt.Type0
|
||||
@@ -112,6 +115,8 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
|
||||
//是否需要gps坐标转火星坐标
|
||||
private var needGpsToGCJ02 = true
|
||||
|
||||
//一键定位绿波动画
|
||||
private var mAnimatorSet: AnimatorSet? = null
|
||||
|
||||
//一键定位开始的时间戳
|
||||
@@ -131,7 +136,8 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
}
|
||||
|
||||
isShowFence = Util.getShowFenceSp()
|
||||
isShowDashed = MMKVUtil.getBoolean(MMKVKey.ShowDashedLine, false)
|
||||
isShowDashed = MMKVUtil.getBoolean(MMKVKey.ShowDashedLine)
|
||||
isShowAllPet = MMKVUtil.getBoolean(MMKVKey.ShowAllPet)
|
||||
|
||||
mViewBinding.apply {
|
||||
getHomeV2Activity()?.edgeToEdgeAdapterBars(
|
||||
@@ -220,7 +226,8 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
}
|
||||
|
||||
val showFence = Util.getShowFenceSp()
|
||||
val showDashed = MMKVUtil.getBoolean(MMKVKey.ShowDashedLine, false)
|
||||
val showDashed = MMKVUtil.getBoolean(MMKVKey.ShowDashedLine)
|
||||
val showAllPet = MMKVUtil.getBoolean(MMKVKey.ShowAllPet)
|
||||
//检测直播页面有没有修改围栏显示
|
||||
if (isShowFence != showFence) {
|
||||
if (null == mSelectMapTypeDialog) {
|
||||
@@ -236,6 +243,13 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
mSelectMapTypeDialog?.setDashedSwitch(showDashed)
|
||||
}
|
||||
}
|
||||
if (isShowAllPet != showAllPet) {
|
||||
if (null == mSelectMapTypeDialog) {
|
||||
setAllPetShow(showAllPet)
|
||||
} else {
|
||||
mSelectMapTypeDialog?.setShowAllPetSwitch(showDashed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getHomeV2Activity(): HomeV2Activity? {
|
||||
@@ -600,20 +614,29 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
* 显示地图类型选择弹窗
|
||||
*/
|
||||
private fun showMapTypeDialog() {
|
||||
if (null == mSelectMapTypeDialog) mSelectMapTypeDialog = ViewUtil.instance.getMapTypeDialog(
|
||||
mContext!!, object : BaseRecyclerAdapter.OnItemClickListener {
|
||||
override fun onItemClick(itemView: View?, pos: Int) {
|
||||
mMapType = Util.getMapTypeSp()
|
||||
if (pos == mMapType) {
|
||||
return
|
||||
if (null == mSelectMapTypeDialog) {
|
||||
mSelectMapTypeDialog = ViewUtil.instance.getMapTypeDialog(
|
||||
mContext!!, object : BaseRecyclerAdapter.OnItemClickListener {
|
||||
override fun onItemClick(itemView: View?, pos: Int) {
|
||||
mMapType = Util.getMapTypeSp()
|
||||
if (pos == mMapType) {
|
||||
return
|
||||
}
|
||||
mHomeMapCommon.switchSatelliteAndNormalMapType()
|
||||
}
|
||||
}, this, this, this
|
||||
).apply {
|
||||
setOnShowListener {
|
||||
getHomeV2Activity()?.apply {
|
||||
if (mPetList.size > 1) mSelectMapTypeDialog?.showAllPetSwitch(true)
|
||||
else mSelectMapTypeDialog?.showAllPetSwitch(false)
|
||||
}
|
||||
mHomeMapCommon.switchSatelliteAndNormalMapType()
|
||||
}
|
||||
}, this, this
|
||||
)
|
||||
else {
|
||||
}
|
||||
} else {
|
||||
mSelectMapTypeDialog!!.mapTypeSpToUpdate()
|
||||
}
|
||||
|
||||
mSelectMapTypeDialog?.show()
|
||||
}
|
||||
|
||||
@@ -645,6 +668,27 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置多宠物显示
|
||||
*/
|
||||
private fun setAllPetShow(isShow: Boolean) {
|
||||
isShowAllPet = isShow
|
||||
MMKVUtil.putBoolean(MMKVKey.ShowAllPet, isShow)
|
||||
if (isShow) {
|
||||
lifecycleScope.launch {
|
||||
getHomeV2Activity()?.apply {
|
||||
getPet(false)?.let { p ->
|
||||
//删除当前选中宠物
|
||||
mHomeMapCommon.showOtherPetHeadMarker(mPetList.filter { it != p }
|
||||
.toMutableList())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mHomeMapCommon.clearOtherPetHeadMarker()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置需要更新的标识
|
||||
*/
|
||||
@@ -755,6 +799,9 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
if (isShowDashed) {
|
||||
mHomeMapCommon.addUserAndPetLine()
|
||||
}
|
||||
if (isShowAllPet) {
|
||||
setAllPetShow(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -951,6 +998,9 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
getPet()?.apply {
|
||||
val intent = Intent(mContext, LiveActivityV3::class.java)
|
||||
intent.putExtra(ConstantString.JumpActivity, isLiveJump)
|
||||
intent.putParcelableArrayListExtra(
|
||||
ConstantString.Lists, mPetList.toCollection(ArrayList())
|
||||
)
|
||||
intent.putExtra(ConstantString.Pet, this)
|
||||
mMapDeviceBean?.let {
|
||||
intent.putExtra(ConstantString.DeviceAuthorized, it.isCloseBattery)
|
||||
@@ -1056,6 +1106,7 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
when (v.id) {
|
||||
R.id.cb_dialog_map_fences_switch -> setFencesShow(isChecked)
|
||||
R.id.cb_dialog_map_dashed_line_switch -> setDashedShow(isChecked)
|
||||
R.id.cb_dialog_map_all_pet_switch -> setAllPetShow(isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.abbidot.tracker.databinding.FragmentBaseBaiduMapBinding
|
||||
import com.abbidot.tracker.ui.fragment.map.googlemap.GoogleBitmapHelper
|
||||
import com.abbidot.tracker.util.ImageUtil
|
||||
import com.abbidot.tracker.util.LonAndLatUtil
|
||||
import com.abbidot.tracker.util.Util.Companion.safeRecycle
|
||||
import com.abbidot.tracker.widget.TypefaceTextView
|
||||
import com.baidu.location.BDAbstractLocationListener
|
||||
import com.baidu.location.BDLocation
|
||||
@@ -218,7 +219,7 @@ abstract class BaseBaiduMapFragment :
|
||||
*/
|
||||
fun setPetHeadIconUrl(petHeadUrl: String) {
|
||||
mPetHeadUrl = petHeadUrl
|
||||
mPetHeadIconBitmap?.recycle()
|
||||
mPetHeadIconBitmap.safeRecycle()
|
||||
mPetHeadIconBitmap = null
|
||||
}
|
||||
|
||||
@@ -247,20 +248,21 @@ abstract class BaseBaiduMapFragment :
|
||||
headBgResId: Int = R.drawable.pic_map_gps_avatar
|
||||
) {
|
||||
|
||||
val mapKey = if (TextUtils.isEmpty(mPetHeadUrl)) "pet_default_head"
|
||||
else mPetHeadUrl.substring(mPetHeadUrl.lastIndexOf("/") + 1, mPetHeadUrl.length)
|
||||
var bitmapDescriptor = MyApplication.mapPetHeadHashMap[mapKey]
|
||||
if (null == bitmapDescriptor || bitmapDescriptor !is BitmapDescriptor) {
|
||||
if (null == mPetHeadIconBitmap) {
|
||||
//设置头像
|
||||
mPetHeadIconBitmap =
|
||||
GoogleBitmapHelper.headToBitmap(mContext!!, headBgResId, mPetHeadUrl, mPetType)
|
||||
}
|
||||
bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(mPetHeadIconBitmap!!)
|
||||
//保存在内存中,提高显示速度
|
||||
MyApplication.mapPetHeadHashMap[mapKey] = bitmapDescriptor
|
||||
}
|
||||
|
||||
// val mapKey = if (TextUtils.isEmpty(mPetHeadUrl)) "pet_default_head"
|
||||
// else mPetHeadUrl.substring(mPetHeadUrl.lastIndexOf("/") + 1, mPetHeadUrl.length)
|
||||
// var bitmapDescriptor = MyApplication.mapPetHeadHashMap[mapKey]
|
||||
// if (null == bitmapDescriptor || bitmapDescriptor !is BitmapDescriptor) {
|
||||
// if (null == mPetHeadIconBitmap) {
|
||||
// //设置头像
|
||||
// mPetHeadIconBitmap =
|
||||
// GoogleBitmapHelper.headToBitmap(mContext!!, headBgResId, mPetHeadUrl, mPetType)
|
||||
// }
|
||||
// bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(mPetHeadIconBitmap!!)
|
||||
// //保存在内存中,提高显示速度
|
||||
// MyApplication.mapPetHeadHashMap[mapKey] = bitmapDescriptor
|
||||
// }
|
||||
val bitmapDescriptor =
|
||||
getMarkerBitmapDescriptor(mContext!!, mPetHeadUrl, mPetType, headBgResId)
|
||||
mMarker?.remove()
|
||||
val latLng = getBaiduMapLatLng(lat, lon, needConvertGCJ02)
|
||||
mPetLatLng = latLng
|
||||
@@ -272,6 +274,42 @@ abstract class BaseBaiduMapFragment :
|
||||
mMarker = mBaiduMap!!.addOverlay(option)
|
||||
}
|
||||
|
||||
private suspend fun getMarkerBitmapDescriptor(
|
||||
context: Context,
|
||||
headUrl: String,
|
||||
petType: Int,
|
||||
headBgResId: Int = R.drawable.pic_map_gps_avatar
|
||||
): BitmapDescriptor? {
|
||||
var bitmap: Bitmap? = null
|
||||
var bitmapDescriptor: Any?
|
||||
try {
|
||||
val mapKey = if (TextUtils.isEmpty(headUrl)) {
|
||||
"pet_default_head"
|
||||
} else {
|
||||
val idx = headUrl.lastIndexOf("/")
|
||||
if (idx != -1) {
|
||||
headUrl.substring(idx + 1)
|
||||
} else {
|
||||
headUrl
|
||||
}
|
||||
}
|
||||
LogUtil.e("mapKey=$mapKey")
|
||||
bitmapDescriptor = MyApplication.mapPetHeadHashMap[mapKey]
|
||||
if (null == bitmapDescriptor || bitmapDescriptor !is BitmapDescriptor) {
|
||||
bitmap = GoogleBitmapHelper.headToBitmap(context, headBgResId, headUrl, petType)
|
||||
bitmap?.let {
|
||||
bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(it)
|
||||
//保存在内存中,提高显示速度
|
||||
MyApplication.mapPetHeadHashMap[mapKey] = bitmapDescriptor as BitmapDescriptor
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
bitmap.safeRecycle()
|
||||
}
|
||||
// 把 return 写在 finally 外面
|
||||
return bitmapDescriptor as? BitmapDescriptor
|
||||
}
|
||||
|
||||
/**
|
||||
* 地图添加图片
|
||||
*/
|
||||
@@ -853,7 +891,8 @@ abstract class BaseBaiduMapFragment :
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mSensorManager?.unregisterListener(mSensorEventListener)
|
||||
mPetHeadIconBitmap?.recycle()
|
||||
mPetHeadIconBitmap.safeRecycle()
|
||||
mPetHeadIconBitmap = null
|
||||
stopLocation()
|
||||
//在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
|
||||
mMapView.onDestroy()
|
||||
|
||||
@@ -8,7 +8,6 @@ import android.graphics.Bitmap
|
||||
import android.graphics.Point
|
||||
import android.location.Location
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -19,7 +18,6 @@ import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.util.AppUtils
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.abbidot.tracker.MyApplication
|
||||
import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.base.BaseFragment
|
||||
import com.abbidot.tracker.bean.FencesBean
|
||||
@@ -30,6 +28,7 @@ import com.abbidot.tracker.databinding.FragmentGoogleMapBinding
|
||||
import com.abbidot.tracker.util.ImageUtil
|
||||
import com.abbidot.tracker.util.LonAndLatUtil
|
||||
import com.abbidot.tracker.util.Util
|
||||
import com.abbidot.tracker.util.Util.Companion.safeRecycle
|
||||
import com.abbidot.tracker.util.ViewUtil
|
||||
import com.abbidot.tracker.widget.MapDeviceNetView
|
||||
import com.abbidot.tracker.widget.MapMarkerInfoView
|
||||
@@ -42,7 +41,6 @@ import com.google.android.gms.maps.GoogleMap
|
||||
import com.google.android.gms.maps.GoogleMapOptions
|
||||
import com.google.android.gms.maps.MapView
|
||||
import com.google.android.gms.maps.OnMapReadyCallback
|
||||
import com.google.android.gms.maps.model.BitmapDescriptor
|
||||
import com.google.android.gms.maps.model.BitmapDescriptorFactory
|
||||
import com.google.android.gms.maps.model.CameraPosition
|
||||
import com.google.android.gms.maps.model.Circle
|
||||
@@ -65,6 +63,12 @@ import com.google.android.gms.tasks.CancellationTokenSource
|
||||
import com.google.android.gms.tasks.Task
|
||||
import com.qmuiteam.qmui.util.QMUIDisplayHelper
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sqrt
|
||||
|
||||
|
||||
/**
|
||||
@@ -97,7 +101,7 @@ abstract class BaseGoogleMapFragment :
|
||||
var mMarker: Marker? = null
|
||||
|
||||
//自定显示用户地点信息图层
|
||||
var mUserMarker: Marker? = null
|
||||
private var mUserMarker: Marker? = null
|
||||
|
||||
//宠物大头针设置自定义头像
|
||||
private var mPetHeadIconBitmap: Bitmap? = null
|
||||
@@ -318,9 +322,13 @@ abstract class BaseGoogleMapFragment :
|
||||
}
|
||||
|
||||
ConstantInt.UserLocationType -> {
|
||||
mPetLatLng?.let {
|
||||
if (null == mPetLatLng) {
|
||||
mUserLatLng?.apply {
|
||||
setLatLngZoom(mContext!!, 250, it, this)
|
||||
moveCameraLocation(this)
|
||||
}
|
||||
} else {
|
||||
mUserLatLng?.apply {
|
||||
setLatLngZoom(mContext!!, 250, mPetLatLng!!, this)
|
||||
cameraUpdateMove()
|
||||
}
|
||||
}
|
||||
@@ -368,7 +376,7 @@ abstract class BaseGoogleMapFragment :
|
||||
fun setPetHeadIconUrl(petHeadUrl: String, petType: Int) {
|
||||
mPetHeadUrl = petHeadUrl
|
||||
mPetType = petType
|
||||
mPetHeadIconBitmap?.recycle()
|
||||
mPetHeadIconBitmap.safeRecycle()
|
||||
mPetHeadIconBitmap = null
|
||||
}
|
||||
|
||||
@@ -390,21 +398,26 @@ abstract class BaseGoogleMapFragment :
|
||||
private suspend fun setPetHeadMarker(
|
||||
latLng: LatLng, headBgResId: Int = R.drawable.pic_map_gps_avatar
|
||||
) {
|
||||
val mapKey = if (TextUtils.isEmpty(mPetHeadUrl)) "pet_default_head"
|
||||
else mPetHeadUrl.substring(mPetHeadUrl.lastIndexOf("/") + 1, mPetHeadUrl.length)
|
||||
var bitmapDescriptor = MyApplication.mapPetHeadHashMap[mapKey]
|
||||
if (null == bitmapDescriptor || bitmapDescriptor !is BitmapDescriptor) {
|
||||
if (null == mPetHeadIconBitmap) {
|
||||
//设置头像
|
||||
mPetHeadIconBitmap =
|
||||
GoogleBitmapHelper.headToBitmap(mContext!!, headBgResId, mPetHeadUrl, mPetType)
|
||||
}
|
||||
bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(mPetHeadIconBitmap!!)
|
||||
//保存在内存中,提高显示速度
|
||||
MyApplication.mapPetHeadHashMap[mapKey] = bitmapDescriptor
|
||||
}
|
||||
// val mapKey = if (TextUtils.isEmpty(mPetHeadUrl)) "pet_default_head"
|
||||
// else mPetHeadUrl.substring(mPetHeadUrl.lastIndexOf("/") + 1, mPetHeadUrl.length)
|
||||
// var bitmapDescriptor = MyApplication.mapPetHeadHashMap[mapKey]
|
||||
// if (null == bitmapDescriptor || bitmapDescriptor !is BitmapDescriptor) {
|
||||
// if (null == mPetHeadIconBitmap) {
|
||||
// //设置头像
|
||||
// mPetHeadIconBitmap =
|
||||
// GoogleBitmapHelper.headToBitmap(mContext!!, headBgResId, mPetHeadUrl, mPetType)
|
||||
// }
|
||||
// bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(mPetHeadIconBitmap!!)
|
||||
// //保存在内存中,提高显示速度
|
||||
// MyApplication.mapPetHeadHashMap[mapKey] = bitmapDescriptor
|
||||
// }
|
||||
|
||||
val bitmapDescriptor = GoogleBitmapHelper.getMarkerBitmapDescriptor(
|
||||
mContext!!, mPetHeadUrl, mPetType, headBgResId
|
||||
)
|
||||
val newLatLng = toGCJ02LatLon(latLng)
|
||||
val markerOptions = MarkerOptions().position(newLatLng)
|
||||
//显示最上面,层级最高,默认值 0f
|
||||
val markerOptions = MarkerOptions().position(newLatLng).zIndex(99f)
|
||||
markerOptions.icon(bitmapDescriptor)
|
||||
mMarker?.remove()
|
||||
mGoogleMap?.apply {
|
||||
@@ -805,7 +818,7 @@ abstract class BaseGoogleMapFragment :
|
||||
*/
|
||||
fun getPolylineOptions(widthDp: Float, lineColorRes: Int): PolylineOptions {
|
||||
return PolylineOptions().clickable(false).width(AppUtils.dpToPx(widthDp))
|
||||
.color(ContextCompat.getColor(mContext!!, lineColorRes)).geodesic(false)
|
||||
.color(ContextCompat.getColor(mContext!!, lineColorRes))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -824,8 +837,21 @@ abstract class BaseGoogleMapFragment :
|
||||
} else {
|
||||
latLngList
|
||||
}
|
||||
|
||||
/*慢速步行:epsilon=0.5,插值 2 个
|
||||
日常骑行:epsilon=1.0,插值 2 个
|
||||
机动车行驶:epsilon=1.5~2.0,插值 3 个
|
||||
**/
|
||||
// 1. 降噪
|
||||
val filterPoints = filterNoisePoint(newLatLngList)
|
||||
// 2. RDP平滑抽稀
|
||||
val smoothPoints = rdpSmooth(filterPoints, epsilon = 1.0)
|
||||
// 3. 插值加密线条
|
||||
val finalPoints = latLngInterpolate(smoothPoints, step = 2)
|
||||
|
||||
//先黄黑线
|
||||
getPolylineOptions(8f, R.color.line_stroke_color).let {
|
||||
it.geodesic(true)
|
||||
it.addAll(newLatLngList)
|
||||
googleMap.addPolyline(it).apply {
|
||||
startCap = RoundCap()
|
||||
@@ -841,7 +867,8 @@ abstract class BaseGoogleMapFragment :
|
||||
|
||||
//再画黄线
|
||||
getPolylineOptions(5f, R.color.rote_line_color).let {
|
||||
it.addAll(newLatLngList)
|
||||
it.geodesic(true)
|
||||
it.addAll(finalPoints)
|
||||
googleMap.addPolyline(it).apply {
|
||||
startCap = RoundCap()
|
||||
endCap = RoundCap()
|
||||
@@ -1267,8 +1294,118 @@ abstract class BaseGoogleMapFragment :
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mPetHeadIconBitmap?.recycle()
|
||||
mPetHeadIconBitmap.safeRecycle()
|
||||
mPetHeadIconBitmap = null
|
||||
mGoogleMapView?.onDestroy()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 两点间距离 单位米
|
||||
*/
|
||||
private fun distanceBetween(p1: LatLng, p2: LatLng): Double {
|
||||
val r = 6371000.0
|
||||
val lat1 = p1.latitude * PI / 180
|
||||
val lng1 = p1.longitude * PI / 180
|
||||
val lat2 = p2.latitude * PI / 180
|
||||
val lng2 = p2.longitude * PI / 180
|
||||
|
||||
val dLat = lat2 - lat1
|
||||
val dLng = lng2 - lng1
|
||||
val a = sin(dLat / 2).pow(2) + cos(lat1) * cos(lat2) * sin(dLng / 2).pow(2)
|
||||
val c = 2 * atan2(sqrt(a), sqrt(1 - a))
|
||||
return r * c
|
||||
}
|
||||
|
||||
/**
|
||||
* Ramer-Douglas-Peucker 轨迹抽稀平滑
|
||||
* @param epsilon 阈值 建议0.5~2.0
|
||||
*/
|
||||
private fun rdpSmooth(points: List<LatLng>, epsilon: Double = 1.0): List<LatLng> {
|
||||
if (points.size < 3) return points
|
||||
var maxDist = 0.0
|
||||
var index = 0
|
||||
val start = points.first()
|
||||
val end = points.last()
|
||||
|
||||
for (i in 1 until points.lastIndex) {
|
||||
val dist = pointToLineDist(points[i], start, end)
|
||||
if (dist > maxDist) {
|
||||
maxDist = dist
|
||||
index = i
|
||||
}
|
||||
}
|
||||
|
||||
return if (maxDist > epsilon) {
|
||||
val left = rdpSmooth(points.subList(0, index + 1), epsilon)
|
||||
val right = rdpSmooth(points.subList(index, points.size), epsilon)
|
||||
left.dropLast(1) + right
|
||||
} else {
|
||||
listOf(start, end)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点到线段距离
|
||||
*/
|
||||
private fun pointToLineDist(p: LatLng, a: LatLng, b: LatLng): Double {
|
||||
val ax = a.longitude
|
||||
val ay = a.latitude
|
||||
val bx = b.longitude
|
||||
val by = b.latitude
|
||||
val px = p.longitude
|
||||
val py = p.latitude
|
||||
|
||||
val cross = (px - ax) * (bx - ax) + (py - ay) * (by - ay)
|
||||
if (cross <= 0.0) return distanceBetween(p, a)
|
||||
|
||||
val len2 = (bx - ax).pow(2) + (by - ay).pow(2)
|
||||
if (cross >= len2) return distanceBetween(p, b)
|
||||
|
||||
val t = cross / len2
|
||||
val nearX = ax + t * (bx - ax)
|
||||
val nearY = ay + t * (by - ay)
|
||||
return distanceBetween(p, LatLng(nearY, nearX))
|
||||
}
|
||||
|
||||
/**
|
||||
* 相邻两点插值补点,让线条更顺滑
|
||||
* @param step 插值个数 推荐2~3
|
||||
*/
|
||||
private fun latLngInterpolate(points: List<LatLng>, step: Int = 2): List<LatLng> {
|
||||
if (points.size < 2) return points
|
||||
val result = mutableListOf<LatLng>()
|
||||
for (i in 0 until points.size - 1) {
|
||||
val p0 = points[i]
|
||||
val p1 = points[i + 1]
|
||||
result.add(p0)
|
||||
for (s in 1..step) {
|
||||
val ratio = s.toDouble() / (step + 1)
|
||||
val lat = p0.latitude + (p1.latitude - p0.latitude) * ratio
|
||||
val lng = p0.longitude + (p1.longitude - p0.longitude) * ratio
|
||||
result.add(LatLng(lat, lng))
|
||||
}
|
||||
}
|
||||
result.add(points.last())
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* GPS降噪,过滤跳点漂移
|
||||
*/
|
||||
private fun filterNoisePoint(
|
||||
points: List<LatLng>, minDis: Double = 5.0, maxDis: Double = 60.0
|
||||
): List<LatLng> {
|
||||
if (points.isEmpty()) return emptyList()
|
||||
val res = mutableListOf<LatLng>().apply { add(points.first()) }
|
||||
for (i in 1 until points.size) {
|
||||
val last = res.last()
|
||||
val dis = distanceBetween(last, points[i])
|
||||
if (dis in minDis..maxDis) {
|
||||
res.add(points[i])
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,12 @@ import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.tracker.MyApplication
|
||||
import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.constant.ConstantInt
|
||||
import com.abbidot.tracker.util.ImageUtil
|
||||
import com.abbidot.tracker.util.Util.Companion.safeRecycle
|
||||
import com.google.android.gms.maps.model.BitmapDescriptor
|
||||
import com.google.android.gms.maps.model.BitmapDescriptorFactory
|
||||
import com.qmuiteam.qmui.util.QMUIDisplayHelper
|
||||
@@ -166,4 +169,40 @@ object GoogleBitmapHelper {
|
||||
vectorDrawable.draw(canvas)
|
||||
return BitmapDescriptorFactory.fromBitmap(bitmap)
|
||||
}
|
||||
|
||||
suspend fun getMarkerBitmapDescriptor(
|
||||
context: Context,
|
||||
headUrl: String,
|
||||
petType: Int,
|
||||
headBgResId: Int = R.drawable.pic_map_gps_avatar
|
||||
): BitmapDescriptor? {
|
||||
var bitmap: Bitmap? = null
|
||||
var bitmapDescriptor: Any?
|
||||
try {
|
||||
val mapKey = if (TextUtils.isEmpty(headUrl)) {
|
||||
"pet_default_head"
|
||||
} else {
|
||||
val idx = headUrl.lastIndexOf("/")
|
||||
if (idx != -1) {
|
||||
headUrl.substring(idx + 1)
|
||||
} else {
|
||||
headUrl
|
||||
}
|
||||
}
|
||||
LogUtil.e("mapKey=$mapKey")
|
||||
bitmapDescriptor = MyApplication.mapPetHeadHashMap[mapKey]
|
||||
if (null == bitmapDescriptor || bitmapDescriptor !is BitmapDescriptor) {
|
||||
bitmap = headToBitmap(context, headBgResId, headUrl, petType)
|
||||
bitmap?.let {
|
||||
bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(it)
|
||||
//保存在内存中,提高显示速度
|
||||
MyApplication.mapPetHeadHashMap[mapKey] = bitmapDescriptor as BitmapDescriptor
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
bitmap.safeRecycle()
|
||||
}
|
||||
// 把 return 写在 finally 外面
|
||||
return bitmapDescriptor as? BitmapDescriptor
|
||||
}
|
||||
}
|
||||
@@ -302,11 +302,10 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
if (null != mPetIconDescriptor) {
|
||||
mGoogleMap?.apply {
|
||||
val newLatLng = toGCJ02LatLon(latLng)
|
||||
mMarkerOptions.position(newLatLng).icon(mPetIconDescriptor)
|
||||
//显示最上面,层级最高,默认值 0f
|
||||
mMarkerOptions.position(newLatLng).icon(mPetIconDescriptor).zIndex(99f)
|
||||
mMarker?.remove()
|
||||
mMarker = addMarker(mMarkerOptions)
|
||||
//显示最上面,层级最高
|
||||
mMarker?.zIndex = 1f
|
||||
setUserMarker()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,14 @@ import android.view.animation.LinearInterpolator
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.util.AppUtils
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.abbidot.baselibrary.util.Utils
|
||||
import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.bean.HistoryDataBean
|
||||
import com.abbidot.tracker.bean.MapDeviceBean
|
||||
import com.abbidot.tracker.bean.PetBean
|
||||
import com.abbidot.tracker.constant.ConstantInt
|
||||
import com.abbidot.tracker.databinding.LayoutPetLocationInfoBinding
|
||||
import com.abbidot.tracker.util.Util
|
||||
@@ -24,6 +27,7 @@ import com.google.android.gms.maps.model.Circle
|
||||
import com.google.android.gms.maps.model.CircleOptions
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
import com.google.android.gms.maps.model.Marker
|
||||
import com.google.android.gms.maps.model.MarkerOptions
|
||||
import com.google.android.gms.maps.model.Polyline
|
||||
import kotlin.math.pow
|
||||
|
||||
@@ -59,6 +63,8 @@ class HomeMapGoogleMapFragmentV3 : BaseGoogleMapFragment() {
|
||||
|
||||
//是否需要反编译地理位置
|
||||
private var isReverseGeocode = false
|
||||
//其他没有选择的宠物
|
||||
private val mOtherPetMarkerList = mutableListOf<Marker?>()
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@@ -358,6 +364,39 @@ class HomeMapGoogleMapFragmentV3 : BaseGoogleMapFragment() {
|
||||
mRippleCircle = null
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示其他宠物的头像Marker
|
||||
*/
|
||||
suspend fun showOtherPetHeadMarker(
|
||||
petList: MutableList<PetBean>, headBgResId: Int = R.drawable.pic_map_gps_avatar
|
||||
) {
|
||||
clearOtherPetHeadMarker()
|
||||
if (MMKVUtil.getBoolean(MMKVKey.ShowAllPet)) {
|
||||
for (pet in petList) {
|
||||
val bitmapDescriptor = GoogleBitmapHelper.getMarkerBitmapDescriptor(
|
||||
mContext!!, pet.imgurl, pet.petType, headBgResId
|
||||
)
|
||||
val newLatLng = toGCJ02LatLon(LatLng(pet.latitude, pet.longitude))
|
||||
val markerOptions = MarkerOptions().position(newLatLng)
|
||||
markerOptions.icon(bitmapDescriptor)
|
||||
mGoogleMap?.apply {
|
||||
mOtherPetMarkerList.add(addMarker(markerOptions)?.apply {
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空其他宠物的头像Marker
|
||||
*/
|
||||
fun clearOtherPetHeadMarker() {
|
||||
for (m in mOtherPetMarkerList) {
|
||||
m?.remove()
|
||||
}
|
||||
mOtherPetMarkerList.clear()
|
||||
}
|
||||
|
||||
override fun onDetach() {
|
||||
super.onDetach()
|
||||
clearRippleCircleAnim()
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.location.LocationManager
|
||||
import android.os.Build
|
||||
import android.os.Parcelable
|
||||
@@ -900,6 +901,12 @@ class Util {
|
||||
return this.code in 0x4E00..0x9FA5
|
||||
}
|
||||
|
||||
/**
|
||||
* 扩展函数:Bitmap单独安全回收
|
||||
*/
|
||||
fun Bitmap?.safeRecycle() {
|
||||
this?.takeIf { !it.isRecycled }?.recycle()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -921,8 +921,9 @@ class ViewUtil private constructor() {
|
||||
fun getMapTypeDialog(
|
||||
context: Context,
|
||||
onItemClickListener: BaseRecyclerAdapter.OnItemClickListener? = null,
|
||||
fenceCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null,
|
||||
dashedCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null
|
||||
fenceCheckedListener: CompoundButton.OnCheckedChangeListener? = null,
|
||||
dashedCheckedListener: CompoundButton.OnCheckedChangeListener? = null,
|
||||
showAllPetCheckedListener: CompoundButton.OnCheckedChangeListener? = null
|
||||
): SelectMapTypeDialog {
|
||||
val mapType = Util.getMapTypeSp()
|
||||
val typeList = mutableListOf<DataBean>()
|
||||
@@ -947,7 +948,7 @@ class ViewUtil private constructor() {
|
||||
})
|
||||
}
|
||||
return SelectMapTypeDialog(
|
||||
context, mapTypeAdapter, fenceCheckedChangeListener, dashedCheckedChangeListener
|
||||
context, mapTypeAdapter, fenceCheckedListener, dashedCheckedListener,showAllPetCheckedListener
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ interface OnCircleViewScaleClickListener {
|
||||
fun circleScaleEndClick()
|
||||
fun circleStartDragClick()
|
||||
fun circleScalingClick()
|
||||
fun circleMinSizeClick()
|
||||
fun circleEndDragClick()
|
||||
}
|
||||
|
||||
@@ -17,11 +18,13 @@ interface OnRectViewRotateScaleClickListener {
|
||||
fun rectScaleEndClick()
|
||||
fun rectScalingClick()
|
||||
fun rectStartDragClick()
|
||||
fun rectMinSizeClick()
|
||||
fun rectEndDragClick()
|
||||
}
|
||||
|
||||
interface OnPolygonViewPointPullClickListener {
|
||||
fun polygonPointPullClick()
|
||||
fun polygonStartDragClick()
|
||||
fun polygonMinSizeClick()
|
||||
fun polygonEndDragClick()
|
||||
}
|
||||
@@ -380,6 +380,7 @@ class FencesCircleView : View {
|
||||
if (mLimitRadius == 0f && circleRadius < mLocationBitmap!!.height / 2f) {
|
||||
return true
|
||||
} else if (circleRadius < mLimitRadius) {
|
||||
mScaleClickListener?.circleMinSizeClick()
|
||||
return true
|
||||
}
|
||||
mMaxCircleRadius = circleRadius
|
||||
|
||||
@@ -339,6 +339,7 @@ class FencesPolygonView : View {
|
||||
}
|
||||
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||
mPointPullClickListener?.polygonMinSizeClick()
|
||||
return false
|
||||
}
|
||||
mOutHideRectWidth = tempRect.width()
|
||||
@@ -401,6 +402,7 @@ class FencesPolygonView : View {
|
||||
}
|
||||
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||
mPointPullClickListener?.polygonMinSizeClick()
|
||||
return false
|
||||
}
|
||||
mOutHideRectWidth = tempRect.width()
|
||||
@@ -462,6 +464,7 @@ class FencesPolygonView : View {
|
||||
}
|
||||
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||
mPointPullClickListener?.polygonMinSizeClick()
|
||||
return false
|
||||
}
|
||||
mOutHideRectWidth = tempRect.width()
|
||||
@@ -523,6 +526,7 @@ class FencesPolygonView : View {
|
||||
}
|
||||
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||
mPointPullClickListener?.polygonMinSizeClick()
|
||||
return false
|
||||
}
|
||||
mOutHideRectWidth = tempRect.width()
|
||||
@@ -584,6 +588,7 @@ class FencesPolygonView : View {
|
||||
}
|
||||
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||
mPointPullClickListener?.polygonMinSizeClick()
|
||||
return false
|
||||
}
|
||||
mOutHideRectWidth = tempRect.width()
|
||||
@@ -645,6 +650,7 @@ class FencesPolygonView : View {
|
||||
}
|
||||
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||
mPointPullClickListener?.polygonMinSizeClick()
|
||||
return false
|
||||
}
|
||||
mOutHideRectWidth = tempRect.width()
|
||||
|
||||
@@ -500,6 +500,7 @@ class FencesRectView : View {
|
||||
return true
|
||||
}
|
||||
} else if (newRectWidth < mLimitSide || newRectHeight < mLimitSide) {
|
||||
mRotateScaleClickListener?.rectMinSizeClick()
|
||||
return true
|
||||
}
|
||||
mRotateScaleClickListener?.rectScalingClick()
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.abbidot.tracker.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
|
||||
/**
|
||||
*Created by .yzq on 2026/5/25/周一.
|
||||
* @link
|
||||
* @description:
|
||||
*/
|
||||
class TrackLineView @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
) : View(context, attrs, defStyleAttr) {
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -66,6 +66,33 @@
|
||||
android:id="@+id/cb_dialog_map_dashed_line_switch"
|
||||
style="@style/my_checkbox_switch_style"
|
||||
android:layout_width="@dimen/dp_47"
|
||||
android:checked="true" />
|
||||
android:checked="false" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/ll_map_type_show_all_pet_switch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/ll_map_type_show_dashed_line_switch"
|
||||
android:layout_marginTop="@dimen/dp_8"
|
||||
android:background="@drawable/shape8_gray_border_transparent_bg"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="@dimen/dp_47"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="@dimen/dp_16">
|
||||
|
||||
<com.abbidot.tracker.widget.TypefaceTextView
|
||||
style="@style/my_TextView_style_v2"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start"
|
||||
android:text="@string/txt_show_all_pet"
|
||||
android:textSize="@dimen/textSize14"
|
||||
app:typeface="@string/roboto_bold_font" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatCheckBox
|
||||
android:id="@+id/cb_dialog_map_all_pet_switch"
|
||||
style="@style/my_checkbox_switch_style"
|
||||
android:layout_width="@dimen/dp_47"
|
||||
android:checked="false" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
</RelativeLayout>
|
||||
@@ -1012,5 +1012,7 @@
|
||||
<string name="txt_package_permission3">1. VIP-Prioritätssupport\n2. Schneller Austauschservice (1x inbegriffen)\n3. Erweiterter Schutz\n4. Sorgenfreier Haustierschutz</string>
|
||||
<string name="txt_add_wifi_tips">Fügen Sie eine Wi-Fi-Zone hinzu, um die Betriebszeit zu verlängern.</string>
|
||||
<string name="txt_add">Hinzufügen</string>
|
||||
<string name="txt_show_all_pet">Alle Haustiere anzeigen</string>
|
||||
<string name="txt_already_min_size">Bereits auf Minimalgröße</string>
|
||||
|
||||
</resources>
|
||||
@@ -1056,5 +1056,7 @@
|
||||
<string name="txt_package_permission3">1. VIP 优先支持\n2. 快速更换服务(含1次)\n3. 增强型保障\n4. 无忧宠物保护</string>
|
||||
<string name="txt_add_wifi_tips">添加wifi区域可延长使用时长</string>
|
||||
<string name="txt_add">去添加</string>
|
||||
<string name="txt_show_all_pet">显示所有宠物</string>
|
||||
<string name="txt_already_min_size">已是最小尺寸</string>
|
||||
|
||||
</resources>
|
||||
@@ -1114,5 +1114,7 @@
|
||||
<string name="txt_package_permission3">1.VIP priority support\n2.Fast replacement service (1 included)\n3.Enhanced protection\n4.Hassle-free pet protection</string>
|
||||
<string name="txt_add_wifi_tips">Add Wi-Fi zone to prolong care time</string>
|
||||
<string name="txt_add">Add</string>
|
||||
<string name="txt_show_all_pet">Display All Pets</string>
|
||||
<string name="txt_already_min_size">Already at minimum size</string>
|
||||
|
||||
</resources>
|
||||
@@ -38,6 +38,7 @@ import androidx.annotation.StringDef
|
||||
MMKVKey.MapType,
|
||||
MMKVKey.ShowFence,
|
||||
MMKVKey.ShowDashedLine,
|
||||
MMKVKey.ShowAllPet,
|
||||
MMKVKey.isCrash,
|
||||
MMKVKey.AvailableOrder,
|
||||
MMKVKey.isFirstCheckBleOpen,
|
||||
@@ -94,6 +95,7 @@ annotation class MMKVKey {
|
||||
//map页是否显示围栏
|
||||
const val ShowFence = "isShowFence"
|
||||
const val ShowDashedLine = "isShowDashedLine"
|
||||
const val ShowAllPet = "isShowAllPet"
|
||||
|
||||
//是首次打开APP
|
||||
const val FirstOpen = "firstOpen"
|
||||
|
||||
Reference in New Issue
Block a user