map和直播页面改版

This commit is contained in:
yezhiqiu
2025-11-27 18:22:51 +08:00
parent 11b6ba16bd
commit 314508e924
27 changed files with 2057 additions and 214 deletions

View File

@@ -30,7 +30,7 @@ android {
targetSdkVersion 35 targetSdkVersion 35
versionCode 2101 versionCode 2101
// versionName "2.1.1" // versionName "2.1.1"
versionName "2.1.1-Beta2" versionName "2.1.1-Beta4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View File

@@ -391,6 +391,10 @@
android:name=".ui.activity.map.LiveActivityV2" android:name=".ui.activity.map.LiveActivityV2"
android:exported="false" android:exported="false"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name=".ui.activity.map.LiveActivityV3"
android:exported="false"
android:screenOrientation="portrait" />
<activity <activity
android:name=".ui.activity.data.MoreSleepActivity" android:name=".ui.activity.data.MoreSleepActivity"
android:exported="false" android:exported="false"

View File

@@ -34,7 +34,10 @@ data class MapDeviceBean(
var fences: MutableList<FencesBean>?, var fences: MutableList<FencesBean>?,
var wifiZones: MutableList<WiFiZoneBean>?, var wifiZones: MutableList<WiFiZoneBean>?,
var startTime: String, var startTime: String,
var endTime: String var endTime: String,
var canShowBattery: Boolean,
var isCloseBattery: Boolean,
var isCloseMsg: Boolean
) : Parcelable { ) : Parcelable {
constructor() : this( constructor() : this(
"", "",
@@ -65,6 +68,9 @@ data class MapDeviceBean(
null, null,
null, null,
"", "",
"" "",
false,
false,
false
) )
} }

View File

@@ -102,6 +102,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
private val mBleReportManage: BleReportManage by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { private val mBleReportManage: BleReportManage by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
mSocketUtilManage = SocketUtilManage() mSocketUtilManage = SocketUtilManage()
mSocketUtilManage?.initEasySocket(mContext) mSocketUtilManage?.initEasySocket(mContext)
LogUtil.e("创建Socket连接")
BleReportManage(mSocketSendMessageViewModel, mSocketUtilManage!!) BleReportManage(mSocketSendMessageViewModel, mSocketUtilManage!!)
} }
@@ -222,11 +223,16 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
XEventBus.observe(this, EventName.ConnectDeviceState) { ble: BleTrackDeviceBean -> XEventBus.observe(this, EventName.ConnectDeviceState) { ble: BleTrackDeviceBean ->
getPet(false)?.apply { getPet(false)?.apply {
//蓝牙连接断开上传日志 //蓝牙连接断开上传日志
if (ble.mac == macID && ble.conState == ConState.DISCONNECTED) { if (ble.mac == macID) {
if (ble.conState == ConState.CONNECTED) {
//蓝牙连接就去连接socket
mBleReportManage.dealBleReportData(macID, null)
} else {
mLogBleReportViewModel.uploadLog(mContext, macID) mLogBleReportViewModel.uploadLog(mContext, macID)
} }
} }
} }
}
//更新套餐数据 //更新套餐数据
XEventBus.observe(this, EventName.RefreshPackage) { XEventBus.observe(this, EventName.RefreshPackage) {
mDataViewModel.getHomeBindPetList(this) mDataViewModel.getHomeBindPetList(this)
@@ -338,7 +344,6 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
getPet(false)?.apply { getPet(false)?.apply {
mLogBleReportViewModel.uploadLog(mContext, macID) mLogBleReportViewModel.uploadLog(mContext, macID)
} }
(mFragments[2] as MapV3Fragment).showPetNameAndHead(mSelectPetPosition)
} else { } else {
onChangeClick(mSelectPetPosition) onChangeClick(mSelectPetPosition)
when (mViewBinding.homeV2ViewPager2.currentItem) { when (mViewBinding.homeV2ViewPager2.currentItem) {
@@ -364,6 +369,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
} }
} }
} }
(mFragments[2] as MapV3Fragment).showPetNameAndHead(mSelectPetPosition)
} }
} }
@@ -406,7 +412,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
* 选择宠物弹窗 * 选择宠物弹窗
*/ */
fun selectPetDialog() { fun selectPetDialog() {
if (isRequestPetData && mPetList.size == 0) { if (mPetList.size == 0) {
showToast(R.string.no_bind_pet) showToast(R.string.no_bind_pet)
return return
} }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,199 @@
package com.abbidot.tracker.ui.common.map
import android.content.Context
import android.view.ViewGroup
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.base.BaseMapCommon
import com.abbidot.tracker.bean.HistoryDataBean
import com.abbidot.tracker.bean.MapDeviceBean
import com.abbidot.tracker.constant.ConstantInt
import com.abbidot.tracker.databinding.LayoutPetLocationInfoBinding
import com.abbidot.tracker.ui.fragment.map.baidumap.HomeMapBaiduMapFragment
import com.abbidot.tracker.ui.fragment.map.googlemap.HomeMapGoogleMapFragmentV3
import com.google.android.gms.maps.model.LatLng
import javax.inject.Inject
/**
*Created by .yzq on 2022/7/5/005.
* @link
* @description:
*/
class HomeMapCommonV3 @Inject constructor() : BaseMapCommon() {
private var mHomeMapGoogleMapFragment: HomeMapGoogleMapFragmentV3? = null
private var mHomeMapBaiduMapFragment: HomeMapBaiduMapFragment? = null
fun getMapFragment(
context: Context,
locationLayoutViewBinding: LayoutPetLocationInfoBinding,
deviceBatteryLayout: ViewGroup,
petAddressTimeFormat: String,
mapLoadOk: () -> Unit
): Fragment {
return if (AppUtils.isChina(AppUtils.SWITCH_MAP_TYPE)) {
mHomeMapBaiduMapFragment = HomeMapBaiduMapFragment.newInstance(context, mapLoadOk)
mHomeMapBaiduMapFragment!!
} else {
mHomeMapGoogleMapFragment = HomeMapGoogleMapFragmentV3.newInstance(
context,
locationLayoutViewBinding,
deviceBatteryLayout,
petAddressTimeFormat,
mapLoadOk
)
mHomeMapGoogleMapFragment!!
}
}
fun setMapDeviceBean(mapDeviceBean: MapDeviceBean?) {
if (null != mHomeMapBaiduMapFragment) {
mHomeMapBaiduMapFragment!!.setMapDeviceBean(mapDeviceBean)
} else if (null != mHomeMapGoogleMapFragment) {
mHomeMapGoogleMapFragment!!.setMapDeviceBean(mapDeviceBean)
}
}
/**
* 开始每隔几秒刷新用户位置
*/
fun startRefreshUserLocation() {
if (isMapLoadOk()) startRefreshUserLocation(
mHomeMapBaiduMapFragment, mHomeMapGoogleMapFragment
)
}
/**
* 获取宠物反编译好的位置信息
*/
fun getDecPetAddressData(): HistoryDataBean? {
if (null != mHomeMapBaiduMapFragment) {
return mHomeMapBaiduMapFragment!!.mDecPetAddressData
} else if (null != mHomeMapGoogleMapFragment) {
return mHomeMapGoogleMapFragment!!.mDecPetAddressData
}
return null
}
fun clearMarker() {
if (null != mHomeMapBaiduMapFragment) {
mHomeMapBaiduMapFragment!!.mBaiduMap?.clear()
} else if (null != mHomeMapGoogleMapFragment) {
mHomeMapGoogleMapFragment!!.clearAllMarker()
}
}
fun refreshPetCurrentLocation(latitude: Double, longitude: Double, isMoveCamera: Boolean) {
if (null != mHomeMapBaiduMapFragment) {
mHomeMapBaiduMapFragment?.apply {
refreshPetCurrentLocation(
latitude, longitude, isMoveCamera
)
}
} else if (null != mHomeMapGoogleMapFragment) {
MMKVUtil.putDouble(MMKVKey.MapShowDefaultLat, latitude)
MMKVUtil.putDouble(MMKVKey.MapShowDefaultLon, longitude)
mHomeMapGoogleMapFragment?.apply {
refreshPetCurrentLocation(
LatLng(latitude, longitude), needMoveCamera = isMoveCamera
)
}
}
}
/**
* 重新设置宠物头像
*/
fun setPetHeadIcon(imageUrl: String, petType: Int) {
if (null != mHomeMapBaiduMapFragment) {
mHomeMapBaiduMapFragment!!.setPetHeadIconUrl(imageUrl)
} else if (null != mHomeMapGoogleMapFragment) {
mHomeMapGoogleMapFragment!!.setPetHeadIconUrl(imageUrl, petType)
}
}
/**
* 地图是否加载好了,准备好了
*/
fun isMapLoadOk() = isMapLoadOk(mHomeMapBaiduMapFragment, mHomeMapGoogleMapFragment)
/**
* 切换地图类型
*/
fun switchSatelliteAndNormalMapType() {
switchSatelliteAndNormalMapType(mHomeMapBaiduMapFragment, mHomeMapGoogleMapFragment)
}
/**
* 切换用户和宠物的位置居中显示
*/
fun switchShowLocation(@ConstantInt type: Int) {
switchShowLocationType(type, mHomeMapBaiduMapFragment, mHomeMapGoogleMapFragment)
}
/**
* 画轨迹线
*/
fun addTrackLine(latitude: Double, longitude: Double) {
if (null != mHomeMapBaiduMapFragment) {
mHomeMapBaiduMapFragment!!.addLine(latitude, longitude)
} else if (null != mHomeMapGoogleMapFragment) {
mHomeMapGoogleMapFragment!!.addLine(LatLng(latitude, longitude))
}
}
/**
* 画轨迹线
*/
fun addTrackLines(trackList: MutableList<HistoryDataBean>) {
if (null != mHomeMapBaiduMapFragment) {
} else if (null != mHomeMapGoogleMapFragment) {
mHomeMapGoogleMapFragment!!.addLines(trackList)
}
}
/**
* 计算用户和宠物的距离
*/
fun getUserAndPetDistance(): Double {
var distance = 0.0
if (null != mHomeMapBaiduMapFragment) {
distance = mHomeMapBaiduMapFragment!!.getUserAndPetDistance()
} else if (null != mHomeMapGoogleMapFragment) {
distance = mHomeMapGoogleMapFragment!!.getUserAndPetDistance()
}
return distance
}
/**
* 开始水波纹动画
*/
fun startRippleCircleAnim() {
if (null != mHomeMapBaiduMapFragment) {
} else if (null != mHomeMapGoogleMapFragment) {
mHomeMapGoogleMapFragment!!.startRippleCircleAnim()
}
}
fun greenRippleCircleAnim() {
mHomeMapGoogleMapFragment?.greenRippleCircleAnim()
}
fun setMarkerInfoViewOffset() {
if (null != mHomeMapBaiduMapFragment) {
} else if (null != mHomeMapGoogleMapFragment) {
mHomeMapGoogleMapFragment!!.setMarkerInfoViewOffset()
}
}
// fun getAddressShowMarkerInfoWindow(historyDataBean: HistoryDataBean) {
// if (null != mHomeMapBaiduMapFragment) {
// mHomeMapBaiduMapFragment!!.showMarkerInfoWindow(historyDataBean)
// } else if (null != mHomeMapGoogleMapFragment) {
// mHomeMapGoogleMapFragment!!.showMarkerInfoWindow(historyDataBean)
// }
// }
}

View File

@@ -18,8 +18,8 @@ import com.abbidot.baselibrary.list.BaseRecyclerAdapter
import com.abbidot.baselibrary.util.AppUtils import com.abbidot.baselibrary.util.AppUtils
import com.abbidot.baselibrary.util.LogUtil import com.abbidot.baselibrary.util.LogUtil
import com.abbidot.baselibrary.util.MMKVUtil import com.abbidot.baselibrary.util.MMKVUtil
import com.abbidot.baselibrary.util.Utils
import com.abbidot.tracker.R import com.abbidot.tracker.R
import com.abbidot.tracker.adapter.HomeMapDeviceMsgAdapter
import com.abbidot.tracker.adapter.HomeMapDeviceStateAdapter import com.abbidot.tracker.adapter.HomeMapDeviceStateAdapter
import com.abbidot.tracker.base.BaseDialog import com.abbidot.tracker.base.BaseDialog
import com.abbidot.tracker.base.BaseFragment import com.abbidot.tracker.base.BaseFragment
@@ -37,15 +37,14 @@ import com.abbidot.tracker.dialog.CommonDialog1
import com.abbidot.tracker.dialog.SelectMapTypeDialog import com.abbidot.tracker.dialog.SelectMapTypeDialog
import com.abbidot.tracker.ui.activity.HomeV2Activity import com.abbidot.tracker.ui.activity.HomeV2Activity
import com.abbidot.tracker.ui.activity.device.MyTrackerV2Activity import com.abbidot.tracker.ui.activity.device.MyTrackerV2Activity
import com.abbidot.tracker.ui.activity.map.LiveActivityV2 import com.abbidot.tracker.ui.activity.map.LiveActivityV3
import com.abbidot.tracker.ui.common.map.HomeMapCommon import com.abbidot.tracker.ui.common.map.HomeMapCommonV3
import com.abbidot.tracker.util.Util import com.abbidot.tracker.util.Util
import com.abbidot.tracker.util.ViewUtil import com.abbidot.tracker.util.ViewUtil
import com.abbidot.tracker.util.bluetooth.SRBleUtil import com.abbidot.tracker.util.bluetooth.SRBleUtil
import com.abbidot.tracker.vm.FamilyViewModel import com.abbidot.tracker.vm.FamilyViewModel
import com.abbidot.tracker.vm.FencesMapViewModel import com.abbidot.tracker.vm.FencesMapViewModel
import com.abbidot.tracker.vm.MapViewModel import com.abbidot.tracker.vm.MapViewModel
import com.abbidot.tracker.widget.MapDeviceNetView
import com.clj.fastble.BleManager import com.clj.fastble.BleManager
import com.hjq.permissions.XXPermissions import com.hjq.permissions.XXPermissions
import com.hjq.permissions.permission.PermissionLists import com.hjq.permissions.permission.PermissionLists
@@ -74,14 +73,14 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
private var mCurrentShowPetPos = -1 private var mCurrentShowPetPos = -1
@Inject @Inject
lateinit var mHomeMapCommon: HomeMapCommon lateinit var mHomeMapCommon: HomeMapCommonV3
private lateinit var mFragment: Fragment private lateinit var mFragment: Fragment
private var mMapDeviceBean: MapDeviceBean? = null private var mMapDeviceBean: MapDeviceBean? = null
private lateinit var mDeviceStateList: MutableList<DataBean> private lateinit var mDeviceStateList: MutableList<DataBean>
private lateinit var mDeviceStateAdapter: HomeMapDeviceStateAdapter private lateinit var mDeviceStateAdapter: HomeMapDeviceStateAdapter
private lateinit var mDeviceMsgList: MutableList<DataBean> // private lateinit var mDeviceMsgList: MutableList<DataBean>
private lateinit var mDeviceMsgAdapter: HomeMapDeviceMsgAdapter // private lateinit var mDeviceMsgAdapter: HomeMapDeviceMsgAdapter
//启动移动地图摄像机 //启动移动地图摄像机
private var isMoveCamera = true private var isMoveCamera = true
@@ -113,7 +112,10 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
rlHomeMapTopLayout, WindowInsetsCompat.Type.statusBars() rlHomeMapTopLayout, WindowInsetsCompat.Type.statusBars()
) )
mFragment = mHomeMapCommon.getMapFragment( mFragment = mHomeMapCommon.getMapFragment(
mContext!!, miHomeMapAddressView, MapDeviceNetView(mContext!!) mContext!!,
ilHomeMapPetLocation,
llHomeMapDeviceBatteryLayout,
Utils.DATE_FORMAT_PATTERN_EN11
) { mapLoadOk() } ) { mapLoadOk() }
llHomeMapTopPet.ivTopPetBtnSmall.setImageResource(R.drawable.icon_map_type) llHomeMapTopPet.ivTopPetBtnSmall.setImageResource(R.drawable.icon_map_type)
@@ -123,17 +125,16 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
) )
mDeviceStateList = mutableListOf() mDeviceStateList = mutableListOf()
mDeviceMsgList = mutableListOf()
mMapViewModel.addDeviceDefaultStateData(mContext!!, mDeviceStateList) mMapViewModel.addDeviceDefaultStateData(mContext!!, mDeviceStateList)
mDeviceStateAdapter = HomeMapDeviceStateAdapter(mContext!!, mDeviceStateList) mDeviceStateAdapter = HomeMapDeviceStateAdapter(mContext!!, mDeviceStateList)
ViewUtil.instance.setRecyclerViewVerticalLinearLayout( ViewUtil.instance.setRecyclerViewVerticalLinearLayout(
mContext!!, rvHomeMapDeviceState, mDeviceStateAdapter, bottom = 10 mContext!!, rvHomeMapDeviceState, mDeviceStateAdapter, bottom = 10
) )
mDeviceMsgAdapter = HomeMapDeviceMsgAdapter(mContext!!, mDeviceMsgList) // mDeviceMsgAdapter = HomeMapDeviceMsgAdapter(mContext!!, mDeviceMsgList)
ViewUtil.instance.setRecyclerViewVerticalLinearLayout( // ViewUtil.instance.setRecyclerViewVerticalLinearLayout(
mContext!!, rvHomeMapDeviceMsg, mDeviceMsgAdapter, bottom = 10 // mContext!!, rvHomeMapDeviceMsg, mDeviceMsgAdapter, bottom = 10
) // )
setOnClickListenerViews( setOnClickListenerViews(
homeMapRefreshBtn, homeMapRefreshBtn,
@@ -141,7 +142,9 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
homeMapLiveBtn, homeMapLiveBtn,
llHomeMapTopPet.ivTopPetBtnSmall, llHomeMapTopPet.ivTopPetBtnSmall,
llHomeMapTopPet.homeDataPetNameSmall, llHomeMapTopPet.homeDataPetNameSmall,
llHomeMapTopPet.homeDataPetHeadSmall.root llHomeMapTopPet.homeDataPetHeadSmall.root,
ilHomeMapDeviceBatteryLayout.ivDeviceCloseBtn,
ilHomeMapDeviceMsg.ivDeviceMsgCloseBtn
) )
if (AppUtils.isDebug()) { if (AppUtils.isDebug()) {
@@ -230,17 +233,22 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
override fun onResult(any: Any) { override fun onResult(any: Any) {
val data = it.getOrNull() val data = it.getOrNull()
data?.apply { data?.apply {
mMapDeviceBean?.let { m ->
data.isCloseMsg = m.isCloseMsg
data.isCloseBattery = m.isCloseBattery
data.canShowBattery = m.canShowBattery
}
mMapDeviceBean = data mMapDeviceBean = data
setMapData(data) setMapData(data)
mMapViewModel.setDeviceStateAndWarningData( mMapViewModel.setDeviceStateAndWarningData(
mContext!!, mContext!!,
getHomeV2Activity()?.getPet(), getHomeV2Activity()?.getPet(),
data, data,
mViewBinding.ilHomeMapDeviceMsg.root,
mViewBinding.ilHomeMapDeviceMsg.tvDeviceMsgContent,
mViewBinding.ilHomeMapDeviceMsg.ivDeviceMsgCloseBtn,
mDeviceStateList, mDeviceStateList,
mDeviceStateAdapter, mDeviceStateAdapter
mDeviceMsgList,
mDeviceMsgAdapter,
mViewBinding.rvHomeMapDeviceMsg
) )
} }
} }
@@ -288,15 +296,30 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
//接收蓝牙连接状态 //接收蓝牙连接状态
XEventBus.observe(this, EventName.ConnectDeviceState) { trackBle: BleTrackDeviceBean -> XEventBus.observe(this, EventName.ConnectDeviceState) { trackBle: BleTrackDeviceBean ->
getHomeV2Activity()?.getPet(false)?.apply { getHomeV2Activity()?.getPet(false)?.apply {
//蓝牙断开就重新获取服务器数据,蓝牙数据上报断开 if (trackBle.mac == macID) {
if (trackBle.mac == macID && trackBle.conState != ConState.CONNECTED) { if (trackBle.conState == ConState.CONNECTED) {
mMapDeviceBean?.let {
mMapViewModel.setDeviceStateAndWarningData(
mContext!!,
getHomeV2Activity()?.getPet(),
it,
mViewBinding.ilHomeMapDeviceMsg.root,
mViewBinding.ilHomeMapDeviceMsg.tvDeviceMsgContent,
mViewBinding.ilHomeMapDeviceMsg.ivDeviceMsgCloseBtn,
mDeviceStateList,
mDeviceStateAdapter
)
}
} else {
//隐藏蓝牙nearby //隐藏蓝牙nearby
mViewBinding.rvHomeMapDeviceMsg.visibility = View.GONE mViewBinding.ilHomeMapDeviceMsg.root.visibility = View.GONE
//蓝牙断开就重新获取服务器数据,蓝牙数据上报断开
updateMapDeviceStatus() updateMapDeviceStatus()
} }
} }
} }
} }
}
/** /**
* 更新蓝牙上报的数据 * 更新蓝牙上报的数据
@@ -314,29 +337,27 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
it.longitude = location.longitude it.longitude = location.longitude
it.latitude = location.latitude it.latitude = location.latitude
} }
mHomeMapCommon.setMapDeviceBean(mMapDeviceBean) setMapDeviceBean(it)
mHomeMapCommon.refreshPetCurrentLocation( mHomeMapCommon.refreshPetCurrentLocation(
it.latitude, it.longitude, isMoveCamera it.latitude, it.longitude, isMoveCamera
) )
mHomeMapCommon.startRefreshUserLocation() mHomeMapCommon.startRefreshUserLocation()
} }
} ViewUtil.instance.viewShow(mViewBinding.homeMapLiveBtn)
mViewBinding.homeMapLiveBtn.visibility = View.VISIBLE
mMapViewModel.setDeviceStateAndWarningData( mMapViewModel.setDeviceStateAndWarningData(
mContext!!, mContext!!,
getHomeV2Activity()?.getPet(), getHomeV2Activity()?.getPet(),
mMapDeviceBean!!, it,
mViewBinding.ilHomeMapDeviceMsg.root,
mViewBinding.ilHomeMapDeviceMsg.tvDeviceMsgContent,
mViewBinding.ilHomeMapDeviceMsg.ivDeviceMsgCloseBtn,
mDeviceStateList, mDeviceStateList,
mDeviceStateAdapter, mDeviceStateAdapter
mDeviceMsgList,
mDeviceMsgAdapter,
mViewBinding.rvHomeMapDeviceMsg
) )
} }
} }
} }
}
/** /**
* 显示被删除邀请的弹窗 * 显示被删除邀请的弹窗
@@ -438,10 +459,6 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
private fun updateMapDeviceStatus( private fun updateMapDeviceStatus(
isNeedCountDown: Boolean = true, useBleLocation: Boolean = false isNeedCountDown: Boolean = true, useBleLocation: Boolean = false
) { ) {
// mShowCenterLocationType = ConstantInt.PetLocationType
// ViewUtil.instance.setMapSwitchLocationButtonImage(
// mViewBinding.homeMapRefreshBtn, mShowCenterLocationType
// )
getHomeV2Activity()?.apply { getHomeV2Activity()?.apply {
if (mPetList.size <= mCurrentShowPetPos) return if (mPetList.size <= mCurrentShowPetPos) return
getPet()?.apply { getPet()?.apply {
@@ -531,8 +548,12 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
if (mHomeMapCommon.isMapLoadOk()) { if (mHomeMapCommon.isMapLoadOk()) {
isMoveCamera = true isMoveCamera = true
mHomeMapCommon.clearMarker() mHomeMapCommon.clearMarker()
mViewBinding.miHomeMapAddressView.visibility = View.GONE mMapDeviceBean?.let {
mViewBinding.rvHomeMapDeviceMsg.visibility = View.GONE it.isCloseMsg = false
it.isCloseBattery = false
it.canShowBattery = false
}
mViewBinding.ilHomeMapDeviceMsg.root.visibility = View.GONE
showLoading(true) showLoading(true)
val pet = mPetList[position] val pet = mPetList[position]
//重新设置地图宠物头像 //重新设置地图宠物头像
@@ -555,7 +576,7 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
if (Util.isTimeoutReport(updateTime) || powerSwitch == ConstantInt.Type0 || powerSwitch == ConstantInt.Type2 || inWifiZone == ConstantInt.Type1) View.GONE if (Util.isTimeoutReport(updateTime) || powerSwitch == ConstantInt.Type0 || powerSwitch == ConstantInt.Type2 || inWifiZone == ConstantInt.Type1) View.GONE
else View.VISIBLE else View.VISIBLE
mHomeMapCommon.setMapDeviceBean(this) setMapDeviceBean(this)
//设置循环查询时间间隔 30秒 //设置循环查询时间间隔 30秒
mMapViewModel.updateMillisInFuture(0.5f) mMapViewModel.updateMillisInFuture(0.5f)
@@ -565,10 +586,6 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
} }
} }
// mShowCenterLocationType = ConstantInt.PetLocationType
// ViewUtil.instance.setMapSwitchLocationButtonImage(
// mViewBinding.homeMapRefreshBtn, mShowCenterLocationType
// )
mHomeMapCommon.refreshPetCurrentLocation(latitude, longitude, isMoveCamera) mHomeMapCommon.refreshPetCurrentLocation(latitude, longitude, isMoveCamera)
mHomeMapCommon.startRefreshUserLocation() mHomeMapCommon.startRefreshUserLocation()
@@ -576,6 +593,22 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
} }
} }
private fun setMapDeviceBean(mapDeviceBean: MapDeviceBean) {
mapDeviceBean.apply {
mViewBinding.ilHomeMapDeviceBatteryLayout.let {
mMapViewModel.setMapDeviceBattery(
mContext!!, mapDeviceBean, it.root, it.tvDeviceBatteryInfo, it.ivDeviceCloseBtn
)
}
mViewBinding.ilHomeMapPetLocation.let {
mMapViewModel.setPetLocationReverseGeocode(
mContext!!, mapDeviceBean, it.root, it.tvPetLocationReverseGeocode
)
}
mHomeMapCommon.setMapDeviceBean(this)
}
}
/** /**
* 检查获取定位,蓝牙权限 * 检查获取定位,蓝牙权限
*/ */
@@ -591,7 +624,7 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
} else { } else {
getPet()?.apply { getPet()?.apply {
mViewBinding.homeMapLiveBtn.isEnabled = false mViewBinding.homeMapLiveBtn.isEnabled = false
val intent = Intent(mContext, LiveActivityV2::class.java) val intent = Intent(mContext, LiveActivityV3::class.java)
intent.putExtra(ConstantString.JumpActivity, true) intent.putExtra(ConstantString.JumpActivity, true)
intent.putExtra(ConstantString.Pet, this) intent.putExtra(ConstantString.Pet, this)
startActivity(intent) startActivity(intent)
@@ -605,7 +638,7 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
} else { } else {
getPet()?.apply { getPet()?.apply {
mViewBinding.homeMapBluetoothBtn.isEnabled = false mViewBinding.homeMapBluetoothBtn.isEnabled = false
val intent = Intent(mContext, LiveActivityV2::class.java) val intent = Intent(mContext, LiveActivityV3::class.java)
intent.putExtra(ConstantString.JumpActivity, false) intent.putExtra(ConstantString.JumpActivity, false)
intent.putExtra(ConstantString.Pet, this) intent.putExtra(ConstantString.Pet, this)
startActivity(intent) startActivity(intent)
@@ -644,7 +677,7 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
getHomeV2Activity()?.let { getHomeV2Activity()?.let {
it.getPet()?.apply { it.getPet()?.apply {
mViewBinding.homeMapLiveBtn.isEnabled = false mViewBinding.homeMapLiveBtn.isEnabled = false
val intent = Intent(mContext, LiveActivityV2::class.java) val intent = Intent(mContext, LiveActivityV3::class.java)
intent.putExtra(ConstantString.JumpActivity, true) intent.putExtra(ConstantString.JumpActivity, true)
intent.putExtra(ConstantString.Pet, this) intent.putExtra(ConstantString.Pet, this)
startActivity(intent) startActivity(intent)
@@ -655,6 +688,15 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
llHomeMapTopPet.ivTopPetBtnSmall -> showMapTypeDialog() llHomeMapTopPet.ivTopPetBtnSmall -> showMapTypeDialog()
homeMapBluetoothBtn -> checkPermissions(1) homeMapBluetoothBtn -> checkPermissions(1)
llHomeMapTopPet.homeDataPetNameSmall, llHomeMapTopPet.homeDataPetHeadSmall.root -> getHomeV2Activity()?.selectPetDialog() llHomeMapTopPet.homeDataPetNameSmall, llHomeMapTopPet.homeDataPetHeadSmall.root -> getHomeV2Activity()?.selectPetDialog()
ilHomeMapDeviceBatteryLayout.ivDeviceCloseBtn -> {
mMapDeviceBean?.isCloseBattery = true
llHomeMapDeviceBatteryLayout.visibility = View.INVISIBLE
}
ilHomeMapDeviceMsg.ivDeviceMsgCloseBtn -> {
mMapDeviceBean?.isCloseMsg = true
ilHomeMapDeviceMsg.root.visibility = View.GONE
}
} }
} }

View File

@@ -21,6 +21,7 @@ import com.abbidot.tracker.R
import com.abbidot.tracker.base.BaseFragment import com.abbidot.tracker.base.BaseFragment
import com.abbidot.tracker.bean.FencesBean import com.abbidot.tracker.bean.FencesBean
import com.abbidot.tracker.bean.HistoryDataBean import com.abbidot.tracker.bean.HistoryDataBean
import com.abbidot.tracker.bean.MapDeviceBean
import com.abbidot.tracker.constant.ConstantInt import com.abbidot.tracker.constant.ConstantInt
import com.abbidot.tracker.databinding.FragmentGoogleMapBinding import com.abbidot.tracker.databinding.FragmentGoogleMapBinding
import com.abbidot.tracker.util.ImageUtil import com.abbidot.tracker.util.ImageUtil
@@ -392,13 +393,16 @@ abstract class BaseGoogleMapFragment :
} }
//刷新当前位置ok,延时等待移动地图摄像头动画 //刷新当前位置ok,延时等待移动地图摄像头动画
if (isAnimMoveCamera) { // if (isAnimMoveCamera) {
// mGoogleMapView.postDelayed({
// onRefreshPetCurrentLocationOk(mGoogleMap!!)
// }, 1000)
// } else {
// onRefreshPetCurrentLocationOk(mGoogleMap!!)
// }
mGoogleMapView.postDelayed({ mGoogleMapView.postDelayed({
onRefreshPetCurrentLocationOk(mGoogleMap!!) onRefreshPetCurrentLocationOk(mGoogleMap!!)
}, 1000) }, 500)
} else {
onRefreshPetCurrentLocationOk(mGoogleMap!!)
}
} }
} }
} }
@@ -1066,6 +1070,21 @@ abstract class BaseGoogleMapFragment :
} }
} }
/**
* 设置Marker弹窗设备电量的位置
*/
fun setMapDeviceBatteryOffset(
viewGroup: ViewGroup, latLng: LatLng, mapDeviceBean: MapDeviceBean
) {
mGoogleMap?.projection?.toScreenLocation(latLng)?.let {
viewGroup.x = it.x.toFloat() - viewGroup.width / 2 + AppUtils.dpToPx(5)
viewGroup.y = it.y.toFloat() - AppUtils.dpToPx(56) - viewGroup.height
if (mapDeviceBean.canShowBattery && !mapDeviceBean.isCloseBattery) ViewUtil.instance.viewShow(
viewGroup
)
}
}
/** /**
* 设置地图网络类型显示位置 * 设置地图网络类型显示位置
*/ */

