diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseDialog.kt b/app/src/main/java/com/abbidot/tracker/base/BaseDialog.kt index 0394f07..8526aa7 100644 --- a/app/src/main/java/com/abbidot/tracker/base/BaseDialog.kt +++ b/app/src/main/java/com/abbidot/tracker/base/BaseDialog.kt @@ -57,6 +57,11 @@ abstract class BaseDialog initView() } + override fun onStart() { + super.onStart() + // ✅ 每次显示都会执行(刷新数据、更新UI等) + } + abstract fun initView() /** diff --git a/app/src/main/java/com/abbidot/tracker/bean/PetBean.kt b/app/src/main/java/com/abbidot/tracker/bean/PetBean.kt index c93f942..0123e89 100644 --- a/app/src/main/java/com/abbidot/tracker/bean/PetBean.kt +++ b/app/src/main/java/com/abbidot/tracker/bean/PetBean.kt @@ -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 { diff --git a/app/src/main/java/com/abbidot/tracker/constant/ConstantString.kt b/app/src/main/java/com/abbidot/tracker/constant/ConstantString.kt index eb81a93..73fbf3e 100644 --- a/app/src/main/java/com/abbidot/tracker/constant/ConstantString.kt +++ b/app/src/main/java/com/abbidot/tracker/constant/ConstantString.kt @@ -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" diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/FencesAddActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/FencesAddActivity.kt index a4f5feb..155481c 100644 --- a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/FencesAddActivity.kt +++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/FencesAddActivity.kt @@ -490,6 +490,10 @@ class FencesAddActivity : BaseActivity(ActivityFencesA override fun rectStartDragClick() { } + override fun rectMinSizeClick() { + + } + override fun rectEndDragClick() { } @@ -504,6 +508,9 @@ class FencesAddActivity : BaseActivity(ActivityFencesA } + override fun circleMinSizeClick() { + } + override fun circleEndDragClick() { } diff --git a/app/src/main/java/com/abbidot/tracker/dialog/SelectMapTypeDialog.kt b/app/src/main/java/com/abbidot/tracker/dialog/SelectMapTypeDialog.kt index f3e56f7..6333599 100644 --- a/app/src/main/java/com/abbidot/tracker/dialog/SelectMapTypeDialog.kt +++ b/app/src/main/java/com/abbidot/tracker/dialog/SelectMapTypeDialog.kt @@ -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::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 + } } \ No newline at end of file diff --git a/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt b/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt index 729b876..e5e2c90 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt @@ -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 var mSelectPetPosition = 0 //宠物数据 - lateinit var mPetList: MutableList + val mPetList = mutableListOf() private var isFirst = true //是否请求过宠物数据 @@ -163,7 +164,6 @@ class HomeV2Activity : BaseActivity(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 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 { diff --git a/app/src/main/java/com/abbidot/tracker/ui/activity/device/fences/AddAndEditFencesZoneBaseActivity.kt b/app/src/main/java/com/abbidot/tracker/ui/activity/device/fences/AddAndEditFencesZoneBaseActivity.kt index 1e8587f..2c82939 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/activity/device/fences/AddAndEditFencesZoneBaseActivity.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/activity/device/fences/AddAndEditFencesZoneBaseActivity.kt @@ -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) diff --git a/app/src/main/java/com/abbidot/tracker/ui/activity/map/LiveActivityV3.kt b/app/src/main/java/com/abbidot/tracker/ui/activity/map/LiveActivityV3.kt index f87921f..64f4f9c 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/activity/map/LiveActivityV3.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/activity/map/LiveActivityV3.kt @@ -94,6 +94,9 @@ class LiveActivityV3 : BaseActivity(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 private var isLiveJump = true private var mLiveStatus = 1 private var mPetBean: PetBean? = null + private var mPetList: MutableList? = null private var mTrackBleDevice: BleTrackDeviceBean? = null //直播是否开始 @@ -138,10 +142,14 @@ class LiveActivityV3 : BaseActivity(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 mDeviceStateList, mDeviceStateAdapter ) + + if (MMKVUtil.getBoolean(MMKVKey.ShowAllPet)) { + setAllPetShow(true) + } } } @@ -808,13 +820,43 @@ class LiveActivityV3 : BaseActivity(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 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) } //重新设置地图宠物头像 diff --git a/app/src/main/java/com/abbidot/tracker/ui/common/map/HomeMapCommonV3.kt b/app/src/main/java/com/abbidot/tracker/ui/common/map/HomeMapCommonV3.kt index fcf1c14..1e57a3f 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/common/map/HomeMapCommonV3.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/common/map/HomeMapCommonV3.kt @@ -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, 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) diff --git a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/MapV3Fragment.kt b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/MapV3Fragment.kt index 8c506fa..6d6547e 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/MapV3Fragment.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/MapV3Fragment.kt @@ -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::i private lateinit var mDeviceStateList: MutableList private lateinit var mDeviceStateAdapter: HomeMapDeviceStateAdapter -// private lateinit var mDeviceMsgList: MutableList -// private lateinit var mDeviceMsgAdapter: HomeMapDeviceMsgAdapter //启动移动地图摄像机 private var isMoveCamera = true @@ -102,7 +102,10 @@ class MapV3Fragment : BaseFragment(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::i //是否需要gps坐标转火星坐标 private var needGpsToGCJ02 = true + + //一键定位绿波动画 private var mAnimatorSet: AnimatorSet? = null //一键定位开始的时间戳 @@ -131,7 +136,8 @@ class MapV3Fragment : BaseFragment(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::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::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::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::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::i if (isShowDashed) { mHomeMapCommon.addUserAndPetLine() } + if (isShowAllPet) { + setAllPetShow(true) + } } } @@ -951,6 +998,9 @@ class MapV3Fragment : BaseFragment(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::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) } } diff --git a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/baidumap/BaseBaiduMapFragment.kt b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/baidumap/BaseBaiduMapFragment.kt index f351830..f4d1dfb 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/baidumap/BaseBaiduMapFragment.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/baidumap/BaseBaiduMapFragment.kt @@ -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() diff --git a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/BaseGoogleMapFragment.kt b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/BaseGoogleMapFragment.kt index f58f309..86c94e7 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/BaseGoogleMapFragment.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/BaseGoogleMapFragment.kt @@ -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, epsilon: Double = 1.0): List { + 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, step: Int = 2): List { + if (points.size < 2) return points + val result = mutableListOf() + 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, minDis: Double = 5.0, maxDis: Double = 60.0 + ): List { + if (points.isEmpty()) return emptyList() + val res = mutableListOf().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 + } } diff --git a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/GoogleBitmapHelper.kt b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/GoogleBitmapHelper.kt index a71ce57..20ccd14 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/GoogleBitmapHelper.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/GoogleBitmapHelper.kt @@ -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 + } } \ No newline at end of file diff --git a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HistoryDataGoogleMapFragment.kt b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HistoryDataGoogleMapFragment.kt index 03b24e7..0ebd040 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HistoryDataGoogleMapFragment.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HistoryDataGoogleMapFragment.kt @@ -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() } } diff --git a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HomeMapGoogleMapFragmentV3.kt b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HomeMapGoogleMapFragmentV3.kt index 838b6c1..955ecb5 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HomeMapGoogleMapFragmentV3.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HomeMapGoogleMapFragmentV3.kt @@ -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() companion object { @JvmStatic @@ -358,6 +364,39 @@ class HomeMapGoogleMapFragmentV3 : BaseGoogleMapFragment() { mRippleCircle = null } + /** + * 显示其他宠物的头像Marker + */ + suspend fun showOtherPetHeadMarker( + petList: MutableList, 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() diff --git a/app/src/main/java/com/abbidot/tracker/util/Util.kt b/app/src/main/java/com/abbidot/tracker/util/Util.kt index f70f58c..02a7c7a 100644 --- a/app/src/main/java/com/abbidot/tracker/util/Util.kt +++ b/app/src/main/java/com/abbidot/tracker/util/Util.kt @@ -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() + } } diff --git a/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt b/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt index ebe1d7e..95f4e46 100644 --- a/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt +++ b/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt @@ -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() @@ -947,7 +948,7 @@ class ViewUtil private constructor() { }) } return SelectMapTypeDialog( - context, mapTypeAdapter, fenceCheckedChangeListener, dashedCheckedChangeListener + context, mapTypeAdapter, fenceCheckedListener, dashedCheckedListener,showAllPetCheckedListener ) } diff --git a/app/src/main/java/com/abbidot/tracker/widget/CustomViewInterfaces.kt b/app/src/main/java/com/abbidot/tracker/widget/CustomViewInterfaces.kt index b59c1f8..e733da1 100644 --- a/app/src/main/java/com/abbidot/tracker/widget/CustomViewInterfaces.kt +++ b/app/src/main/java/com/abbidot/tracker/widget/CustomViewInterfaces.kt @@ -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() } \ No newline at end of file diff --git a/app/src/main/java/com/abbidot/tracker/widget/FencesCircleView.kt b/app/src/main/java/com/abbidot/tracker/widget/FencesCircleView.kt index 9ddc0b7..fa2521a 100644 --- a/app/src/main/java/com/abbidot/tracker/widget/FencesCircleView.kt +++ b/app/src/main/java/com/abbidot/tracker/widget/FencesCircleView.kt @@ -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 diff --git a/app/src/main/java/com/abbidot/tracker/widget/FencesPolygonView.kt b/app/src/main/java/com/abbidot/tracker/widget/FencesPolygonView.kt index 0737f85..b25caf7 100644 --- a/app/src/main/java/com/abbidot/tracker/widget/FencesPolygonView.kt +++ b/app/src/main/java/com/abbidot/tracker/widget/FencesPolygonView.kt @@ -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() diff --git a/app/src/main/java/com/abbidot/tracker/widget/FencesRectView.kt b/app/src/main/java/com/abbidot/tracker/widget/FencesRectView.kt index 0577723..152a689 100644 --- a/app/src/main/java/com/abbidot/tracker/widget/FencesRectView.kt +++ b/app/src/main/java/com/abbidot/tracker/widget/FencesRectView.kt @@ -500,6 +500,7 @@ class FencesRectView : View { return true } } else if (newRectWidth < mLimitSide || newRectHeight < mLimitSide) { + mRotateScaleClickListener?.rectMinSizeClick() return true } mRotateScaleClickListener?.rectScalingClick() diff --git a/app/src/main/java/com/abbidot/tracker/widget/TrackLineView.kt b/app/src/main/java/com/abbidot/tracker/widget/TrackLineView.kt new file mode 100644 index 0000000..0d847bb --- /dev/null +++ b/app/src/main/java/com/abbidot/tracker/widget/TrackLineView.kt @@ -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) + + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_select_map_type_layout.xml b/app/src/main/res/layout/dialog_select_map_type_layout.xml index 6eea180..47ae6a5 100644 --- a/app/src/main/res/layout/dialog_select_map_type_layout.xml +++ b/app/src/main/res/layout/dialog_select_map_type_layout.xml @@ -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" /> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 157d518..814627d 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -1012,5 +1012,7 @@ 1. VIP-Prioritätssupport\n2. Schneller Austauschservice (1x inbegriffen)\n3. Erweiterter Schutz\n4. Sorgenfreier Haustierschutz Fügen Sie eine Wi-Fi-Zone hinzu, um die Betriebszeit zu verlängern. Hinzufügen + Alle Haustiere anzeigen + Bereits auf Minimalgröße \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 5c2eaa1..926501e 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1056,5 +1056,7 @@ 1. VIP 优先支持\n2. 快速更换服务(含1次)\n3. 增强型保障\n4. 无忧宠物保护 添加wifi区域可延长使用时长 去添加 + 显示所有宠物 + 已是最小尺寸 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c7170e8..e599b52 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1114,5 +1114,7 @@ 1.VIP priority support\n2.Fast replacement service (1 included)\n3.Enhanced protection\n4.Hassle-free pet protection Add Wi-Fi zone to prolong care time Add + Display All Pets + Already at minimum size \ No newline at end of file diff --git a/baselibrary/src/main/java/com/abbidot/baselibrary/constant/MMKVKey.kt b/baselibrary/src/main/java/com/abbidot/baselibrary/constant/MMKVKey.kt index d62049a..0b16b16 100644 --- a/baselibrary/src/main/java/com/abbidot/baselibrary/constant/MMKVKey.kt +++ b/baselibrary/src/main/java/com/abbidot/baselibrary/constant/MMKVKey.kt @@ -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"