1.route页ui功能改版
@@ -1 +1 @@
|
|||||||
#Wed Apr 08 14:56:42 CST 2026
|
#Thu Apr 09 17:00:19 CST 2026
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ android {
|
|||||||
applicationId "com.abbidot.tracker"
|
applicationId "com.abbidot.tracker"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 35
|
targetSdkVersion 35
|
||||||
versionCode 2113
|
versionCode 2202
|
||||||
// versionName "2.1.13"
|
// versionName "2.2.2"
|
||||||
versionName "2.1.13-Beta3"
|
versionName "2.2.2-Beta1"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,6 @@
|
|||||||
android:protectionLevel="signature" /> <!-- Optional. Required for location feature -->
|
android:protectionLevel="signature" /> <!-- Optional. Required for location feature -->
|
||||||
<uses-permission android:name="${applicationId}.permission.JPUSH_MESSAGE" /> <!-- 为了提高sdk识别唯一用户的能力,保证消息推送的精准送达,建议集成以下权限(可选) -->
|
<uses-permission android:name="${applicationId}.permission.JPUSH_MESSAGE" /> <!-- 为了提高sdk识别唯一用户的能力,保证消息推送的精准送达,建议集成以下权限(可选) -->
|
||||||
<!-- <uses-permission -->
|
<!-- <uses-permission -->
|
||||||
<!-- android:name="android.permission.QUERY_ALL_PACKAGES" -->
|
|
||||||
<!-- tools:ignore="QueryAllPackagesPermission" /> -->
|
<!-- tools:ignore="QueryAllPackagesPermission" /> -->
|
||||||
<!-- 如您需要接入地理围栏业务,建议集成以下权限(可选) -->
|
<!-- 如您需要接入地理围栏业务,建议集成以下权限(可选) -->
|
||||||
<uses-permission android:name="android.permission.GET_TASKS" /> <!-- 如您需要对应设备通知相关的能力,建议集成以下权限(可选) -->
|
<uses-permission android:name="android.permission.GET_TASKS" /> <!-- 如您需要对应设备通知相关的能力,建议集成以下权限(可选) -->
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package com.abbidot.tracker.adapter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.text.format.DateUtils
|
||||||
|
import android.view.View
|
||||||
|
import com.abbidot.baselibrary.list.BaseRecyclerAdapter
|
||||||
|
import com.abbidot.baselibrary.list.RecyclerViewHolder
|
||||||
|
import com.abbidot.baselibrary.util.Utils
|
||||||
|
import com.abbidot.tracker.R
|
||||||
|
import com.abbidot.tracker.bean.MessageBean
|
||||||
|
import com.abbidot.tracker.constant.ConstantInt
|
||||||
|
|
||||||
|
/**
|
||||||
|
*Created by .yzq on 2026/4/10/周五.
|
||||||
|
* @link
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
class HistoryFenceAdapter(
|
||||||
|
ctx: Context, list: MutableList<MessageBean>?
|
||||||
|
) : BaseRecyclerAdapter<MessageBean>(ctx, list) {
|
||||||
|
override fun getEmptyLayoutId(viewType: Int) = 0
|
||||||
|
|
||||||
|
override fun getItemLayoutId(viewType: Int) = R.layout.item_history_fence_layout
|
||||||
|
|
||||||
|
override fun bindData(holder: RecyclerViewHolder?, position: Int, item: MessageBean) {
|
||||||
|
holder?.apply {
|
||||||
|
getImageView(R.id.iv_history_fence_type_image).let {
|
||||||
|
when (item.deviceMessageType) {
|
||||||
|
ConstantInt.Type1, ConstantInt.Type3 -> it.setImageResource(R.drawable.icon_history_danger_fence_image)
|
||||||
|
ConstantInt.Type2 -> it.setImageResource(R.drawable.icon_history_save_fence_image)
|
||||||
|
ConstantInt.Type4 -> it.setImageResource(R.drawable.icon_history_no_save_fence_image)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getTextView(R.id.tv_history_fence_type_time).text =
|
||||||
|
getRelativeTimeString(item.timeStamp)
|
||||||
|
getTextView(R.id.tv_history_fence_type_content).text = item.message
|
||||||
|
getImageView(R.id.iv_history_fence_type_line).let {
|
||||||
|
it.visibility = if (position == getData().size - 1) View.GONE
|
||||||
|
else View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getRelativeTimeString(timeStamp: Long): String {
|
||||||
|
val formatDateStr: String
|
||||||
|
val cTimeStamp = Utils.stringToTimestamp(
|
||||||
|
Utils.formatTime(
|
||||||
|
timeStamp, Utils.DATE_FORMAT_PATTERN_CN2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val now = System.currentTimeMillis()
|
||||||
|
formatDateStr = if (DateUtils.isToday(cTimeStamp)) {
|
||||||
|
mContext.getString(R.string.txt_today) + " " + Utils.formatTime(
|
||||||
|
timeStamp, Utils.DATE_FORMAT_PATTERN_EN14
|
||||||
|
)
|
||||||
|
} else if (now - cTimeStamp < (48 * 60 * 60 * 1000)) {
|
||||||
|
mContext.getString(R.string.txt_yesterday) + " " + Utils.formatTime(
|
||||||
|
timeStamp, Utils.DATE_FORMAT_PATTERN_EN14
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Utils.formatTime(
|
||||||
|
timeStamp, Utils.DATE_FORMAT_PATTERN_EN15
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return formatDateStr
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,7 +58,7 @@ class NotificationV2Adapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getRelativeTimeString(timeStamp: Long): String {
|
private fun getRelativeTimeString(timeStamp: Long): String {
|
||||||
var formatDateStr = ""
|
val formatDateStr: String
|
||||||
val cTimeStamp = Utils.stringToTimestamp(
|
val cTimeStamp = Utils.stringToTimestamp(
|
||||||
Utils.formatTime(
|
Utils.formatTime(
|
||||||
timeStamp, Utils.DATE_FORMAT_PATTERN_CN2
|
timeStamp, Utils.DATE_FORMAT_PATTERN_CN2
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.abbidot.tracker.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by .yzq on 2026/4/13/周一.
|
||||||
|
*
|
||||||
|
* @link
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
public class TopSlideLayoutManager extends LinearLayoutManager {
|
||||||
|
private int mTopOffset;
|
||||||
|
|
||||||
|
public TopSlideLayoutManager(Context context, int orientation, boolean reverseLayout) {
|
||||||
|
super(context, orientation, reverseLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTopOffset(int topOffset) {
|
||||||
|
mTopOffset = topOffset;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||||
|
super.onLayoutChildren(recycler, state);
|
||||||
|
// 可以在这里调整子项的位置,例如将顶部几个项上移
|
||||||
|
if (getChildCount() > 0) {
|
||||||
|
View firstChild = getChildAt(0);
|
||||||
|
if (firstChild != null) {
|
||||||
|
int top = getDecoratedTop(firstChild) - mTopOffset;
|
||||||
|
layoutDecoratedWithMargins(firstChild, firstChild.getLeft(), top, firstChild.getRight(), top + firstChild.getHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ import java.util.Calendar
|
|||||||
class ShowCalenderAndTimeDialog(
|
class ShowCalenderAndTimeDialog(
|
||||||
context: Context,
|
context: Context,
|
||||||
showCalenderTextView: TextView,
|
showCalenderTextView: TextView,
|
||||||
okListener: OnDialogOkListener? = null,
|
okListener: OnDialogSelectListener? = null,
|
||||||
format: String = Utils.DATE_FORMAT_PATTERN_EN1,
|
format: String = Utils.DATE_FORMAT_PATTERN_EN1,
|
||||||
canSelectFutureDate: Boolean = false,
|
canSelectFutureDate: Boolean = false,
|
||||||
calenderShowTimestamp: Long = 0,
|
calenderShowTimestamp: Long = 0,
|
||||||
@@ -86,7 +86,7 @@ class ShowCalenderAndTimeDialog(
|
|||||||
0,
|
0,
|
||||||
23,
|
23,
|
||||||
5,
|
5,
|
||||||
24,
|
16,
|
||||||
NumberPickerValueFill0Format(),
|
NumberPickerValueFill0Format(),
|
||||||
this@ShowCalenderAndTimeDialog
|
this@ShowCalenderAndTimeDialog
|
||||||
)
|
)
|
||||||
@@ -98,7 +98,7 @@ class ShowCalenderAndTimeDialog(
|
|||||||
0,
|
0,
|
||||||
59,
|
59,
|
||||||
5,
|
5,
|
||||||
24,
|
16,
|
||||||
NumberPickerValueFill0Format(),
|
NumberPickerValueFill0Format(),
|
||||||
this@ShowCalenderAndTimeDialog
|
this@ShowCalenderAndTimeDialog
|
||||||
)
|
)
|
||||||
@@ -172,16 +172,18 @@ class ShowCalenderAndTimeDialog(
|
|||||||
}:${Utils.fill2Digits(npDialogCalenderMin.value)}:00"
|
}:${Utils.fill2Digits(npDialogCalenderMin.value)}:00"
|
||||||
val timesTamp = Utils.stringToTimestamp(selectMonthYear)
|
val timesTamp = Utils.stringToTimestamp(selectMonthYear)
|
||||||
val nowTimestamp = System.currentTimeMillis()
|
val nowTimestamp = System.currentTimeMillis()
|
||||||
|
|
||||||
if (timesTamp > nowTimestamp) {
|
if (timesTamp > nowTimestamp) {
|
||||||
//时间戳还原
|
//时间戳还原
|
||||||
setSelectDate(nowTimestamp)
|
setSelectDate(nowTimestamp)
|
||||||
mShowCalenderTextView.text = Utils.formatTime(nowTimestamp, mDateFormat)
|
mShowCalenderTextView.text = Utils.formatTime(nowTimestamp, mDateFormat)
|
||||||
|
mOkListener?.onSelectClick(this@ShowCalenderAndTimeDialog, nowTimestamp)
|
||||||
} else {
|
} else {
|
||||||
mShowCalenderTextView.text = Utils.stringToDate(
|
mShowCalenderTextView.text = Utils.stringToDate(
|
||||||
selectMonthYear, Utils.DATE_FORMAT_PATTERN_CN2, mDateFormat
|
selectMonthYear, Utils.DATE_FORMAT_PATTERN_CN2, mDateFormat
|
||||||
)
|
)
|
||||||
|
mOkListener?.onSelectClick(this@ShowCalenderAndTimeDialog, timesTamp)
|
||||||
}
|
}
|
||||||
mOkListener?.onOkClick(this@ShowCalenderAndTimeDialog)
|
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -837,6 +837,16 @@ interface INetworkService {
|
|||||||
@Query("toTime") toTime: Long
|
@Query("toTime") toTime: Long
|
||||||
): BaseResponse<MutableList<HistoryDataBean>>
|
): BaseResponse<MutableList<HistoryDataBean>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取设备进出围栏历史数据
|
||||||
|
*/
|
||||||
|
@GET("data/getHistoryInOutFenceList")
|
||||||
|
suspend fun getHistoryFenceList(
|
||||||
|
@Query("deviceId") deviceId: String,
|
||||||
|
@Query("beginTimeStamp") fromTime: Long,
|
||||||
|
@Query("endTimeStamp") toTime: Long
|
||||||
|
): BaseResponse<MutableList<MessageBean>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置运动目标
|
* 设置运动目标
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -753,6 +753,13 @@ object NetworkApi : BaseNetworkApi<INetworkService>(INetworkService.BASE_URL) {
|
|||||||
service.getHistoryByDay(deviceId, fromTime, toTime)
|
service.getHistoryByDay(deviceId, fromTime, toTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取设备进出围栏历史数据
|
||||||
|
*/
|
||||||
|
suspend fun getHistoryFenceList(deviceId: String, fromTime: Long, toTime: Long) = getResult {
|
||||||
|
service.getHistoryFenceList(deviceId, fromTime, toTime)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置运动目标
|
* 设置运动目标
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ import com.abbidot.tracker.ui.activity.device.AddNewTracker1Activity
|
|||||||
import com.abbidot.tracker.ui.activity.device.MyTrackerV2Activity
|
import com.abbidot.tracker.ui.activity.device.MyTrackerV2Activity
|
||||||
import com.abbidot.tracker.ui.fragment.account.AccountV2Fragment
|
import com.abbidot.tracker.ui.fragment.account.AccountV2Fragment
|
||||||
import com.abbidot.tracker.ui.fragment.data.ActivityV2Fragment
|
import com.abbidot.tracker.ui.fragment.data.ActivityV2Fragment
|
||||||
import com.abbidot.tracker.ui.fragment.data.RouteV2Fragment
|
import com.abbidot.tracker.ui.fragment.data.RouteV3Fragment
|
||||||
import com.abbidot.tracker.ui.fragment.map.MapV3Fragment
|
import com.abbidot.tracker.ui.fragment.map.MapV3Fragment
|
||||||
import com.abbidot.tracker.ui.fragment.pet.PetV2Fragment
|
import com.abbidot.tracker.ui.fragment.pet.PetV2Fragment
|
||||||
import com.abbidot.tracker.util.SocketUtilManage
|
import com.abbidot.tracker.util.SocketUtilManage
|
||||||
@@ -111,7 +111,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
|||||||
|
|
||||||
private val mFragments = mutableListOf<Fragment>(
|
private val mFragments = mutableListOf<Fragment>(
|
||||||
ActivityV2Fragment.newInstance(this),
|
ActivityV2Fragment.newInstance(this),
|
||||||
RouteV2Fragment.newInstance(this),
|
RouteV3Fragment.newInstance(this),
|
||||||
MapV3Fragment.newInstance(this),
|
MapV3Fragment.newInstance(this),
|
||||||
PetV2Fragment.newInstance(this),
|
PetV2Fragment.newInstance(this),
|
||||||
AccountV2Fragment.newInstance(this)
|
AccountV2Fragment.newInstance(this)
|
||||||
@@ -460,7 +460,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
|||||||
onChangeClick(mSelectPetPosition)
|
onChangeClick(mSelectPetPosition)
|
||||||
when (mViewBinding.homeV2ViewPager2.currentItem) {
|
when (mViewBinding.homeV2ViewPager2.currentItem) {
|
||||||
0 -> {
|
0 -> {
|
||||||
(mFragments[1] as RouteV2Fragment).setNeedUpdateTag()
|
(mFragments[1] as RouteV3Fragment).setNeedUpdateTag()
|
||||||
(mFragments[3] as PetV2Fragment).setNeedUpdateTag()
|
(mFragments[3] as PetV2Fragment).setNeedUpdateTag()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,13 +471,13 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
|||||||
|
|
||||||
2, 4 -> {
|
2, 4 -> {
|
||||||
(mFragments[0] as ActivityV2Fragment).setNeedUpdateTag()
|
(mFragments[0] as ActivityV2Fragment).setNeedUpdateTag()
|
||||||
(mFragments[1] as RouteV2Fragment).setNeedUpdateTag()
|
(mFragments[1] as RouteV3Fragment).setNeedUpdateTag()
|
||||||
(mFragments[3] as PetV2Fragment).setNeedUpdateTag()
|
(mFragments[3] as PetV2Fragment).setNeedUpdateTag()
|
||||||
}
|
}
|
||||||
|
|
||||||
3 -> {
|
3 -> {
|
||||||
(mFragments[0] as ActivityV2Fragment).setNeedUpdateTag()
|
(mFragments[0] as ActivityV2Fragment).setNeedUpdateTag()
|
||||||
(mFragments[1] as RouteV2Fragment).setNeedUpdateTag()
|
(mFragments[1] as RouteV3Fragment).setNeedUpdateTag()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -638,7 +638,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
|||||||
fun refreshLocationBtnState() {
|
fun refreshLocationBtnState() {
|
||||||
when (mViewBinding.homeV2ViewPager2.currentItem) {
|
when (mViewBinding.homeV2ViewPager2.currentItem) {
|
||||||
0 -> (mFragments[0] as ActivityV2Fragment).checkNotifyLocationState()
|
0 -> (mFragments[0] as ActivityV2Fragment).checkNotifyLocationState()
|
||||||
1 -> (mFragments[1] as RouteV2Fragment).checkNotifyLocationState()
|
1 -> (mFragments[1] as RouteV3Fragment).checkNotifyLocationState()
|
||||||
3 -> (mFragments[3] as PetV2Fragment).checkNotifyLocationState()
|
3 -> (mFragments[3] as PetV2Fragment).checkNotifyLocationState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -654,7 +654,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
|||||||
mChangePetListDialogAdapter.setSelectPetPos(mSelectPetPosition)
|
mChangePetListDialogAdapter.setSelectPetPos(mSelectPetPosition)
|
||||||
when (mViewBinding.homeV2ViewPager2.currentItem) {
|
when (mViewBinding.homeV2ViewPager2.currentItem) {
|
||||||
0 -> (mFragments[0] as ActivityV2Fragment).showPetNameAndHead(position)
|
0 -> (mFragments[0] as ActivityV2Fragment).showPetNameAndHead(position)
|
||||||
1 -> (mFragments[1] as RouteV2Fragment).showPetNameAndHead(position)
|
1 -> (mFragments[1] as RouteV3Fragment).showPetNameAndHead(position)
|
||||||
2 -> (mFragments[2] as MapV3Fragment).showPetNameAndHead(position)
|
2 -> (mFragments[2] as MapV3Fragment).showPetNameAndHead(position)
|
||||||
3 -> (mFragments[3] as PetV2Fragment).showPetNameAndHead(position)
|
3 -> (mFragments[3] as PetV2Fragment).showPetNameAndHead(position)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.abbidot.tracker.ui.common.map
|
package com.abbidot.tracker.ui.common.map
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.appcompat.widget.AppCompatSeekBar
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.abbidot.baselibrary.util.AppUtils
|
import com.abbidot.baselibrary.util.AppUtils
|
||||||
|
import com.abbidot.baselibrary.util.LogUtil
|
||||||
import com.abbidot.tracker.base.BaseMapCommon
|
import com.abbidot.tracker.base.BaseMapCommon
|
||||||
import com.abbidot.tracker.bean.HistoryDataBean
|
import com.abbidot.tracker.bean.HistoryDataBean
|
||||||
import com.abbidot.tracker.bean.PetBean
|
import com.abbidot.tracker.bean.PetBean
|
||||||
@@ -10,7 +12,6 @@ import com.abbidot.tracker.ui.fragment.map.baidumap.HistoryDataBaiduMapFragment
|
|||||||
import com.abbidot.tracker.ui.fragment.map.googlemap.HistoryDataGoogleMapFragment
|
import com.abbidot.tracker.ui.fragment.map.googlemap.HistoryDataGoogleMapFragment
|
||||||
import com.abbidot.tracker.vm.GeoCoderViewModel
|
import com.abbidot.tracker.vm.GeoCoderViewModel
|
||||||
import com.abbidot.tracker.widget.MapMarkerInfoView
|
import com.abbidot.tracker.widget.MapMarkerInfoView
|
||||||
import com.abbidot.tracker.widget.VerticalTopToBottomSeekBar
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Created by .yzq on 2022/7/5/005.
|
*Created by .yzq on 2022/7/5/005.
|
||||||
@@ -26,7 +27,7 @@ class HistoryDataMapCommon : BaseMapCommon() {
|
|||||||
context: Context,
|
context: Context,
|
||||||
markerInfoView: MapMarkerInfoView,
|
markerInfoView: MapMarkerInfoView,
|
||||||
geoCoderViewModel: GeoCoderViewModel,
|
geoCoderViewModel: GeoCoderViewModel,
|
||||||
verticalTopToBottomSeekBar: VerticalTopToBottomSeekBar,
|
verticalTopToBottomSeekBar: AppCompatSeekBar,
|
||||||
mapLoadOk: () -> Unit
|
mapLoadOk: () -> Unit
|
||||||
): Fragment {
|
): Fragment {
|
||||||
return if (AppUtils.isChina(AppUtils.SWITCH_MAP_TYPE)) {
|
return if (AppUtils.isChina(AppUtils.SWITCH_MAP_TYPE)) {
|
||||||
@@ -102,11 +103,16 @@ class HistoryDataMapCommon : BaseMapCommon() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setLatLngData(data: MutableList<HistoryDataBean>) {
|
fun setLatLngData(data: MutableList<HistoryDataBean>) {
|
||||||
|
if (data.size == 0) return
|
||||||
|
try {
|
||||||
if (null != mHistoryDataBaiduMapFragment) {
|
if (null != mHistoryDataBaiduMapFragment) {
|
||||||
mHistoryDataBaiduMapFragment!!.setLatLngData(data)
|
mHistoryDataBaiduMapFragment!!.setLatLngData(data)
|
||||||
} else if (null != mHistoryDataGoogleMapFragment) {
|
} else if (null != mHistoryDataGoogleMapFragment) {
|
||||||
mHistoryDataGoogleMapFragment!!.setLatLngData(data)
|
mHistoryDataGoogleMapFragment!!.setLatLngData(data)
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LogUtil.e("setLatLngData异常:${e.message}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showInfoWindow(historyDataBean: HistoryDataBean) {
|
fun showInfoWindow(historyDataBean: HistoryDataBean) {
|
||||||
@@ -117,6 +123,10 @@ class HistoryDataMapCommon : BaseMapCommon() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun resetMarkerInfoViewOffset() {
|
||||||
|
mHistoryDataGoogleMapFragment?.resetMarkerInfoViewOffset()
|
||||||
|
}
|
||||||
|
|
||||||
fun setPetUserLatLng() {
|
fun setPetUserLatLng() {
|
||||||
if (null != mHistoryDataBaiduMapFragment) {
|
if (null != mHistoryDataBaiduMapFragment) {
|
||||||
} else if (null != mHistoryDataGoogleMapFragment) {
|
} else if (null != mHistoryDataGoogleMapFragment) {
|
||||||
|
|||||||
@@ -449,8 +449,8 @@ class RouteV2Fragment : BaseFragment<FragmentRouteV2Binding>(FragmentRouteV2Bind
|
|||||||
mFromCalenderDialog = ShowCalenderAndTimeDialog(
|
mFromCalenderDialog = ShowCalenderAndTimeDialog(
|
||||||
mContext!!,
|
mContext!!,
|
||||||
tvHomeRouteCalendarFrom,
|
tvHomeRouteCalendarFrom,
|
||||||
object : BaseDialog.OnDialogOkListener {
|
object : BaseDialog.OnDialogSelectListener {
|
||||||
override fun onOkClick(dialog: BaseDialog<*>) {
|
override fun onSelectClick(dialog: BaseDialog<*>, any: Any) {
|
||||||
mCurrentTimestamp = System.currentTimeMillis()
|
mCurrentTimestamp = System.currentTimeMillis()
|
||||||
isSelectCustomDate = true
|
isSelectCustomDate = true
|
||||||
getHistoryDay(tvHomeRouteCalendarFrom)
|
getHistoryDay(tvHomeRouteCalendarFrom)
|
||||||
@@ -477,8 +477,8 @@ class RouteV2Fragment : BaseFragment<FragmentRouteV2Binding>(FragmentRouteV2Bind
|
|||||||
mToCalenderDialog = ShowCalenderAndTimeDialog(
|
mToCalenderDialog = ShowCalenderAndTimeDialog(
|
||||||
mContext!!,
|
mContext!!,
|
||||||
tvHomeRouteCalendarTo,
|
tvHomeRouteCalendarTo,
|
||||||
object : BaseDialog.OnDialogOkListener {
|
object : BaseDialog.OnDialogSelectListener {
|
||||||
override fun onOkClick(dialog: BaseDialog<*>) {
|
override fun onSelectClick(dialog: BaseDialog<*>, any: Any) {
|
||||||
isSelectCustomDate = true
|
isSelectCustomDate = true
|
||||||
getHistoryDay(tvHomeRouteCalendarTo)
|
getHistoryDay(tvHomeRouteCalendarTo)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,648 @@
|
|||||||
|
package com.abbidot.tracker.ui.fragment.data
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.SeekBar
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.commit
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.abbidot.baselibrary.constant.EventName
|
||||||
|
import com.abbidot.baselibrary.eventbus.XEventBus
|
||||||
|
import com.abbidot.baselibrary.util.AppUtils
|
||||||
|
import com.abbidot.baselibrary.util.LogUtil
|
||||||
|
import com.abbidot.baselibrary.util.Utils
|
||||||
|
import com.abbidot.tracker.R
|
||||||
|
import com.abbidot.tracker.adapter.HistoryFenceAdapter
|
||||||
|
import com.abbidot.tracker.base.BaseDialog
|
||||||
|
import com.abbidot.tracker.base.BaseFragment
|
||||||
|
import com.abbidot.tracker.bean.HistoryDataBean
|
||||||
|
import com.abbidot.tracker.bean.MessageBean
|
||||||
|
import com.abbidot.tracker.constant.ConstantInt
|
||||||
|
import com.abbidot.tracker.constant.GetResultCallback
|
||||||
|
import com.abbidot.tracker.databinding.FragmentRouteV3Binding
|
||||||
|
import com.abbidot.tracker.dialog.ShowCalenderAndTimeDialog
|
||||||
|
import com.abbidot.tracker.ui.activity.HomeV2Activity
|
||||||
|
import com.abbidot.tracker.ui.common.map.HistoryDataMapCommon
|
||||||
|
import com.abbidot.tracker.util.Util
|
||||||
|
import com.abbidot.tracker.util.ViewUtil
|
||||||
|
import com.abbidot.tracker.vm.DataDetailViewModel
|
||||||
|
import com.abbidot.tracker.vm.GeoCoderViewModel
|
||||||
|
import com.abbidot.tracker.widget.NoClickSlideSeekBar
|
||||||
|
import com.abbidot.tracker.widget.TypefaceTextView
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首页轨迹
|
||||||
|
* create an instance of this fragment.
|
||||||
|
*/
|
||||||
|
class RouteV3Fragment : BaseFragment<FragmentRouteV3Binding>(FragmentRouteV3Binding::inflate) {
|
||||||
|
|
||||||
|
private val mDataDetailViewModel: DataDetailViewModel by viewModels()
|
||||||
|
private val mGeoCoderViewModel: GeoCoderViewModel by viewModels()
|
||||||
|
|
||||||
|
private lateinit var mFragment: Fragment
|
||||||
|
|
||||||
|
private var mFromCalenderDialog: ShowCalenderAndTimeDialog? = null
|
||||||
|
private var mToCalenderDialog: ShowCalenderAndTimeDialog? = null
|
||||||
|
|
||||||
|
//当前这个页面显示的宠物下标
|
||||||
|
private var mCurrentShowPetPos = -1
|
||||||
|
|
||||||
|
//最多只能选择多少天的历史记录
|
||||||
|
private val mOnlySelectDay = 7L
|
||||||
|
|
||||||
|
//当前的时间戳
|
||||||
|
private var mCurrentTimestamp = 0L
|
||||||
|
private var mFromTimestamp = 0L
|
||||||
|
private var mToTimestamp = 0L
|
||||||
|
|
||||||
|
//方便保存地理反编译信息
|
||||||
|
private var mHistoryDataList = mutableListOf<HistoryDataBean>()
|
||||||
|
private val mHistoryDataMapCommon = HistoryDataMapCommon()
|
||||||
|
|
||||||
|
//是否选过自定义日期,没有则再次回到这个页面,刷新取24小时的记录
|
||||||
|
private var isSelectCustomDate = false
|
||||||
|
|
||||||
|
// private var isFirst = true
|
||||||
|
private var mProgress = 0
|
||||||
|
|
||||||
|
//原来有列表一个元素的高度
|
||||||
|
private var mLastScrollViewHeight = 0
|
||||||
|
|
||||||
|
private var mTotalHeight = 0
|
||||||
|
|
||||||
|
private lateinit var mHistoryFenceAdapter: HistoryFenceAdapter
|
||||||
|
private val mAllHistoryFenceList = mutableListOf<MessageBean>()
|
||||||
|
|
||||||
|
//充值续费或升级返回类型
|
||||||
|
private var mRechargeBackType = ConstantInt.SpecialType
|
||||||
|
|
||||||
|
//列表是否展开
|
||||||
|
private var isListExpand = false
|
||||||
|
|
||||||
|
//判断是否滑过
|
||||||
|
private var isHaveSlide = false
|
||||||
|
private var mLastY = 0f
|
||||||
|
private var mDiffHeight = 0
|
||||||
|
|
||||||
|
//是否上滑
|
||||||
|
private var isSlideUp = false
|
||||||
|
|
||||||
|
// private lateinit var mTopSlideLayoutManager: TopSlideLayoutManager
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun newInstance(context: Context) = RouteV3Fragment().apply {
|
||||||
|
mContext = context
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
override fun initData() {
|
||||||
|
mViewBinding.apply {
|
||||||
|
getHomeV2Activity()?.edgeToEdgeAdapterBars(
|
||||||
|
root, WindowInsetsCompat.Type.statusBars()
|
||||||
|
)
|
||||||
|
mFragment = mHistoryDataMapCommon.getMapFragment(
|
||||||
|
mContext!!, miHomeRouteAddressViewV3, mGeoCoderViewModel, vsbMapRouteLineV3
|
||||||
|
) {
|
||||||
|
mapLoadOk()
|
||||||
|
}
|
||||||
|
|
||||||
|
mHistoryFenceAdapter = HistoryFenceAdapter(mContext!!, null)
|
||||||
|
ViewUtil.instance.setRecyclerViewVerticalLinearLayout(
|
||||||
|
mContext!!, rvMapRouteLineV3FencesList, mHistoryFenceAdapter
|
||||||
|
)
|
||||||
|
// rvMapRouteLineV3FencesList.let {
|
||||||
|
// mTopSlideLayoutManager = TopSlideLayoutManager(
|
||||||
|
// mContext!!, LinearLayoutManager.VERTICAL, false
|
||||||
|
// )
|
||||||
|
// it.layoutManager = mTopSlideLayoutManager
|
||||||
|
// it.adapter = mHistoryFenceAdapter
|
||||||
|
// }
|
||||||
|
|
||||||
|
ilHomeRoutePetHeadV3.ivTopPetBtnSmall.visibility = View.GONE
|
||||||
|
//设置不可点击状态
|
||||||
|
vsbMapRouteLineV3.setStatus(NoClickSlideSeekBar.STATUS.STATUS_SLIDE)
|
||||||
|
|
||||||
|
setOnClickListenerViews(
|
||||||
|
llHomeRouteCalendarFromV3,
|
||||||
|
llHomeRouteCalendarToV3,
|
||||||
|
ilHomeRoutePetHeadV3.homeDataPetHeadSmall.root,
|
||||||
|
ilHomeRoutePetHeadV3.homeDataPetNameSmall,
|
||||||
|
ivHomeRouteMapTypeBtnV3,
|
||||||
|
ivMapRouteLineV3LastBtn,
|
||||||
|
ivMapRouteLineV3NextBtn
|
||||||
|
)
|
||||||
|
|
||||||
|
llMapRouteLineV3ZoomingLayout.setOnTouchListener { _, event ->
|
||||||
|
if (rlMapRouteLineV3TimeLayout.isVisible) {
|
||||||
|
if (mLastScrollViewHeight == 0) {
|
||||||
|
mTotalHeight = cvHomeRouteV3Card.height + svHomeRouteMapScroll.height
|
||||||
|
mLastScrollViewHeight = svHomeRouteMapScroll.height
|
||||||
|
}
|
||||||
|
|
||||||
|
when (event.action) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
LogUtil.e("ACTION_DOWN")
|
||||||
|
mLastY = event.rawY
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionEvent.ACTION_MOVE -> {
|
||||||
|
val dy = mLastY - event.rawY
|
||||||
|
val layoutParams = svHomeRouteMapScroll.layoutParams
|
||||||
|
val diff = (svHomeRouteMapScroll.height + dy).toInt()
|
||||||
|
isSlideUp = dy >= 0.0f
|
||||||
|
if (diff > mLastScrollViewHeight) {
|
||||||
|
isHaveSlide = true
|
||||||
|
if (mHistoryFenceAdapter.getData().size != mAllHistoryFenceList.size) {
|
||||||
|
mHistoryFenceAdapter.setData(mAllHistoryFenceList, true)
|
||||||
|
}
|
||||||
|
mDiffHeight = diff
|
||||||
|
layoutParams.height = diff
|
||||||
|
svHomeRouteMapScroll.layoutParams = layoutParams
|
||||||
|
mLastY = event.rawY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionEvent.ACTION_UP -> {
|
||||||
|
LogUtil.e("ACTION_UP")
|
||||||
|
val layoutParams = svHomeRouteMapScroll.layoutParams
|
||||||
|
if (mDiffHeight > mTotalHeight / 2) {
|
||||||
|
setSeekBarShowHide(false)
|
||||||
|
layoutParams.height = mTotalHeight
|
||||||
|
svHomeRouteMapScroll.layoutParams = layoutParams
|
||||||
|
isListExpand = true
|
||||||
|
} else {
|
||||||
|
svHomeRouteMapScroll.postDelayed(
|
||||||
|
{ mHistoryDataMapCommon.setLatLngData(mHistoryDataList) }, 200
|
||||||
|
)
|
||||||
|
if (mDiffHeight > mLastScrollViewHeight) {
|
||||||
|
layoutParams.height = if (isSlideUp) {
|
||||||
|
isListExpand = true
|
||||||
|
setSeekBarShowHide(false)
|
||||||
|
mTotalHeight / 2
|
||||||
|
} else {
|
||||||
|
isListExpand = false
|
||||||
|
setSeekBarShowHide(true)
|
||||||
|
if (mHistoryFenceAdapter.getData().size > 1) {
|
||||||
|
mHistoryFenceAdapter.setData(
|
||||||
|
mAllHistoryFenceList.subList(
|
||||||
|
0, 1
|
||||||
|
), true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
mLastScrollViewHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
svHomeRouteMapScroll.layoutParams = layoutParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AppUtils.isDebug()) {
|
||||||
|
ilHomeRoutePetHeadV3.homeDataPetHeadSmall.root.setOnLongClickListener {
|
||||||
|
getHomeV2Activity()?.goToDebugActivity()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//解决报错java.lang.IllegalArgumentException
|
||||||
|
//No view found for id 0x7f090254 (com.abbidot.tracker:id/fc_home_route_fragment) for fragment HomeMapGoogleMapFragment
|
||||||
|
//https://www.jianshu.com/p/9235092f407a
|
||||||
|
childFragmentManager.commit {
|
||||||
|
add(R.id.fc_home_route_fragment_v3, mFragment)
|
||||||
|
}
|
||||||
|
|
||||||
|
initEven()
|
||||||
|
initState()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getHomeV2Activity(): HomeV2Activity? {
|
||||||
|
return if (null == activity) {
|
||||||
|
LogUtil.e("RouteV2Fragment,getHomeV2Activity,null == activity")
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
activity as HomeV2Activity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一开始获取24小时内的数据
|
||||||
|
*/
|
||||||
|
private fun get24HourTime() {
|
||||||
|
mCurrentTimestamp = System.currentTimeMillis()
|
||||||
|
mViewBinding.apply {
|
||||||
|
mFromTimestamp = Utils.getBeforeHowTimestamp(mCurrentTimestamp, 1)
|
||||||
|
mToTimestamp = mCurrentTimestamp
|
||||||
|
tvHomeRouteCalendarToV3.text =
|
||||||
|
Utils.formatTime(mToTimestamp, Utils.DATE_FORMAT_PATTERN_EN13)
|
||||||
|
tvHomeRouteCalendarFromV3.text =
|
||||||
|
Utils.formatTime(mFromTimestamp, Utils.DATE_FORMAT_PATTERN_EN13)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun initState() {
|
||||||
|
mViewBinding.miHomeRouteAddressViewV3.visibility = View.GONE
|
||||||
|
mHistoryDataMapCommon.clearAllMarker()
|
||||||
|
setSeekBarMax(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initEven() {
|
||||||
|
mViewBinding.vsbMapRouteLineV3.setOnSeekBarChangeListener(object :
|
||||||
|
SeekBar.OnSeekBarChangeListener {
|
||||||
|
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||||
|
if (mProgress == progress) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mProgress = progress
|
||||||
|
mViewBinding.miHomeRouteAddressViewV3.visibility = View.GONE
|
||||||
|
mHistoryDataMapCommon.slideChanged(progress)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartTrackingTouch(seekBar: SeekBar) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||||
|
mHistoryDataMapCommon.slideStopChanged(seekBar.progress)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
//续费成功后,不执行
|
||||||
|
if (mRechargeBackType == ConstantInt.Type1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
getHomeV2Activity()?.apply {
|
||||||
|
if (mCurrentShowPetPos == mSelectPetPosition) {
|
||||||
|
if (!isSelectCustomDate) {
|
||||||
|
if (mHistoryDataMapCommon.isMapLoadOk()) {
|
||||||
|
get24HourTime()
|
||||||
|
getHistoryDay(mViewBinding.tvHomeRouteCalendarFromV3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//其他页面是否选择了宠物
|
||||||
|
if (!isSelectCustomDate) get24HourTime()
|
||||||
|
showPetNameAndHead(mSelectPetPosition)
|
||||||
|
}
|
||||||
|
checkNotifyLocationState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkNotifyLocationState() {
|
||||||
|
getHomeV2Activity()?.apply {
|
||||||
|
checkNotifyRefreshLocation(mViewBinding.ilHomeRoutePetHeadV3.homeDataPetNameSmall)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun liveDataObserve() {
|
||||||
|
//更新套餐数据
|
||||||
|
XEventBus.observe(this, EventName.RefreshPackage) {
|
||||||
|
//监听续费成功
|
||||||
|
if (mRechargeBackType == ConstantInt.Type0) {
|
||||||
|
mRechargeBackType = ConstantInt.Type1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mDataDetailViewModel.apply {
|
||||||
|
mHistoryDetailLive.observe(this@RouteV3Fragment) {
|
||||||
|
dealRequestResult(it, object : GetResultCallback {
|
||||||
|
override fun onResult(any: Any) {
|
||||||
|
val data = it.getOrNull()!!
|
||||||
|
setLatLngData(data)
|
||||||
|
getHomeV2Activity()?.let { a ->
|
||||||
|
a.getPet(false)?.let { p ->
|
||||||
|
mAllHistoryFenceList.clear()
|
||||||
|
getHistoryFenceList(
|
||||||
|
a, p.deviceId, mFromTimestamp / 1000, mToTimestamp / 1000
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequestError(exceptionCode: String?) {
|
||||||
|
setSeekBarShowHide(false)
|
||||||
|
}
|
||||||
|
}, isShowNoDataTip = false)
|
||||||
|
}
|
||||||
|
mHistoryFenceEvents.observe(this@RouteV3Fragment) {
|
||||||
|
dealRequestResult(it, object : GetResultCallback {
|
||||||
|
override fun onResult(any: Any) {
|
||||||
|
it.getOrNull()?.let { d ->
|
||||||
|
if (d.size > 0) {
|
||||||
|
mViewBinding.rlMapRouteLineV3TimeLayout.visibility = View.VISIBLE
|
||||||
|
mAllHistoryFenceList.addAll(d)
|
||||||
|
if (isListExpand) {
|
||||||
|
mHistoryFenceAdapter.setData(
|
||||||
|
mAllHistoryFenceList, true
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
mHistoryFenceAdapter.setData(
|
||||||
|
mAllHistoryFenceList.subList(0, 1), true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (isHaveSlide) {
|
||||||
|
//判断滑过,从无数据到有数据布局错乱
|
||||||
|
val layoutParams =
|
||||||
|
mViewBinding.svHomeRouteMapScroll.layoutParams
|
||||||
|
if (layoutParams.height < mLastScrollViewHeight) {
|
||||||
|
layoutParams.height = mLastScrollViewHeight
|
||||||
|
mViewBinding.svHomeRouteMapScroll.layoutParams =
|
||||||
|
layoutParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mViewBinding.rlMapRouteLineV3TimeLayout.visibility = View.GONE
|
||||||
|
val lastScrollViewNoListHeight =
|
||||||
|
mViewBinding.rlHomeRouteCalendarV3Layout.height
|
||||||
|
if (isHaveSlide) {
|
||||||
|
val layoutParams =
|
||||||
|
mViewBinding.svHomeRouteMapScroll.layoutParams
|
||||||
|
layoutParams.height = lastScrollViewNoListHeight
|
||||||
|
mViewBinding.svHomeRouteMapScroll.layoutParams = layoutParams
|
||||||
|
}
|
||||||
|
isListExpand = false
|
||||||
|
}
|
||||||
|
if (mViewBinding.cvHomeRouteV3Card.height > 0) mViewBinding.svHomeRouteMapScroll.postDelayed(
|
||||||
|
{ mHistoryDataMapCommon.setLatLngData(mHistoryDataList) }, 200
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, isShowNoDataTip = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//地理反编译成功返回
|
||||||
|
mGeoCoderViewModel.mLatLonAddressLiveData.observe(this) {
|
||||||
|
val position = mViewBinding.vsbMapRouteLineV3.progress
|
||||||
|
if (mHistoryDataList.size <= position) return@observe
|
||||||
|
mHistoryDataList[position].apply {
|
||||||
|
//详细位置
|
||||||
|
address = it
|
||||||
|
val timeString = Utils.formatTime(timeStamp * 1000, Utils.DATE_FORMAT_PATTERN_EN10)
|
||||||
|
//更新位置时间
|
||||||
|
dayTime = timeString
|
||||||
|
mViewBinding.root.postDelayed(
|
||||||
|
{
|
||||||
|
mViewBinding.miHomeRouteAddressViewV3.let { mi ->
|
||||||
|
mi.visibility = View.VISIBLE
|
||||||
|
mi.setShowText(timeString, it)
|
||||||
|
}
|
||||||
|
}, 100
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地图加载好了
|
||||||
|
*/
|
||||||
|
private fun mapLoadOk() {
|
||||||
|
if (mCurrentShowPetPos == -1) return
|
||||||
|
getHomeV2Activity()?.apply {
|
||||||
|
showPetNameAndHead(mSelectPetPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置需要更新的标识
|
||||||
|
*/
|
||||||
|
fun setNeedUpdateTag() {
|
||||||
|
mCurrentShowPetPos = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示选择的宠物
|
||||||
|
*/
|
||||||
|
fun showPetNameAndHead(position: Int) {
|
||||||
|
getHomeV2Activity()?.apply {
|
||||||
|
if (mPetList.size == 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mCurrentShowPetPos = position
|
||||||
|
|
||||||
|
ViewUtil.instance.selectPetDialogShow(
|
||||||
|
mContext,
|
||||||
|
mPetList,
|
||||||
|
position,
|
||||||
|
mViewBinding.ilHomeRoutePetHeadV3.homeDataPetNameSmall,
|
||||||
|
mViewBinding.ilHomeRoutePetHeadV3.homeDataPetHeadSmall.appHeadImage
|
||||||
|
)
|
||||||
|
|
||||||
|
if (mHistoryDataMapCommon.isMapLoadOk()) {
|
||||||
|
getHistoryDay(mViewBinding.tvHomeRouteCalendarFromV3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setLatLngData(data: MutableList<HistoryDataBean>) {
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
mHistoryDataList = data
|
||||||
|
getHomeV2Activity()?.getPet(false)?.let {
|
||||||
|
mHistoryDataMapCommon.setPetBean(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isResumed) {
|
||||||
|
getHomeV2Activity()?.getPet()?.let { pet ->
|
||||||
|
if (Util.checkPackageLimit(getHomeV2Activity()!!, pet.deviceId)) {
|
||||||
|
mRechargeBackType = pet.availableOrder
|
||||||
|
mHistoryDataMapCommon.setPetUserLatLng()
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.size == 0) {
|
||||||
|
setSeekBarShowHide(false)
|
||||||
|
mHistoryDataMapCommon.setPetUserLatLng()
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
|
||||||
|
setSeekBarShowHide(true)
|
||||||
|
val max = data.size - 1
|
||||||
|
setSeekBarMax(max)
|
||||||
|
|
||||||
|
mHistoryDataMapCommon.setLatLngData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置SeekBar相关布局隐藏显示
|
||||||
|
*/
|
||||||
|
private fun setSeekBarShowHide(show: Boolean) {
|
||||||
|
mViewBinding.apply {
|
||||||
|
if (show && !isListExpand) {
|
||||||
|
vsbMapRouteLineV3.visibility = View.VISIBLE
|
||||||
|
ivMapRouteLineV3LastBtn.visibility = View.VISIBLE
|
||||||
|
ivMapRouteLineV3NextBtn.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
vsbMapRouteLineV3.visibility = View.GONE
|
||||||
|
ivMapRouteLineV3LastBtn.visibility = View.GONE
|
||||||
|
ivMapRouteLineV3NextBtn.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setSeekBarMax(max: Int) {
|
||||||
|
mViewBinding.vsbMapRouteLineV3.let {
|
||||||
|
it.max = max
|
||||||
|
//定位中心显示最后一个经纬度
|
||||||
|
it.progress = max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cSelectView 当前设置日期的view
|
||||||
|
*/
|
||||||
|
private fun getHistoryDay(cSelectView: TypefaceTextView) {
|
||||||
|
mViewBinding.apply {
|
||||||
|
// mFromTimestamp = Utils.stringToTimestamp(
|
||||||
|
// tvHomeRouteCalendarFromV3.text.toString(), Utils.DATE_FORMAT_PATTERN_EN13
|
||||||
|
// )
|
||||||
|
// mToTimestamp = Utils.stringToTimestamp(
|
||||||
|
// tvHomeRouteCalendarToV3.text.toString(), Utils.DATE_FORMAT_PATTERN_EN13
|
||||||
|
// )
|
||||||
|
if (mToTimestamp - mFromTimestamp < 0) {
|
||||||
|
checkCorrectDate(cSelectView)
|
||||||
|
} else if (mToTimestamp - mFromTimestamp > mOnlySelectDay * 24 * 60 * 60 * 1000) {
|
||||||
|
checkCorrectDate(cSelectView)
|
||||||
|
}
|
||||||
|
|
||||||
|
getHomeV2Activity()?.getPet()?.apply {
|
||||||
|
initState()
|
||||||
|
mDataDetailViewModel.getHistoryByDay(
|
||||||
|
getHomeV2Activity()!!, deviceId, mFromTimestamp / 1000, mToTimestamp / 1000
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测符合的日期
|
||||||
|
*/
|
||||||
|
private fun checkCorrectDate(cSelectView: TypefaceTextView) {
|
||||||
|
mViewBinding.apply {
|
||||||
|
if (cSelectView == tvHomeRouteCalendarFromV3) {
|
||||||
|
mToTimestamp = Utils.getAfterHowTimestamp(mFromTimestamp, mOnlySelectDay)
|
||||||
|
if (mToTimestamp > mCurrentTimestamp) {
|
||||||
|
mToTimestamp = mCurrentTimestamp
|
||||||
|
}
|
||||||
|
tvHomeRouteCalendarToV3.text = Utils.formatTime(
|
||||||
|
mToTimestamp, Utils.DATE_FORMAT_PATTERN_EN13
|
||||||
|
)
|
||||||
|
mToCalenderDialog?.setSelectDate(mToTimestamp)
|
||||||
|
} else {
|
||||||
|
//结束日期小于开始日期,就默认选择结束日期前一天
|
||||||
|
mFromTimestamp =
|
||||||
|
if (mFromTimestamp > mToTimestamp) Utils.getBeforeHowTimestamp(mToTimestamp, 1L)
|
||||||
|
else Utils.getBeforeHowTimestamp(mToTimestamp, mOnlySelectDay)
|
||||||
|
tvHomeRouteCalendarFromV3.text = Utils.formatTime(
|
||||||
|
mFromTimestamp, Utils.DATE_FORMAT_PATTERN_EN13
|
||||||
|
)
|
||||||
|
mFromCalenderDialog?.setSelectDate(mFromTimestamp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View?) {
|
||||||
|
mViewBinding.apply {
|
||||||
|
when (v!!) {
|
||||||
|
ilHomeRoutePetHeadV3.homeDataPetNameSmall, ilHomeRoutePetHeadV3.homeDataPetHeadSmall.root -> {
|
||||||
|
getHomeV2Activity()?.let {
|
||||||
|
if (!it.isNotifyRefreshLocation) it.selectPetDialog(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llHomeRouteCalendarFromV3 -> {
|
||||||
|
getHomeV2Activity()?.getPet()?.let {
|
||||||
|
//防止执行多次弹窗
|
||||||
|
if (isLimitClick()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (Util.checkPackageLimit(getHomeV2Activity()!!, it.deviceId)) {
|
||||||
|
mRechargeBackType = it.availableOrder
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null == mFromCalenderDialog) {
|
||||||
|
mFromCalenderDialog = ShowCalenderAndTimeDialog(
|
||||||
|
mContext!!,
|
||||||
|
tvHomeRouteCalendarFromV3,
|
||||||
|
object : BaseDialog.OnDialogSelectListener {
|
||||||
|
override fun onSelectClick(dialog: BaseDialog<*>, any: Any) {
|
||||||
|
mCurrentTimestamp = System.currentTimeMillis()
|
||||||
|
isSelectCustomDate = true
|
||||||
|
mFromTimestamp = any as Long
|
||||||
|
getHistoryDay(tvHomeRouteCalendarFromV3)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
calenderShowTimestamp = mFromTimestamp,
|
||||||
|
format = Utils.DATE_FORMAT_PATTERN_EN13
|
||||||
|
)
|
||||||
|
}
|
||||||
|
mFromCalenderDialog?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
llHomeRouteCalendarToV3 -> {
|
||||||
|
getHomeV2Activity()?.getPet()?.let {
|
||||||
|
//防止执行多次弹窗
|
||||||
|
if (isLimitClick()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (Util.checkPackageLimit(getHomeV2Activity()!!, it.deviceId)) {
|
||||||
|
mRechargeBackType = it.availableOrder
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (null == mToCalenderDialog) {
|
||||||
|
mToCalenderDialog = ShowCalenderAndTimeDialog(
|
||||||
|
mContext!!,
|
||||||
|
tvHomeRouteCalendarToV3,
|
||||||
|
object : BaseDialog.OnDialogSelectListener {
|
||||||
|
override fun onSelectClick(dialog: BaseDialog<*>, any: Any) {
|
||||||
|
isSelectCustomDate = true
|
||||||
|
mToTimestamp = any as Long
|
||||||
|
getHistoryDay(tvHomeRouteCalendarToV3)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
calenderShowTimestamp = mToTimestamp,
|
||||||
|
format = Utils.DATE_FORMAT_PATTERN_EN13
|
||||||
|
)
|
||||||
|
}
|
||||||
|
mToCalenderDialog?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
ivHomeRouteMapTypeBtnV3 -> mHistoryDataMapCommon.switchSatelliteAndNormalMapType()
|
||||||
|
ivMapRouteLineV3LastBtn -> {
|
||||||
|
if (vsbMapRouteLineV3.progress == 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vsbMapRouteLineV3.progress -= 1
|
||||||
|
mHistoryDataMapCommon.slideStopChanged(vsbMapRouteLineV3.progress)
|
||||||
|
}
|
||||||
|
|
||||||
|
ivMapRouteLineV3NextBtn -> {
|
||||||
|
if (vsbMapRouteLineV3.progress == vsbMapRouteLineV3.max) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vsbMapRouteLineV3.progress += 1
|
||||||
|
mHistoryDataMapCommon.slideStopChanged(vsbMapRouteLineV3.progress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,17 +28,20 @@ import com.abbidot.baselibrary.util.MMKVUtil
|
|||||||
import com.abbidot.baselibrary.util.Utils
|
import com.abbidot.baselibrary.util.Utils
|
||||||
import com.abbidot.tracker.R
|
import com.abbidot.tracker.R
|
||||||
import com.abbidot.tracker.adapter.HomeMapDeviceStateAdapter
|
import com.abbidot.tracker.adapter.HomeMapDeviceStateAdapter
|
||||||
|
import com.abbidot.tracker.adapter.SelectMapListDialogAdapter
|
||||||
import com.abbidot.tracker.base.BaseDialog
|
import com.abbidot.tracker.base.BaseDialog
|
||||||
import com.abbidot.tracker.base.BaseFragment
|
import com.abbidot.tracker.base.BaseFragment
|
||||||
import com.abbidot.tracker.bean.BleReportDataBean
|
import com.abbidot.tracker.bean.BleReportDataBean
|
||||||
import com.abbidot.tracker.bean.BleTrackDeviceBean
|
import com.abbidot.tracker.bean.BleTrackDeviceBean
|
||||||
import com.abbidot.tracker.bean.DataBean
|
import com.abbidot.tracker.bean.DataBean
|
||||||
import com.abbidot.tracker.bean.MapDeviceBean
|
import com.abbidot.tracker.bean.MapDeviceBean
|
||||||
|
import com.abbidot.tracker.bean.MenuTxtBean
|
||||||
import com.abbidot.tracker.constant.ConstantInt
|
import com.abbidot.tracker.constant.ConstantInt
|
||||||
import com.abbidot.tracker.constant.ConstantString
|
import com.abbidot.tracker.constant.ConstantString
|
||||||
import com.abbidot.tracker.constant.GetResultCallback
|
import com.abbidot.tracker.constant.GetResultCallback
|
||||||
import com.abbidot.tracker.databinding.FragmentMapV3Binding
|
import com.abbidot.tracker.databinding.FragmentMapV3Binding
|
||||||
import com.abbidot.tracker.dialog.CommonDialog1
|
import com.abbidot.tracker.dialog.CommonDialog1
|
||||||
|
import com.abbidot.tracker.dialog.SelectMapListDialog
|
||||||
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.map.LiveActivityV3
|
import com.abbidot.tracker.ui.activity.map.LiveActivityV3
|
||||||
@@ -104,6 +107,13 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
|||||||
private var needGpsToGCJ02 = true
|
private var needGpsToGCJ02 = true
|
||||||
private var mAnimatorSet: AnimatorSet? = null
|
private var mAnimatorSet: AnimatorSet? = null
|
||||||
|
|
||||||
|
private val mMapGooglePackageName = "com.google.android.apps.maps"
|
||||||
|
private val mMapGaoDePackageName = "com.autonavi.minimap"
|
||||||
|
private val mMapBaiduPackageName = "com.baidu.BaiduMap"
|
||||||
|
|
||||||
|
private lateinit var mSelectMapListDialogAdapter: SelectMapListDialogAdapter
|
||||||
|
private var mSelectMapListDialog: SelectMapListDialog? = null
|
||||||
|
|
||||||
//一键定位开始的时间戳
|
//一键定位开始的时间戳
|
||||||
private var notifyRefreshLocationTimestamp = 0L
|
private var notifyRefreshLocationTimestamp = 0L
|
||||||
|
|
||||||
@@ -909,28 +919,110 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun goNavigation() {
|
// private fun goNavigation() {
|
||||||
mMapDeviceBean?.let { m ->
|
// mMapDeviceBean?.let { m ->
|
||||||
try {
|
// try {
|
||||||
//自动弹出手机中已经有安装地图的应用
|
// //自动弹出手机中已经有安装地图的应用
|
||||||
val uri = if (MMKVUtil.getBoolean(MMKVKey.isGpsToGCJ02)) {
|
// val uri = if (MMKVUtil.getBoolean(MMKVKey.isGpsToGCJ02)) {
|
||||||
val convertLatLon =
|
// val convertLatLon =
|
||||||
LonAndLatUtil.convertFromWGS84ToGCJ02(m.latitude, m.longitude)
|
// LonAndLatUtil.convertFromWGS84ToGCJ02(m.latitude, m.longitude)
|
||||||
"google.navigation:q=${convertLatLon[0]},${convertLatLon[1]}&mode=w".toUri()
|
// "google.navigation:q=${convertLatLon[0]},${convertLatLon[1]}&mode=w".toUri()
|
||||||
} else {
|
// } else {
|
||||||
"google.navigation:q=${m.latitude},${m.longitude}&mode=w".toUri()
|
// "google.navigation:q=${m.latitude},${m.longitude}&mode=w".toUri()
|
||||||
|
// }
|
||||||
|
// val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||||
|
// intent.setPackage("com.google.android.apps.maps")
|
||||||
|
// startActivity(intent)
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// showToast(getString(R.string.txt_no_install))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
private fun showNavigationDialog() {
|
||||||
|
if (null == mSelectMapListDialog) {
|
||||||
|
val mapList = mutableListOf<MenuTxtBean>()
|
||||||
|
ViewUtil.instance.addMenuBean(
|
||||||
|
mapList,
|
||||||
|
getString(R.string.map_navigate_map_google),
|
||||||
|
mMapGooglePackageName,
|
||||||
|
R.drawable.ico_map_google
|
||||||
|
)
|
||||||
|
ViewUtil.instance.addMenuBean(
|
||||||
|
mapList,
|
||||||
|
getString(R.string.map_navigate_map_gaode),
|
||||||
|
mMapGaoDePackageName,
|
||||||
|
R.drawable.ico_map_gaode
|
||||||
|
)
|
||||||
|
ViewUtil.instance.addMenuBean(
|
||||||
|
mapList,
|
||||||
|
getString(R.string.map_navigate_map_baidu),
|
||||||
|
mMapBaiduPackageName,
|
||||||
|
R.drawable.ico_map_gaode
|
||||||
|
)
|
||||||
|
|
||||||
|
mSelectMapListDialogAdapter = SelectMapListDialogAdapter(mContext!!, mapList)
|
||||||
|
mSelectMapListDialogAdapter.setOnItemClickListener(object :
|
||||||
|
BaseRecyclerAdapter.OnItemClickListener {
|
||||||
|
override fun onItemClick(itemView: View?, pos: Int) {
|
||||||
|
selectMapNavigation(mapList[pos])
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
mSelectMapListDialog = SelectMapListDialog(mContext!!, mSelectMapListDialogAdapter)
|
||||||
|
}
|
||||||
|
mSelectMapListDialog!!.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择地图开始跳转
|
||||||
|
*/
|
||||||
|
private fun selectMapNavigation(item: MenuTxtBean) {
|
||||||
|
mSelectMapListDialog?.dismiss()
|
||||||
|
mMapDeviceBean?.apply {
|
||||||
|
try {
|
||||||
|
when (item.menuValue) {
|
||||||
|
//谷歌地图
|
||||||
|
mMapGooglePackageName -> {
|
||||||
|
var lat = latitude
|
||||||
|
var lon = longitude
|
||||||
|
if (MMKVUtil.getBoolean(MMKVKey.isGpsToGCJ02)) {
|
||||||
|
val convertLatLon =
|
||||||
|
LonAndLatUtil.convertFromWGS84ToGCJ02(latitude, longitude)
|
||||||
|
lat = convertLatLon[0]
|
||||||
|
lon = convertLatLon[1]
|
||||||
|
}
|
||||||
|
val uri = "google.navigation:q=${lat},${lon}&mode=w".toUri()
|
||||||
val intent = Intent(Intent.ACTION_VIEW, uri)
|
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||||
intent.setPackage("com.google.android.apps.maps")
|
intent.setPackage(item.menuValue)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
//高德地图 https://lbs.amap.com/api/amap-mobile/guide/android/walk-navi
|
||||||
|
mMapGaoDePackageName -> {
|
||||||
|
val uri = "amapuri://openFeature?featureName=OnFootNavi&sourceApplication=${
|
||||||
|
getString(
|
||||||
|
R.string.app_name
|
||||||
|
)
|
||||||
|
}&lat=${latitude}&lon=${longitude}&dev=1".toUri()
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||||
|
intent.setPackage(item.menuValue)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
//百度地图 https://lbs.baidu.com/docs/webapi?title=mapadjustment/uri/andriod
|
||||||
|
mMapBaiduPackageName -> {
|
||||||
|
val uri =
|
||||||
|
"baidumap://map/direction?destination=name:|latlng:${latitude},${longitude}&mode=walking&coord_type=wgs84".toUri()
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||||
|
intent.setPackage(item.menuValue)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
showToast(getString(R.string.txt_no_install))
|
showToast(getString(R.string.txt_no_install), gravity = Gravity.CENTER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(v: View?) {
|
override fun onClick(v: View?) {
|
||||||
if (isLimitClick()) return
|
|
||||||
mViewBinding.apply {
|
mViewBinding.apply {
|
||||||
when (v!!) {
|
when (v!!) {
|
||||||
homeMapRefreshBtn -> {
|
homeMapRefreshBtn -> {
|
||||||
@@ -964,6 +1056,7 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
|||||||
}
|
}
|
||||||
|
|
||||||
homeMapLiveBtn -> {
|
homeMapLiveBtn -> {
|
||||||
|
if (isLimitClick()) return
|
||||||
if (!isCanLive) {
|
if (!isCanLive) {
|
||||||
showToast(R.string.txt_live_works_cellular, gravity = Gravity.CENTER)
|
showToast(R.string.txt_live_works_cellular, gravity = Gravity.CENTER)
|
||||||
return
|
return
|
||||||
@@ -974,7 +1067,11 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
|||||||
|
|
||||||
ivHomeMapRefreshLocation -> notifyRefreshLocation()
|
ivHomeMapRefreshLocation -> notifyRefreshLocation()
|
||||||
llHomeMapTopPet.ivTopPetBtnSmall -> showMapTypeDialog()
|
llHomeMapTopPet.ivTopPetBtnSmall -> showMapTypeDialog()
|
||||||
homeMapBluetoothBtn -> checkPermissions(1)
|
homeMapBluetoothBtn -> {
|
||||||
|
if (isLimitClick()) return
|
||||||
|
checkPermissions(1)
|
||||||
|
}
|
||||||
|
|
||||||
llHomeMapTopPet.homeDataPetNameSmall, llHomeMapTopPet.homeDataPetHeadSmall.root -> {
|
llHomeMapTopPet.homeDataPetNameSmall, llHomeMapTopPet.homeDataPetHeadSmall.root -> {
|
||||||
getHomeV2Activity()?.let {
|
getHomeV2Activity()?.let {
|
||||||
if (!it.isNotifyRefreshLocation) {
|
if (!it.isNotifyRefreshLocation) {
|
||||||
@@ -993,7 +1090,11 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
|||||||
ilHomeMapDeviceMsg.root.visibility = View.GONE
|
ilHomeMapDeviceMsg.root.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
ilHomeMapPetLocation.ivPetLocationNavigationBtn -> goNavigation()
|
ilHomeMapPetLocation.ivPetLocationNavigationBtn -> {
|
||||||
|
if (isLimitClick()) return
|
||||||
|
// goNavigation()
|
||||||
|
showNavigationDialog()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.abbidot.tracker.ui.fragment.map.googlemap
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
|
import androidx.appcompat.widget.AppCompatSeekBar
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.abbidot.baselibrary.constant.MMKVKey
|
import com.abbidot.baselibrary.constant.MMKVKey
|
||||||
import com.abbidot.baselibrary.util.AppUtils
|
import com.abbidot.baselibrary.util.AppUtils
|
||||||
@@ -15,7 +16,6 @@ import com.abbidot.tracker.constant.ConstantInt
|
|||||||
import com.abbidot.tracker.util.ViewUtil
|
import com.abbidot.tracker.util.ViewUtil
|
||||||
import com.abbidot.tracker.vm.GeoCoderViewModel
|
import com.abbidot.tracker.vm.GeoCoderViewModel
|
||||||
import com.abbidot.tracker.widget.MapMarkerInfoView
|
import com.abbidot.tracker.widget.MapMarkerInfoView
|
||||||
import com.abbidot.tracker.widget.VerticalTopToBottomSeekBar
|
|
||||||
import com.google.android.gms.maps.GoogleMap
|
import com.google.android.gms.maps.GoogleMap
|
||||||
import com.google.android.gms.maps.model.BitmapDescriptor
|
import com.google.android.gms.maps.model.BitmapDescriptor
|
||||||
import com.google.android.gms.maps.model.BitmapDescriptorFactory
|
import com.google.android.gms.maps.model.BitmapDescriptorFactory
|
||||||
@@ -32,7 +32,7 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() {
|
|||||||
// private val mScreenshotsViewModel: ScreenshotsViewModel by viewModels()
|
// private val mScreenshotsViewModel: ScreenshotsViewModel by viewModels()
|
||||||
private lateinit var mGeoCoderViewModel: GeoCoderViewModel
|
private lateinit var mGeoCoderViewModel: GeoCoderViewModel
|
||||||
private lateinit var mMarkerInfoView: MapMarkerInfoView
|
private lateinit var mMarkerInfoView: MapMarkerInfoView
|
||||||
private lateinit var mVerticalTopToBottomSeekBar: VerticalTopToBottomSeekBar
|
private lateinit var mVerticalTopToBottomSeekBar: AppCompatSeekBar
|
||||||
|
|
||||||
private val mMarkerOptions = MarkerOptions()
|
private val mMarkerOptions = MarkerOptions()
|
||||||
private lateinit var mPetIconDescriptor: BitmapDescriptor
|
private lateinit var mPetIconDescriptor: BitmapDescriptor
|
||||||
@@ -55,7 +55,7 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() {
|
|||||||
context: Context,
|
context: Context,
|
||||||
markerInfoView: MapMarkerInfoView,
|
markerInfoView: MapMarkerInfoView,
|
||||||
geoCoderViewModel: GeoCoderViewModel,
|
geoCoderViewModel: GeoCoderViewModel,
|
||||||
verticalTopToBottomSeekBar: VerticalTopToBottomSeekBar,
|
verticalTopToBottomSeekBar: AppCompatSeekBar,
|
||||||
mapLoadOk: () -> Unit
|
mapLoadOk: () -> Unit
|
||||||
) = HistoryDataGoogleMapFragment().apply {
|
) = HistoryDataGoogleMapFragment().apply {
|
||||||
mContext = context
|
mContext = context
|
||||||
@@ -97,9 +97,7 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() {
|
|||||||
if (getGoogleMapZoom() != cameraPosition.zoom) {
|
if (getGoogleMapZoom() != cameraPosition.zoom) {
|
||||||
setGoogleMapZoom(cameraPosition.zoom)
|
setGoogleMapZoom(cameraPosition.zoom)
|
||||||
}
|
}
|
||||||
mCurLatLng?.let {
|
resetMarkerInfoViewOffset()
|
||||||
if (mMarkerInfoView.isVisible) setMarkerInfoViewOffset(mMarkerInfoView, it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
setOnMarkerClickListener { m ->
|
setOnMarkerClickListener { m ->
|
||||||
//点击数字大头针回到该位置
|
//点击数字大头针回到该位置
|
||||||
@@ -123,6 +121,12 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() {
|
|||||||
if (::mMapLoadOk.isInitialized) mMapLoadOk()
|
if (::mMapLoadOk.isInitialized) mMapLoadOk()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun resetMarkerInfoViewOffset() {
|
||||||
|
mCurLatLng?.let {
|
||||||
|
if (mMarkerInfoView.isVisible) setMarkerInfoViewOffset(mMarkerInfoView, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun setPetBean(petBean: PetBean) {
|
suspend fun setPetBean(petBean: PetBean) {
|
||||||
if (petBean == mPetBean) {
|
if (petBean == mPetBean) {
|
||||||
return
|
return
|
||||||
@@ -153,7 +157,7 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() {
|
|||||||
mGoogleMap?.clear()
|
mGoogleMap?.clear()
|
||||||
|
|
||||||
if (data.size == 0) return
|
if (data.size == 0) return
|
||||||
|
mLatLngList.clear()
|
||||||
var maxLat = data[0].latitude
|
var maxLat = data[0].latitude
|
||||||
var maxLon = data[0].longitude
|
var maxLon = data[0].longitude
|
||||||
var minLat = data[0].latitude
|
var minLat = data[0].latitude
|
||||||
@@ -195,7 +199,7 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() {
|
|||||||
* 滑动改变
|
* 滑动改变
|
||||||
*/
|
*/
|
||||||
fun slideChanged(progress: Int) {
|
fun slideChanged(progress: Int) {
|
||||||
setPetMarkerLatLng(mLatLngList[progress])
|
if (progress < mLatLngList.size) setPetMarkerLatLng(mLatLngList[progress])
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ class ViewUtil private constructor() {
|
|||||||
) {
|
) {
|
||||||
numberPicker.apply {
|
numberPicker.apply {
|
||||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
|
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
|
||||||
selectionDividerHeight = AppUtils.dpToPx(1)
|
selectionDividerHeight = AppUtils.dpToPx(0.5f).toInt()
|
||||||
if (tSize > 0) {
|
if (tSize > 0) {
|
||||||
textSize = QMUIDisplayHelper.sp2px(context, tSize).toFloat()
|
textSize = QMUIDisplayHelper.sp2px(context, tSize).toFloat()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import com.abbidot.tracker.base.BaseActivity
|
import com.abbidot.tracker.base.BaseActivity
|
||||||
import com.abbidot.tracker.bean.ActiveTimeBean
|
import com.abbidot.tracker.bean.ActiveTimeBean
|
||||||
import com.abbidot.tracker.bean.HistoryDataBean
|
import com.abbidot.tracker.bean.HistoryDataBean
|
||||||
|
import com.abbidot.tracker.bean.MessageBean
|
||||||
import com.abbidot.tracker.bean.SleepTimeBean
|
import com.abbidot.tracker.bean.SleepTimeBean
|
||||||
import com.abbidot.tracker.retrofit2.NetworkApi
|
import com.abbidot.tracker.retrofit2.NetworkApi
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -20,6 +21,7 @@ class DataDetailViewModel : ViewModel() {
|
|||||||
val mActiveDetailLiveData = MutableLiveData<Result<ActiveTimeBean>>()
|
val mActiveDetailLiveData = MutableLiveData<Result<ActiveTimeBean>>()
|
||||||
val mSleepDetailLiveData = MutableLiveData<Result<SleepTimeBean>>()
|
val mSleepDetailLiveData = MutableLiveData<Result<SleepTimeBean>>()
|
||||||
val mHistoryDetailLive = MutableLiveData<Result<MutableList<HistoryDataBean>>>()
|
val mHistoryDetailLive = MutableLiveData<Result<MutableList<HistoryDataBean>>>()
|
||||||
|
val mHistoryFenceEvents = MutableLiveData<Result<MutableList<MessageBean>>>()
|
||||||
val mSetGoalLiveData = MutableLiveData<Result<String>>()
|
val mSetGoalLiveData = MutableLiveData<Result<String>>()
|
||||||
val mPetActivityInfoLiveData = MutableLiveData<Result<ActiveTimeBean>>()
|
val mPetActivityInfoLiveData = MutableLiveData<Result<ActiveTimeBean>>()
|
||||||
|
|
||||||
@@ -40,10 +42,7 @@ class DataDetailViewModel : ViewModel() {
|
|||||||
* 获取SleepTime数据
|
* 获取SleepTime数据
|
||||||
*/
|
*/
|
||||||
fun getSleepTimeByDay(
|
fun getSleepTimeByDay(
|
||||||
activity: BaseActivity<*>,
|
activity: BaseActivity<*>, deviceId: String, dayTime: String, petId: String
|
||||||
deviceId: String,
|
|
||||||
dayTime: String,
|
|
||||||
petId: String
|
|
||||||
) {
|
) {
|
||||||
activity.showLoading(true)
|
activity.showLoading(true)
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@@ -60,6 +59,16 @@ class DataDetailViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getHistoryFenceList(
|
||||||
|
activity: BaseActivity<*>, deviceId: String, fromTime: Long, toTime: Long
|
||||||
|
) {
|
||||||
|
activity.showLoading(true)
|
||||||
|
viewModelScope.launch {
|
||||||
|
val result = NetworkApi.getHistoryFenceList(deviceId, fromTime, toTime)
|
||||||
|
mHistoryFenceEvents.value = result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*设置运动目标
|
*设置运动目标
|
||||||
* @param goalTime min
|
* @param goalTime min
|
||||||
|
|||||||
195
app/src/main/java/com/abbidot/tracker/widget/AppBarBehavior.java
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
package com.abbidot.tracker.widget;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
|
||||||
|
import com.google.android.material.appbar.AppBarLayout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仿饿了么地图滑动特效
|
||||||
|
*/
|
||||||
|
public class AppBarBehavior extends AppBarLayout.Behavior {
|
||||||
|
/**
|
||||||
|
* nestedScrollview的滑动距离
|
||||||
|
*/
|
||||||
|
int ay = 0;
|
||||||
|
/**
|
||||||
|
* nestedScrollview 沒有滑动到顶部之前的可滑动最大距离
|
||||||
|
*/
|
||||||
|
private int minY = 0;
|
||||||
|
|
||||||
|
public AppBarBehavior() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppBarBehavior(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AppBarLayout布局时调用
|
||||||
|
*
|
||||||
|
* @param parent 父布局CoordinatorLayout
|
||||||
|
* @param abl 使用此Behavior的AppBarLayout
|
||||||
|
* @param layoutDirection 布局方向
|
||||||
|
* @return 返回true表示子View重新布局,返回false表示请求默认布局
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onLayoutChild(CoordinatorLayout parent, AppBarLayout abl, int layoutDirection) {
|
||||||
|
return super.onLayoutChild(parent, abl, layoutDirection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当CoordinatorLayout的子View尝试发起嵌套滚动时调用
|
||||||
|
*
|
||||||
|
* @param parent 父布局CoordinatorLayout
|
||||||
|
* @param child 使用此Behavior的AppBarLayout
|
||||||
|
* @param directTargetChild CoordinatorLayout的子View,或者是包含嵌套滚动操作的目标View
|
||||||
|
* @param target 发起嵌套滚动的目标View(即AppBarLayout下面的ScrollView或RecyclerView)
|
||||||
|
* @param nestedScrollAxes 嵌套滚动的方向
|
||||||
|
* @return 返回true表示接受滚动
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes, int type) {
|
||||||
|
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当嵌套滚动已由CoordinatorLayout接受时调用
|
||||||
|
*
|
||||||
|
* @param coordinatorLayout 父布局CoordinatorLayout
|
||||||
|
* @param child 使用此Behavior的AppBarLayout
|
||||||
|
* @param directTargetChild CoordinatorLayout的子View,或者是包含嵌套滚动操作的目标View
|
||||||
|
* @param target 发起嵌套滚动的目标View(即AppBarLayout下面的ScrollView或RecyclerView)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onNestedScrollAccepted(@NonNull CoordinatorLayout coordinatorLayout, @NonNull AppBarLayout child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) {
|
||||||
|
super.onNestedScrollAccepted(coordinatorLayout, child, directTargetChild, target, axes, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当准备开始嵌套滚动时调用
|
||||||
|
*
|
||||||
|
* @param coordinatorLayout 父布局CoordinatorLayout
|
||||||
|
* @param child 使用此Behavior的AppBarLayout
|
||||||
|
* @param target 发起嵌套滚动的目标View(即AppBarLayout下面的ScrollView或RecyclerView)
|
||||||
|
* @param dx 用户在水平方向上滑动的像素数
|
||||||
|
* @param dy 用户在垂直方向上滑动的像素数
|
||||||
|
* @param consumed 输出参数,consumed[0]为水平方向应该消耗的距离,consumed[1]为垂直方向应该消耗的距离
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) {
|
||||||
|
if (minY == 0) {
|
||||||
|
minY = target.getHeight() + child.getHeight() - coordinatorLayout.getHeight();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 如果nestedScrollview 布局内容少没有内部滑动,这时需要我们进行处理
|
||||||
|
* 当nestedScrollview 内容很多时,我们不需要任何事情
|
||||||
|
* */
|
||||||
|
if (target.getScrollY() <= 0) {
|
||||||
|
ay += dy;
|
||||||
|
if (dy > 0 && ay >= minY) {
|
||||||
|
dy = minY + dy - ay;//这里之所以没有让dy = 0;因为当快速滑动时就会有问题,快速滑动时dy的变化很大,自行琢磨一下,还不懂加群交流
|
||||||
|
ay = minY;
|
||||||
|
}
|
||||||
|
if (dy < 0 && ay <= 0) {
|
||||||
|
ay = 0;
|
||||||
|
dy = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套滚动时调用
|
||||||
|
*
|
||||||
|
* @param coordinatorLayout 父布局CoordinatorLayout
|
||||||
|
* @param child 使用此Behavior的AppBarLayout
|
||||||
|
* @param target 发起嵌套滚动的目标View(即AppBarLayout下面的ScrollView或RecyclerView)
|
||||||
|
* @param dxConsumed 由目标View滚动操作消耗的水平像素数
|
||||||
|
* @param dyConsumed 由目标View滚动操作消耗的垂直像素数
|
||||||
|
* @param dxUnconsumed 由用户请求但是目标View滚动操作未消耗的水平像素数
|
||||||
|
* @param dyUnconsumed 由用户请求但是目标View滚动操作未消耗的垂直像素数
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
|
||||||
|
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当嵌套滚动的子View准备快速滚动时调用
|
||||||
|
*
|
||||||
|
* @param coordinatorLayout 父布局CoordinatorLayout
|
||||||
|
* @param child 使用此Behavior的AppBarLayout
|
||||||
|
* @param target 发起嵌套滚动的目标View(即AppBarLayout下面的ScrollView或RecyclerView)
|
||||||
|
* @param velocityX 水平方向的速度
|
||||||
|
* @param velocityY 垂直方向的速度
|
||||||
|
* @return 如果Behavior消耗了快速滚动返回true
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY) {
|
||||||
|
|
||||||
|
return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当嵌套滚动的子View快速滚动时调用
|
||||||
|
*
|
||||||
|
* @param coordinatorLayout 父布局CoordinatorLayout
|
||||||
|
* @param child 使用此Behavior的AppBarLayout
|
||||||
|
* @param target 发起嵌套滚动的目标View(即AppBarLayout下面的ScrollView或RecyclerView)
|
||||||
|
* @param velocityX 水平方向的速度
|
||||||
|
* @param velocityY 垂直方向的速度
|
||||||
|
* @param consumed 如果嵌套的子View消耗了快速滚动则为true
|
||||||
|
* @return 如果Behavior消耗了快速滚动返回true
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) {
|
||||||
|
return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当触摸时调用
|
||||||
|
*
|
||||||
|
* @param parent 父布局CoordinatorLayout
|
||||||
|
* @param child 使用此Behavior的AppBarLayout
|
||||||
|
* @param ev 手势事件
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
|
||||||
|
return super.onTouchEvent(parent, child, ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当触摸想要拦截时调用 关键所在 true 不拦截 false 拦截AppBarLayout的手势触摸
|
||||||
|
*
|
||||||
|
* @param parent 父布局CoordinatorLayout
|
||||||
|
* @param child 使用此Behavior的AppBarLayout
|
||||||
|
* @param ev 手势事件
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 嵌套滚动结束时被调用
|
||||||
|
*
|
||||||
|
* @param coordinatorLayout 父布局CoordinatorLayout
|
||||||
|
* @param abl 使用此Behavior的AppBarLayout
|
||||||
|
* @param target 发起嵌套滚动的目标View(即AppBarLayout下面的ScrollView或RecyclerView)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout abl, View target, int type) {
|
||||||
|
super.onStopNestedScroll(coordinatorLayout, abl, target, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.abbidot.tracker.widget;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by .yzq on 2026/4/10/周五.
|
||||||
|
*
|
||||||
|
* @link
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
public class CustomLayoutManager extends LinearLayoutManager {
|
||||||
|
|
||||||
|
public CustomLayoutManager(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||||
|
super.onLayoutChildren(recycler, state);
|
||||||
|
|
||||||
|
// 根据需要修改布局和滚动效果
|
||||||
|
// 例如调整位置或是控制滑出顶部的限制
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canScrollVertically() {
|
||||||
|
return true; // 允许垂直滚动
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scrollToPosition(int position) {
|
||||||
|
// 自定义滚动位置,确保滑动时不会被提前阻止
|
||||||
|
super.scrollToPosition(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package com.abbidot.tracker.widget;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
import androidx.appcompat.widget.AppCompatSeekBar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可以通过STATUS设置 Seekbar禁止点击禁止滑动等
|
||||||
|
*/
|
||||||
|
public class NoClickSlideSeekBar extends AppCompatSeekBar {
|
||||||
|
private static final int PADDING_DEFAULT = 50;
|
||||||
|
|
||||||
|
public enum STATUS {
|
||||||
|
STATUS_ENABLE, STATUS_CLICK, STATUS_SLIDE, STATUS_UNABLE
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 填充大小
|
||||||
|
*/
|
||||||
|
private final int mPaddingSize = PADDING_DEFAULT;
|
||||||
|
|
||||||
|
private STATUS mStaus = STATUS.STATUS_ENABLE;
|
||||||
|
|
||||||
|
private Rect mThumbRect;
|
||||||
|
|
||||||
|
private int mX, mY;
|
||||||
|
|
||||||
|
private NoClickSlideSeekBar(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoClickSlideSeekBar(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NoClickSlideSeekBar(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
|
||||||
|
if (MotionEvent.ACTION_DOWN == event.getAction()) {
|
||||||
|
mThumbRect = getThumb().getBounds();
|
||||||
|
}
|
||||||
|
mX = (int) event.getX();
|
||||||
|
mY = (int) event.getY();
|
||||||
|
|
||||||
|
if (mStaus == STATUS.STATUS_CLICK && !checkBound()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (mStaus == STATUS.STATUS_SLIDE && checkBound()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (mStaus == STATUS.STATUS_UNABLE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断当前触摸点 是否在滑块之类-mPaddingSize是为了提高体验,因为有些滑块太小
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean checkBound() {
|
||||||
|
|
||||||
|
if (mX < mThumbRect.left - mPaddingSize || mX > mThumbRect.right + mPaddingSize || mY < mThumbRect.top - mPaddingSize || mY > mThumbRect.bottom + mPaddingSize) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(STATUS status) {
|
||||||
|
this.mStaus = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BIN
app/src/main/res/drawable-xhdpi/icon_bar_thumb_image.png
Normal file
|
After Width: | Height: | Size: 428 B |
|
After Width: | Height: | Size: 504 B |
|
After Width: | Height: | Size: 504 B |
|
After Width: | Height: | Size: 432 B |
BIN
app/src/main/res/drawable-xhdpi/icon_left_arrow_image.png
Normal file
|
After Width: | Height: | Size: 252 B |
BIN
app/src/main/res/drawable-xhdpi/icon_right_arrow_image.png
Normal file
|
After Width: | Height: | Size: 236 B |
BIN
app/src/main/res/drawable-xhdpi/icon_vertical_dot_line_image.png
Normal file
|
After Width: | Height: | Size: 178 B |
BIN
app/src/main/res/drawable-xxhdpi/icon_bar_thumb_image.png
Normal file
|
After Width: | Height: | Size: 633 B |
|
After Width: | Height: | Size: 730 B |
|
After Width: | Height: | Size: 730 B |
|
After Width: | Height: | Size: 546 B |
BIN
app/src/main/res/drawable-xxhdpi/icon_left_arrow_image.png
Normal file
|
After Width: | Height: | Size: 326 B |
BIN
app/src/main/res/drawable-xxhdpi/icon_right_arrow_image.png
Normal file
|
After Width: | Height: | Size: 305 B |
|
After Width: | Height: | Size: 186 B |
BIN
app/src/main/res/drawable-xxxhdpi/icon_bar_thumb_image.png
Normal file
|
After Width: | Height: | Size: 797 B |
|
After Width: | Height: | Size: 1001 B |
|
After Width: | Height: | Size: 1001 B |
|
After Width: | Height: | Size: 713 B |
BIN
app/src/main/res/drawable-xxxhdpi/icon_left_arrow_image.png
Normal file
|
After Width: | Height: | Size: 399 B |
BIN
app/src/main/res/drawable-xxxhdpi/icon_right_arrow_image.png
Normal file
|
After Width: | Height: | Size: 378 B |
|
After Width: | Height: | Size: 201 B |
@@ -3,13 +3,13 @@
|
|||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:state_pressed="false">
|
<item android:state_pressed="false">
|
||||||
<shape android:shape="rectangle">
|
<shape android:shape="rectangle">
|
||||||
<solid android:color="@color/block_color" />
|
<solid android:color="@color/line_color1" />
|
||||||
<corners android:radius="@dimen/dp_8" />
|
<corners android:radius="@dimen/dp_8" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item android:state_pressed="true">
|
<item android:state_pressed="true">
|
||||||
<shape android:shape="rectangle">
|
<shape android:shape="rectangle">
|
||||||
<solid android:color="@color/white" />
|
<solid android:color="@color/block_color" />
|
||||||
<corners android:radius="@dimen/dp_8" />
|
<corners android:radius="@dimen/dp_8" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
18
app/src/main/res/drawable/shape_seek_bar_style_v3.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@android:id/background">
|
||||||
|
<shape>
|
||||||
|
<corners android:radius="@dimen/dp_20" />
|
||||||
|
<solid android:color="@color/grey_color_92" />
|
||||||
|
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:id="@android:id/progress">
|
||||||
|
<clip>
|
||||||
|
<shape>
|
||||||
|
<solid android:color="@color/line_stroke_color" />
|
||||||
|
<corners android:radius="@dimen/dp_20" />
|
||||||
|
</shape>
|
||||||
|
</clip>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
||||||
@@ -28,20 +28,20 @@
|
|||||||
|
|
||||||
<NumberPicker
|
<NumberPicker
|
||||||
android:id="@+id/np_dialog_calender_hour"
|
android:id="@+id/np_dialog_calender_hour"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="@dimen/dp_47"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<com.abbidot.tracker.widget.TypefaceTextView
|
<com.abbidot.tracker.widget.TypefaceTextView
|
||||||
android:id="@+id/tv_home_route_calendar_from"
|
android:id="@+id/tv_home_route_calendar_from"
|
||||||
style="@style/my_TextView_style_v2"
|
style="@style/my_TextView_style_v2"
|
||||||
android:layout_marginHorizontal="@dimen/dp_18"
|
android:layout_marginHorizontal="@dimen/dp_10"
|
||||||
android:text=":"
|
android:text=":"
|
||||||
android:textSize="@dimen/textSize24"
|
android:textSize="@dimen/textSize20"
|
||||||
app:typeface="@string/roboto_bold_font" />
|
app:typeface="@string/roboto_bold_font" />
|
||||||
|
|
||||||
<NumberPicker
|
<NumberPicker
|
||||||
android:id="@+id/np_dialog_calender_min"
|
android:id="@+id/np_dialog_calender_min"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="@dimen/dp_47"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<com.abbidot.tracker.widget.TypefaceRoundButton
|
<com.abbidot.tracker.widget.TypefaceRoundButton
|
||||||
android:id="@+id/btn_select_calender_hour_min_cancel"
|
android:id="@+id/btn_select_calender_hour_min_cancel"
|
||||||
style="@style/my_QMUIRoundButton_small_style_v2"
|
style="@style/my_QMUIRoundButton_small_style_v2"
|
||||||
android:layout_marginEnd="@dimen/dp_4"
|
android:layout_marginEnd="@dimen/dp_6"
|
||||||
android:text="@string/txt_cancel"
|
android:text="@string/txt_cancel"
|
||||||
app:qmui_borderColor="@color/block_color2"
|
app:qmui_borderColor="@color/block_color2"
|
||||||
app:qmui_borderWidth="0.55dp"
|
app:qmui_borderWidth="0.55dp"
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
<com.abbidot.tracker.widget.TypefaceRoundButton
|
<com.abbidot.tracker.widget.TypefaceRoundButton
|
||||||
android:id="@+id/btn_select_calender_hour_min_ok"
|
android:id="@+id/btn_select_calender_hour_min_ok"
|
||||||
style="@style/my_QMUIRoundButton_small_style_v2"
|
style="@style/my_QMUIRoundButton_small_style_v2"
|
||||||
android:layout_marginStart="@dimen/dp_4"
|
android:layout_marginStart="@dimen/dp_6"
|
||||||
android:text="@android:string/ok"
|
android:text="@android:string/ok"
|
||||||
android:textColor="@color/select_color"
|
android:textColor="@color/select_color"
|
||||||
app:qmui_backgroundColor="@color/btn_yellow_color"
|
app:qmui_backgroundColor="@color/btn_yellow_color"
|
||||||
|
|||||||
232
app/src/main/res/layout/fragment_route_v3.xml
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
<?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.fragment.data.RouteV3Fragment">
|
||||||
|
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/il_home_route_pet_head_v3"
|
||||||
|
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_8" />
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/cv_home_route_v3_card"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_margin="@dimen/dp_8"
|
||||||
|
android:layout_weight="1"
|
||||||
|
app:cardCornerRadius="@dimen/dp_32">
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/fc_home_route_fragment_v3"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<com.abbidot.tracker.widget.MapMarkerInfoView
|
||||||
|
android:id="@+id/mi_home_route_address_view_v3"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/iv_home_route_map_type_btn_v3"
|
||||||
|
style="@style/map_image_white_btn_style"
|
||||||
|
android:layout_gravity="top|end"
|
||||||
|
android:layout_margin="@dimen/dp_12" />
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:id="@+id/sv_home_route_map_scroll"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/rl_home_route_calendar_v3_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
|
||||||
|
android:layout_marginHorizontal="@dimen/dp_8"
|
||||||
|
android:background="@drawable/shape_home_route_calendar_bg"
|
||||||
|
android:padding="@dimen/dp_12">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/v_home_route_calendar_center_v3"
|
||||||
|
android:layout_width="@dimen/dp_1"
|
||||||
|
android:layout_height="@dimen/dp_1"
|
||||||
|
android:layout_centerHorizontal="true" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:id="@+id/ll_home_route_calendar_from_v3"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="@dimen/dp_4"
|
||||||
|
android:layout_toStartOf="@id/v_home_route_calendar_center_v3"
|
||||||
|
android:background="@drawable/shape8_white_gray_bg"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingVertical="@dimen/dp_8">
|
||||||
|
|
||||||
|
<com.abbidot.tracker.widget.TypefaceTextView
|
||||||
|
android:id="@+id/tv_home_route_calendar_from_v3"
|
||||||
|
style="@style/my_TextView_style_v2"
|
||||||
|
android:layout_marginStart="@dimen/dp_12"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="start"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
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:layout_marginEnd="@dimen/dp_8"
|
||||||
|
android:src="@drawable/icon_date_time_svg" />
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:id="@+id/ll_home_route_calendar_to_v3"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignTop="@id/ll_home_route_calendar_from_v3"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginStart="@dimen/dp_4"
|
||||||
|
android:layout_toEndOf="@id/v_home_route_calendar_center_v3"
|
||||||
|
android:background="@drawable/shape8_white_gray_bg"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingVertical="@dimen/dp_8">
|
||||||
|
|
||||||
|
<com.abbidot.tracker.widget.TypefaceTextView
|
||||||
|
android:id="@+id/tv_home_route_calendar_to_v3"
|
||||||
|
style="@style/my_TextView_style_v2"
|
||||||
|
android:layout_marginStart="@dimen/dp_12"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="start"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
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:layout_marginEnd="@dimen/dp_8"
|
||||||
|
android:src="@drawable/icon_date_time_svg" />
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/iv_map_route_line_v3_last_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/ll_home_route_calendar_from_v3"
|
||||||
|
android:layout_alignStart="@id/ll_home_route_calendar_from_v3"
|
||||||
|
android:layout_marginTop="@dimen/dp_10"
|
||||||
|
android:background="@drawable/selector_transparent_pressed"
|
||||||
|
android:paddingVertical="@dimen/dp_8"
|
||||||
|
android:src="@drawable/icon_left_arrow_image"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/iv_map_route_line_v3_next_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignTop="@id/iv_map_route_line_v3_last_btn"
|
||||||
|
android:layout_alignEnd="@id/ll_home_route_calendar_to_v3"
|
||||||
|
android:background="@drawable/selector_transparent_pressed"
|
||||||
|
android:paddingVertical="@dimen/dp_8"
|
||||||
|
android:src="@drawable/icon_right_arrow_image"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<com.abbidot.tracker.widget.NoClickSlideSeekBar
|
||||||
|
android:id="@+id/vsb_map_route_line_v3"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/ll_home_route_calendar_from_v3"
|
||||||
|
android:layout_marginHorizontal="@dimen/dp_2"
|
||||||
|
android:layout_marginTop="@dimen/dp_12"
|
||||||
|
android:layout_toStartOf="@id/iv_map_route_line_v3_next_btn"
|
||||||
|
android:layout_toEndOf="@id/iv_map_route_line_v3_last_btn"
|
||||||
|
android:maxHeight="@dimen/dp_8"
|
||||||
|
android:progress="100"
|
||||||
|
android:progressDrawable="@drawable/shape_seek_bar_style_v3"
|
||||||
|
android:splitTrack="false"
|
||||||
|
android:thumb="@drawable/icon_bar_thumb_image"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/rl_map_route_line_v3_time_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/dp_8"
|
||||||
|
android:background="@drawable/shape20_white_half_bottom_bg"
|
||||||
|
android:paddingHorizontal="@dimen/dp_14"
|
||||||
|
android:paddingBottom="@dimen/dp_22"
|
||||||
|
android:visibility="visible">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:id="@+id/ll_map_route_line_v3_zooming_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingTop="@dimen/dp_4"
|
||||||
|
android:paddingBottom="@dimen/dp_10">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/v_map_route_line_v3_zooming"
|
||||||
|
android:layout_width="@dimen/dp_30"
|
||||||
|
android:layout_height="@dimen/dp_4"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:src="@drawable/shape8_gray_bg" />
|
||||||
|
|
||||||
|
<com.abbidot.tracker.widget.TypefaceTextView
|
||||||
|
style="@style/my_TextView_style_v2"
|
||||||
|
android:layout_below="@id/ll_map_route_line_v3_zooming_layout"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:text="@string/txt_time_line"
|
||||||
|
android:textSize="@dimen/textSize12"
|
||||||
|
app:typeface="@string/roboto_regular_font" />
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/iv_history_fence_start_image"
|
||||||
|
android:layout_width="@dimen/dp_18"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/ll_map_route_line_v3_zooming_layout"
|
||||||
|
android:layout_marginTop="@dimen/dp_2"
|
||||||
|
android:src="@drawable/icon_right_arrow_image"
|
||||||
|
android:tint="@color/select_color" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rv_map_route_line_v3_fences_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/ll_map_route_line_v3_zooming_layout"
|
||||||
|
android:layout_marginStart="@dimen/dp_8"
|
||||||
|
android:layout_toEndOf="@id/iv_history_fence_start_image" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/dp_40"
|
||||||
|
android:background="@color/transparent" />
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
45
app/src/main/res/layout/item_history_fence_layout.xml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/iv_history_fence_type_image"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/icon_history_danger_fence_image" />
|
||||||
|
|
||||||
|
<com.abbidot.tracker.widget.TypefaceTextView
|
||||||
|
android:id="@+id/tv_history_fence_type_time"
|
||||||
|
style="@style/my_TextView_style_v2"
|
||||||
|
android:layout_alignTop="@id/iv_history_fence_type_image"
|
||||||
|
android:layout_alignBottom="@id/iv_history_fence_type_image"
|
||||||
|
android:layout_marginStart="@dimen/dp_8"
|
||||||
|
android:layout_toEndOf="@id/iv_history_fence_type_image"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textSize="@dimen/textSize16"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<com.abbidot.tracker.widget.TypefaceTextView
|
||||||
|
android:id="@+id/tv_history_fence_type_content"
|
||||||
|
style="@style/my_TextView_style_v2"
|
||||||
|
android:layout_below="@id/tv_history_fence_type_time"
|
||||||
|
android:layout_alignStart="@id/tv_history_fence_type_time"
|
||||||
|
android:layout_marginTop="@dimen/dp_6"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/select_color3"
|
||||||
|
android:textSize="@dimen/textSize14"
|
||||||
|
app:typeface="@string/roboto_regular_font" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/iv_history_fence_type_line"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/iv_history_fence_type_image"
|
||||||
|
android:layout_alignStart="@id/iv_history_fence_type_image"
|
||||||
|
android:layout_alignEnd="@id/iv_history_fence_type_image"
|
||||||
|
android:layout_marginTop="@dimen/dp_2"
|
||||||
|
android:src="@drawable/icon_vertical_dot_line_image" />
|
||||||
|
</RelativeLayout>
|
||||||
@@ -377,4 +377,5 @@
|
|||||||
<color name="rote_line_color">#00C478</color>
|
<color name="rote_line_color">#00C478</color>
|
||||||
<color name="light_yellow_color">#F9FFE8</color>
|
<color name="light_yellow_color">#F9FFE8</color>
|
||||||
<color name="grey_color_91">#B0B0B0</color>
|
<color name="grey_color_91">#B0B0B0</color>
|
||||||
|
<color name="grey_color_92">#758E94</color>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -262,7 +262,7 @@
|
|||||||
<string name="map_navigate_map_google">Google Map</string>
|
<string name="map_navigate_map_google">Google Map</string>
|
||||||
<string name="map_navigate_map_gaode">Gaode Map</string>
|
<string name="map_navigate_map_gaode">Gaode Map</string>
|
||||||
<string name="map_navigate_cancel">Cancel</string>
|
<string name="map_navigate_cancel">Cancel</string>
|
||||||
<string name="txt_no_install">The APP is not installed, please download and install the app first</string>
|
<string name="txt_no_install">Install the map app to navigate</string>
|
||||||
<!-- Data -->
|
<!-- Data -->
|
||||||
<string name="data_active_time">Active Time</string>
|
<string name="data_active_time">Active Time</string>
|
||||||
<string name="data_active_goal">Goal</string>
|
<string name="data_active_goal">Goal</string>
|
||||||
@@ -1076,4 +1076,7 @@
|
|||||||
<string name="txt_fully_asleep">Fell asleep %s ago</string>
|
<string name="txt_fully_asleep">Fell asleep %s ago</string>
|
||||||
<string name="txt_move_wake">Move %s to wake up</string>
|
<string name="txt_move_wake">Move %s to wake up</string>
|
||||||
|
|
||||||
|
<string name="map_navigate_map_baidu">Baidu Map</string>
|
||||||
|
<string name="txt_time_line">Timeline</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -39,7 +39,7 @@ class AppUtils {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据包名判断app是否安装
|
* 根据包名判断app是否安装 高版本不兼容
|
||||||
*/
|
*/
|
||||||
fun isAppInstalled(context: Context, packageName: String): Boolean {
|
fun isAppInstalled(context: Context, packageName: String): Boolean {
|
||||||
val pm = context.packageManager
|
val pm = context.packageManager
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ class Utils {
|
|||||||
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_EN11 = "dd/MM HH:mm"
|
||||||
const val DATE_FORMAT_PATTERN_EN12 = "HH:mm:ss"
|
const val DATE_FORMAT_PATTERN_EN12 = "HH:mm:ss"
|
||||||
|
const val DATE_FORMAT_PATTERN_EN13 = "MMM d | HH:mm"
|
||||||
|
const val DATE_FORMAT_PATTERN_EN14 = "HH:mm"
|
||||||
|
const val DATE_FORMAT_PATTERN_EN15 = "MM-dd HH:mm"
|
||||||
|
|
||||||
//返回星期几 简写
|
//返回星期几 简写
|
||||||
const val WEEK_FORMAT_PATTERN = "E"
|
const val WEEK_FORMAT_PATTERN = "E"
|
||||||
|
|||||||