View File

@@ -0,0 +1,320 @@
package com.abbidot.tracker.ui.fragment.map.googlemap
import android.animation.ValueAnimator
import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import androidx.core.content.ContextCompat
import androidx.core.view.isGone
import androidx.fragment.app.viewModels
import com.abbidot.baselibrary.util.AppUtils
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.databinding.LayoutPetLocationInfoBinding
import com.abbidot.tracker.util.Util
import com.abbidot.tracker.util.ViewUtil
import com.abbidot.tracker.vm.GeoCoderViewModel
import com.google.android.gms.maps.GoogleMap
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.Polyline
import com.google.android.gms.maps.model.PolylineOptions
import kotlin.math.pow
/**
*Created by .yzq on 2022/1/13/013.
* @link
* @description:首页map谷歌地图
*/
class HomeMapGoogleMapFragmentV3 : BaseGoogleMapFragment() {
private val mGeoCoderViewModel: GeoCoderViewModel by viewModels()
private lateinit var mPetLocationLayoutBinding: LayoutPetLocationInfoBinding
private lateinit var mDeviceBatteryLayout: ViewGroup
//宠物当前反地理位置信息
var mDecPetAddressData: HistoryDataBean? = null
private var mMapDeviceBean: MapDeviceBean? = null
private lateinit var mMapLoadOk: () -> Unit
//启动动画移动地图摄像机
private var isMoveCamera = true
private var mPolyline: Polyline? = null
private var mRippleCircle: Circle? = null
private var mValueAnimator: ValueAnimator? = null
private var mRippleCirclePercent = 0.0
private var mRippleCircleRadius = 200
private var isMapCameraMove = false
private var mPetAddressTimeFormat = Utils.DATE_FORMAT_PATTERN_EN11
companion object {
@JvmStatic
fun newInstance(
context: Context,
locationLayoutViewBinding: LayoutPetLocationInfoBinding,
deviceBatteryLayout: ViewGroup,
petAddressTimeFormat: String,
mapLoadOk: () -> Unit
) = HomeMapGoogleMapFragmentV3().apply {
mContext = context
mDeviceBatteryLayout = deviceBatteryLayout
mPetLocationLayoutBinding = locationLayoutViewBinding
mPetAddressTimeFormat = petAddressTimeFormat
mMapLoadOk = mapLoadOk
}
}
fun setMapDeviceBean(mapDeviceBean: MapDeviceBean?) {
mMapDeviceBean = mapDeviceBean
}
override fun liveDataObserve() {
//反地理编码成功返回
mGeoCoderViewModel.mLatLonAddressLiveData.observe(viewLifecycleOwner) {
//保存地理信息,方便传参给导航页面
if (null == mDecPetAddressData) mDecPetAddressData = HistoryDataBean()
mMapDeviceBean?.apply {
val timeString = Utils.formatTime(latLonUpdateTime * 1000, mPetAddressTimeFormat)
mDecPetAddressData?.let { history ->
//更新位置时间
history.dayTime = timeString
//详细位置
history.address = it
//传递位置信息给InfoWindowAdapter窗口
// mMarker?.tag = history
// showMarkerInfoWindow(history)
val address = String.format(mContext!!.getString(R.string.txt_near), it)
ViewUtil.instance.viewShow(mPetLocationLayoutBinding.root)
mPetLocationLayoutBinding.let { layout ->
layout.tvPetLocationReverseGeocode.text = address
layout.tvPetLocationUpdateTime.text = timeString
}
}
}
}
}
override fun onMapLoadOk(googleMap: GoogleMap) {
//设置自定义头部地点布局
mGoogleMap?.apply {
setOnCameraIdleListener {
if (isMapCameraMove) {
isMapCameraMove = false
} else {
setMarkerInfoViewOffset()
}
}
setOnCameraMoveListener {
isMapCameraMove = true
setMarkerInfoViewOffset()
}
setOnMarkerClickListener(object : GoogleMap.OnMarkerClickListener {
override fun onMarkerClick(marker: Marker): Boolean {
if (marker == mMarker) {
mMapDeviceBean?.let {
if (it.canShowBattery) {
mDeviceBatteryLayout.visibility = if (mDeviceBatteryLayout.isGone) {
it.isCloseBattery = false
View.VISIBLE
} else {
it.isCloseBattery = true
View.GONE
}
}
}
return true
}
return false
}
})
getLastLocation()
}
//变量是否初始化
if (::mMapLoadOk.isInitialized) mMapLoadOk()
}
override fun onRefreshPetCurrentLocationOk(googleMap: GoogleMap) {
if (null == mMarker) return
else startReverseGeocode()
}
/**
* 刚开始的反编译地理位置
*/
private fun startReverseGeocode() {
mMapDeviceBean?.apply {
mGeoCoderViewModel.getLatLonAddress(latitude, longitude, false)
setMarkerInfoViewOffset()
}
}
fun setMarkerInfoViewOffset() {
mPetLatLng?.apply {
mMapDeviceBean?.let {
setMapDeviceBatteryOffset(
mDeviceBatteryLayout, LatLng(latitude, longitude), it
)
}
}
}
/**
* 计算用户和宠物的距离
*/
fun getUserAndPetDistance(): Double {
var distance = 0.0
mUserLatLng?.apply {
mPetLatLng?.let {
distance =
Util.measureLatLonDistance(latitude, longitude, it.latitude, it.longitude)
}
}
return distance
}
/**
* 画用户和宠物之间的虚线
*/
private fun addUserAndPetLine(petLatLng: LatLng) {
mUserLatLng?.apply {
mGoogleMap?.let {
if (null == mPolyline) {
val polylineOptions =
PolylineOptions().clickable(false).width(AppUtils.dpToPx(1.5f))
.color(ContextCompat.getColor(mContext!!, R.color.blue_color9))
.geodesic(false)
mPolyline = it.addPolyline(polylineOptions)
mPolyline?.pattern = getDashedPatternStyle(18f)
}
mPolyline?.let { pLine ->
val latList = mutableListOf<LatLng>()
latList.add(petLatLng)
latList.add(this)
pLine.points = latList
}
}
}
}
/**
* 初始化并添加水波纹圆
*/
private fun addRippleCircle() {
mPetLatLng?.apply {
mGoogleMap?.let {
if (null == mRippleCircle) {
mRippleCircle = it.addCircle(
CircleOptions().center(this)
.radius(mRippleCircleRadius * mRippleCirclePercent)
.strokeWidth(AppUtils.dpToPx(2).toFloat())
.fillColor(ContextCompat.getColor(mContext!!, R.color.black10))
.strokeColor(ContextCompat.getColor(mContext!!, R.color.black10))
)
setRippleCircleAnim()
}
}
}
}
/**
* 设置水波纹动画
*/
private fun setRippleCircleAnim() {
if (null == mValueAnimator) {
mValueAnimator = ViewUtil.instance.setValueAnimator(
0.0, 100.0, 1500, LinearInterpolator()
) {
mRippleCirclePercent = it.animatedValue as Float / 100.0
mRippleCircle?.apply {
mPetLatLng?.let { petLatLng ->
center = petLatLng
radius = mRippleCircleRadius * mRippleCirclePercent
}
}
}?.apply {
repeatMode = ValueAnimator.RESTART
repeatCount = ValueAnimator.INFINITE
}
}
}
/**
* 画线
*/
fun addLine(latLng: LatLng) {
// addPolyline(mGoogleMap!!, latLng)
// addUserAndPetLine(latLng)
refreshPetCurrentLocation(latLng, needMoveCamera = isMoveCamera)
// mRippleCircle?.apply {
// //一像素对应几米
// val pxDis = 2.0.pow(15.5 - getGoogleMapZoom())
// mRippleCircleRadius = (pxDis * 150).toInt()
// fillColor = (ContextCompat.getColor(mContext!!, R.color.select_color5))
// strokeColor = (ContextCompat.getColor(mContext!!, R.color.select_color5))
// mValueAnimator?.duration = 2000
// }
}
/**
* 画多条线
*/
fun addLines(trackList: MutableList<HistoryDataBean>) {
val latLngList = mutableListOf<LatLng>()
for (i in 0 until trackList.size) {
trackList[i].apply {
val latLng = LatLng(latitude, longitude)
latLngList.add(latLng)
if (i == trackList.size - 1) {
// addUserAndPetLine(latLng)
refreshPetCurrentLocation(latLng, needMoveCamera = isMoveCamera)
}
}
}
// addPolyLines(mGoogleMap!!, latLngList)
}
/**
* 开始水波纹动画
*/
fun startRippleCircleAnim() {
mPetLatLng?.apply {
//一像素对应几米
val pxDis = 2.0.pow(15.5 - getGoogleMapZoom())
mRippleCircleRadius = (pxDis * 150).toInt()
// addUserAndPetLine(this)
addRippleCircle()
}
}
/**
* 直播开始之后,改变绿色波纹动画
*/
fun greenRippleCircleAnim() {
mRippleCircle?.apply {
//一像素对应几米
val pxDis = 2.0.pow(15.5 - getGoogleMapZoom())
mRippleCircleRadius = (pxDis * 150).toInt()
fillColor = (ContextCompat.getColor(mContext!!, R.color.select_color5))
strokeColor = (ContextCompat.getColor(mContext!!, R.color.select_color5))
mValueAnimator?.duration = 2000
}
}
override fun onDetach() {
super.onDetach()
mValueAnimator?.cancel()
}
}

View File

@@ -36,6 +36,7 @@ import android.widget.TextView
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.setPadding import androidx.core.view.setPadding
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
@@ -1116,6 +1117,6 @@ class ViewUtil private constructor() {
} }
fun viewShow(view: View) { fun viewShow(view: View) {
if (view.isGone) view.visibility = View.VISIBLE if (view.isGone || view.isInvisible) view.visibility = View.VISIBLE
} }
} }

View File

@@ -2,6 +2,10 @@ package com.abbidot.tracker.vm
import android.content.Context import android.content.Context
import android.os.CountDownTimer import android.os.CountDownTimer
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.ContextCompat
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@@ -17,6 +21,8 @@ import com.abbidot.tracker.retrofit2.NetworkApi
import com.abbidot.tracker.util.Util import com.abbidot.tracker.util.Util
import com.abbidot.tracker.util.ViewUtil import com.abbidot.tracker.util.ViewUtil
import com.abbidot.tracker.util.bluetooth.SRBleUtil import com.abbidot.tracker.util.bluetooth.SRBleUtil
import com.abbidot.tracker.widget.TypefaceButton
import com.abbidot.tracker.widget.TypefaceTextView
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class MapViewModel : ViewModel() { class MapViewModel : ViewModel() {
@@ -28,8 +34,7 @@ class MapViewModel : ViewModel() {
private var mRefreshDataMin = 0.5f private var mRefreshDataMin = 0.5f
private var mDeviceId = "" private var mDeviceId = ""
//警告动画是否结束 private var mDeviceMsgType = ConstantInt.SpecialType
private var isWarningAnimEnd = true
fun getMapDeviceStatus(deviceId: String, isNeedCountDown: Boolean = true) { fun getMapDeviceStatus(deviceId: String, isNeedCountDown: Boolean = true) {
viewModelScope.launch { viewModelScope.launch {
@@ -199,6 +204,63 @@ class MapViewModel : ViewModel() {
} }
} }
/**
* 设置设备状态和告警信息显示
*/
fun setDeviceStateAndWarningData(
context: Context,
petBean: PetBean?,
mapDeviceBean: MapDeviceBean,
rootView: ViewGroup,
tvDeviceMsgView: TypefaceButton,
deviceMsgCloseBtn: AppCompatImageView,
deviceStateList: MutableList<DataBean>,
deviceStateAdapter: BaseRecyclerAdapter<DataBean>,
) {
mapDeviceBean.apply {
tvDeviceMsgView.setBackgroundResource(R.color.device_msg_color1)
if (null != petBean && null != SRBleUtil.instance.getConnectMacDevice(petBean.macID)) {
if (isCloseMsg && mDeviceMsgType == ConstantInt.Type0) {
} else {
val nearby =
String.format(context.getString(R.string.txt_is_nearby), petBean.petName)
tvDeviceMsgView.text = nearby
isCloseMsg = false
tvDeviceMsgView.setBackgroundResource(R.color.green_color10)
ViewUtil.instance.viewShow(rootView)
deviceMsgCloseBtn.visibility = View.GONE
}
} else if (inNoGoZone == ConstantInt.BadZone) {
if (isCloseMsg && mDeviceMsgType == ConstantInt.Type1) {
} else {
tvDeviceMsgView.text = context.getString(R.string.txt_in_no_go_zone)
ViewUtil.instance.viewShow(deviceMsgCloseBtn)
ViewUtil.instance.viewShow(rootView)
isCloseMsg = false
mDeviceMsgType = ConstantInt.Type1
}
} else if (inSafeZone == ConstantInt.BadZone) {
if (isCloseMsg && mDeviceMsgType == ConstantInt.Type2) {
} else {
tvDeviceMsgView.text = context.getString(R.string.txt_out_save_zone)
ViewUtil.instance.viewShow(rootView)
ViewUtil.instance.viewShow(deviceMsgCloseBtn)
isCloseMsg = false
mDeviceMsgType = ConstantInt.Type2
}
} else {
mDeviceMsgType = ConstantInt.Type3
rootView.visibility = View.GONE
}
setDeviceState(context, mapDeviceBean, deviceStateList)
deviceStateAdapter.notifyItemRangeChanged(0, deviceStateList.size)
}
}
/** /**
* 设置没有的状态 * 设置没有的状态
*/ */
@@ -363,6 +425,71 @@ class MapViewModel : ViewModel() {
} }
} }
fun setMapDeviceBattery(
context: Context,
mapDeviceBean: MapDeviceBean,
rootView: ViewGroup,
batteryText: TypefaceTextView,
closeBtn: AppCompatImageView
) {
mapDeviceBean.apply {
if (isCloseBattery) return@apply
batteryText.let {
canShowBattery = true
rootView.visibility = View.VISIBLE
if (powerSwitch == ConstantInt.Type0) {
it.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0)
it.text = context.getString(R.string.txt_powered_off)
ViewUtil.instance.viewShow(closeBtn)
} else if (powerSwitch == ConstantInt.Type3) {
it.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.icon_charge_image, 0, 0, 0
)
it.text = context.getString(R.string.txt_charging)
ViewUtil.instance.viewShow(closeBtn)
} else if (batteryLevel <= ConstantInt.LowBattery30) {
val lowBattery =
if (batteryLevel <= ConstantInt.LowBattery10) ConstantInt.LowBattery10
else if (batteryLevel <= ConstantInt.LowBattery20) ConstantInt.LowBattery20
else ConstantInt.LowBattery30
it.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.icon_low_battery_image, 0, 0, 0
)
it.text = String.format(
context.getString(R.string.txt_battery_less_than), "$lowBattery"
)
} else {
rootView.visibility = View.INVISIBLE
canShowBattery = false
}
}
}
}
fun setPetLocationReverseGeocode(
context: Context,
mapDeviceBean: MapDeviceBean,
rootView: ViewGroup,
locationText: TypefaceTextView,
) {
mapDeviceBean.apply {
val imageResId = if (inWifiZone == ConstantInt.Type1) {
rootView.background =
ContextCompat.getDrawable(context, R.drawable.shape16_light_green_color_bg)
R.drawable.icon_wifi_image
} else {
rootView.background =
ContextCompat.getDrawable(context, R.drawable.shape16_white_color_bg)
R.drawable.icon_wifi_image
0
}
locationText.setCompoundDrawablesWithIntrinsicBounds(
imageResId, 0, 0, 0
)
}
}
/** /**
* 停止获取数据 * 停止获取数据
*/ */

View File

@@ -1,133 +0,0 @@
package com.abbidot.tracker.widget
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.text.TextUtils
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat
import com.abbidot.baselibrary.util.AppUtils
import com.abbidot.tracker.R
import com.qmuiteam.qmui.util.QMUIDisplayHelper
/**
*Created by .yzq on 2024/8/26/026.
* @link
* @description:
*/
class MapBatteryView : View {
private lateinit var mContext: Context
private var mOffsetX = 0
private var mOffsetY = 0
//文字和边界的距离。三角形的直线长
private var mPadding = 0
private lateinit var mTextPaint: Paint
private lateinit var mPaint: Paint
//小三角形的path
private lateinit var mTrianglePath: Path
private var mTimeText = ""
private var mAddressText = ""
constructor(context: Context) : super(context) {
init(context)
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context, attrs, defStyleAttr
) {
init(context)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init(context)
}
private fun init(context: Context) {
//禁用硬件加速,防止返回到界面多次执行onDraw
setLayerType(LAYER_TYPE_SOFTWARE, null)
mContext = context
mPaint = Paint().apply {
color = ContextCompat.getColor(mContext, R.color.white)
}
//开启抗锯齿
mTextPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = ContextCompat.getColor(mContext, R.color.black)
textSize = QMUIDisplayHelper.sp2px(mContext, 12).toFloat()
}
mPadding = AppUtils.dpToPx(6)
mTrianglePath = Path()
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.apply {
startDraw(this)
}
}
private fun startDraw(canvas: Canvas) {
if (TextUtils.isEmpty(mAddressText) && TextUtils.isEmpty(mTimeText)) return
mTrianglePath.apply {
reset()
moveTo((mOffsetX - mPadding).toFloat(), (mOffsetY - mPadding).toFloat())
lineTo(mOffsetX.toFloat(), mOffsetY.toFloat())
lineTo((mOffsetX + mPadding).toFloat(), (mOffsetY - mPadding).toFloat())
close()
}
canvas.apply {
drawPath(mTrianglePath, mPaint)
val fontMetrics = mTextPaint.fontMetrics
//文字高度
val textHeight = fontMetrics.bottom - fontMetrics.top
//时间文字宽度
val timeTextWith = mTextPaint.measureText(mTimeText)
//地址文字宽度
val addressTextWith = mTextPaint.measureText(mAddressText)
val maxTextWith = maxOf(timeTextWith, addressTextWith)
drawRoundRect(
mOffsetX - maxTextWith / 2 - mPadding,
mOffsetY - textHeight * 2 - mPadding * 2,
mOffsetX + maxTextWith / 2 + mPadding,
mOffsetY.toFloat() - mPadding,
AppUtils.dpToPx(6f),
AppUtils.dpToPx(6f),
mPaint
)
drawText(
mTimeText,
mOffsetX - timeTextWith / 2,
mOffsetY - textHeight / 2 - mPadding,
mTextPaint
)
drawText(
mAddressText,
mOffsetX - addressTextWith / 2,
mOffsetY - textHeight / 2 - textHeight - mPadding,
mTextPaint
)
}
}
fun setShowText(time: String, address: String) {
mTimeText = time
mAddressText = address
invalidate()
}
fun setOffsetXY(x: Int, y: Int) {
mOffsetX = x
mOffsetY = y
invalidate()
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/green_color10" />
<corners android:radius="@dimen/dp_16" />
</shape>

View File

@@ -0,0 +1,145 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.activity.map.LiveActivityV2">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fc_live_v2_map_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_live_v3_map_device_battery_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible">
<include
android:id="@+id/il_live_v3_map_device_battery_layout"
layout="@layout/layout_map_device_battery" />
</androidx.appcompat.widget.LinearLayoutCompat>
<include
android:id="@+id/ll_live_v2_map_top_pet"
layout="@layout/layout_top_pet_data_small"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/dp_8"
android:layout_marginTop="@dimen/dp_40" />
<com.qmuiteam.qmui.widget.roundwidget.QMUIRoundLinearLayout
android:id="@+id/ll_live_v2_state_layout"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_34"
android:layout_below="@id/ll_live_v2_map_top_pet"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/dp_8"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/dp_12"
android:visibility="gone"
app:qmui_backgroundColor="@color/select_color2"
app:qmui_radius="@dimen/dp_28">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lav_live_v2_state_anim"
android:layout_width="@dimen/dp_40"
android:layout_height="wrap_content"
android:visibility="gone"
app:lottie_loop="true" />
<com.abbidot.tracker.widget.TypefaceTextView
android:id="@+id/tv_live_v2_state_content"
style="@style/my_TextView_style_v2"
android:text="@string/txt_starting_live"
android:textColor="@color/select_color"
android:textSize="@dimen/textSize12"
app:typeface="@string/roboto_regular_font" />
</com.qmuiteam.qmui.widget.roundwidget.QMUIRoundLinearLayout>
<include
android:id="@+id/il_live_v3_map_device_msg"
layout="@layout/item_home_map_device_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ll_live_v2_state_layout"
android:layout_centerInParent="true"
android:layout_marginTop="@dimen/dp_6"
android:visibility="gone" />
<com.abbidot.tracker.widget.NonSwipeRecyclerView
android:id="@+id/rv_map_live_v2_device_state"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ll_live_v2_map_top_pet"
android:layout_alignParentEnd="true"
android:layout_marginTop="@dimen/dp_18"
android:layout_marginEnd="@dimen/dp_12"
android:layoutDirection="rtl" />
<include
android:id="@+id/il_live_v2_bluetooth_find_device"
layout="@layout/layout_bluetooth_find_device"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:visibility="gone" />
<include
android:id="@+id/il_live_v3_map_pet_location"
layout="@layout/layout_pet_location_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginHorizontal="@dimen/dp_8"
android:layout_marginBottom="@dimen/dp_4"
android:visibility="invisible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_map_live_v2_refresh_btn"
style="@style/map_image_yellow_btn_style"
android:layout_above="@id/il_live_v3_map_pet_location"
android:layout_alignParentEnd="true"
android:layout_marginEnd="@dimen/dp_12"
android:layout_marginBottom="@dimen/dp_16" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_map_live_v2_bluetooth_btn"
style="@style/map_image_white_btn_style"
android:layout_alignTop="@id/iv_map_live_v2_refresh_btn"
android:layout_alignBottom="@id/iv_map_live_v2_refresh_btn"
android:layout_marginStart="@dimen/dp_12"
android:padding="@dimen/dp_8"
android:src="@drawable/icon_map_bluetooth" />
<include
android:id="@+id/il_map_live_v2_issue_layout"
layout="@layout/layout_live_issue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:visibility="gone" />
</RelativeLayout>
<include
android:id="@+id/il_live_v2_operate_layout"
layout="@layout/layout_live_v2_data_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white" />
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@@ -10,10 +10,17 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
<com.abbidot.tracker.widget.MapMarkerInfoView
android:id="@+id/mi_home_map_address_view" <androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent" android:id="@+id/ll_home_map_device_battery_layout"
android:layout_height="match_parent" /> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible">
<include
android:id="@+id/il_home_map_device_battery_layout"
layout="@layout/layout_map_device_battery" />
</androidx.appcompat.widget.LinearLayoutCompat>
<RelativeLayout <RelativeLayout
@@ -29,13 +36,15 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_8" /> android:layout_marginTop="@dimen/dp_8" />
<androidx.recyclerview.widget.RecyclerView <include
android:id="@+id/rv_home_map_device_msg" android:id="@+id/il_home_map_device_msg"
layout="@layout/item_home_map_device_msg"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/ll_home_map_top_pet" android:layout_below="@id/ll_home_map_top_pet"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:layout_marginTop="@dimen/dp_8" /> android:layout_marginTop="@dimen/dp_6"
android:visibility="gone" />
<com.abbidot.tracker.widget.NonSwipeRecyclerView <com.abbidot.tracker.widget.NonSwipeRecyclerView
android:id="@+id/rv_home_map_device_state" android:id="@+id/rv_home_map_device_state"
@@ -53,7 +62,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_marginBottom="@dimen/dp_40" /> android:layout_marginBottom="@dimen/dp_38"
android:visibility="invisible" />
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/home_map_bluetooth_btn" android:id="@+id/home_map_bluetooth_btn"
@@ -80,7 +90,7 @@
android:orientation="vertical" android:orientation="vertical"
android:paddingHorizontal="@dimen/dp_14" android:paddingHorizontal="@dimen/dp_14"
android:paddingVertical="@dimen/dp_16" android:paddingVertical="@dimen/dp_16"
android:visibility="visible"> android:visibility="invisible">
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="@dimen/dp_255" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:gravity="center"> android:gravity="center">
@@ -9,11 +9,22 @@
<com.abbidot.tracker.widget.TypefaceButton <com.abbidot.tracker.widget.TypefaceButton
android:id="@+id/tv_device_msg_content" android:id="@+id/tv_device_msg_content"
style="@style/my_TextView_style_v2" style="@style/my_TextView_style_v2"
android:background="@color/orange_color3" android:layout_marginTop="@dimen/dp_4"
android:layout_marginEnd="@dimen/dp_4"
android:background="@color/device_msg_color1"
android:paddingHorizontal="@dimen/dp_18" android:paddingHorizontal="@dimen/dp_18"
android:paddingVertical="@dimen/dp_12" android:paddingVertical="@dimen/dp_12"
android:textColor="@color/data_black_color" android:textColor="@color/data_black_color"
android:textSize="@dimen/textSize12" android:textSize="@dimen/textSize12"
app:qmui_radius="@dimen/dp_28" /> app:qmui_radius="@dimen/dp_28" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_device_msg_close_btn"
android:layout_width="@dimen/dp_16"
android:layout_height="@dimen/dp_16"
android:layout_gravity="end"
android:src="@drawable/ic_delete_easyy_photos"
android:tint="@color/gray_color3" />
</FrameLayout>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_6"
android:layout_marginEnd="@dimen/dp_8"
android:gravity="center"
android:orientation="vertical">
<com.abbidot.tracker.widget.TypefaceTextView
android:id="@+id/tv_device_battery_info"
style="@style/my_TextView_style_v2"
android:background="@drawable/shape8_white_bg"
android:drawableStart="@drawable/icon_low_battery_image"
android:drawablePadding="@dimen/dp_4"
android:padding="@dimen/dp_10"
android:text="@string/txt_powered_off"
android:textSize="@dimen/textSize12"
app:typeface="@string/roboto_regular_font" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_white_trigon" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_device_close_btn"
android:layout_width="@dimen/dp_16"
android:layout_height="@dimen/dp_16"
android:layout_gravity="end"
android:src="@drawable/ic_delete_easyy_photos"
android:tint="@color/gray_color3" />
</FrameLayout>

View File

@@ -18,6 +18,7 @@
<com.abbidot.tracker.widget.TypefaceTextView <com.abbidot.tracker.widget.TypefaceTextView
android:id="@+id/tv_pet_location_update_time"
style="@style/my_TextView_style_v2" style="@style/my_TextView_style_v2"
android:layout_below="@id/tv_pet_location_reverse_geocode" android:layout_below="@id/tv_pet_location_reverse_geocode"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"

View File

@@ -796,7 +796,7 @@
<string name="txt_hours">hours</string> <string name="txt_hours">hours</string>
<string name="txt_search_device">Searching…</string> <string name="txt_search_device">Searching…</string>
<string name="txt_no_search_device">Keep tracker on and nearby to scan.</string> <string name="txt_no_search_device">Keep tracker on and nearby to scan.</string>
<string name="txt_battery_less_than">Battery less than %s%%</string> <string name="txt_battery_less_than">Less than %s%%</string>
<string name="txt_outside">Outside</string> <string name="txt_outside">Outside</string>
<string name="txt_inside">Inside</string> <string name="txt_inside">Inside</string>
<string name="txt_7days_avg">7 Days Avg.</string> <string name="txt_7days_avg">7 Days Avg.</string>
@@ -1050,5 +1050,8 @@
<string name="txt_show_crash">The program has an exception and is about to exit</string> <string name="txt_show_crash">The program has an exception and is about to exit</string>
<string name="txt_activate_subscribe">Activate Subscription</string> <string name="txt_activate_subscribe">Activate Subscription</string>
<string name="txt_powered_off">Powered off</string>
<string name="txt_near">Near %s</string>
<string name="txt_charging">Charging</string>
</resources> </resources>

View File

@@ -42,6 +42,8 @@ class Utils {
const val DATE_FORMAT_PATTERN_EN8 = "hh:mm a" const val DATE_FORMAT_PATTERN_EN8 = "hh:mm a"
const val DATE_FORMAT_PATTERN_EN9 = "MMM d, yyyy hh:mm a" const val DATE_FORMAT_PATTERN_EN9 = "MMM d, yyyy hh:mm a"
const val DATE_FORMAT_PATTERN_EN10 = "dd/MM/yyyy HH:mm:ss" const val DATE_FORMAT_PATTERN_EN10 = "dd/MM/yyyy HH:mm:ss"
const val DATE_FORMAT_PATTERN_EN11 = "dd/MM HH:mm"
const val DATE_FORMAT_PATTERN_EN12 = "dd/MM HH:mm:ss"
//返回星期几 简写 //返回星期几 简写
const val WEEK_FORMAT_PATTERN = "E" const val WEEK_FORMAT_PATTERN = "E"