From 69aa917897a3c22468778668fea44752933483c3 Mon Sep 17 00:00:00 2001 From: yezhiqiu <983577727@qq.com> Date: Tue, 14 Apr 2026 17:10:34 +0800 Subject: [PATCH] =?UTF-8?q?1.route=E9=A1=B5ui=E5=8A=9F=E8=83=BD=E6=94=B9?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compile-file-map.properties | 2 +- app/build.gradle | 6 +- app/src/main/AndroidManifest.xml | 1 - .../tracker/adapter/HistoryFenceAdapter.kt | 67 ++ .../tracker/adapter/NotificationV2Adapter.kt | 2 +- .../adapter/TopSlideLayoutManager.java | 40 ++ .../dialog/ShowCalenderAndTimeDialog.kt | 10 +- .../tracker/retrofit2/INetworkService.kt | 10 + .../abbidot/tracker/retrofit2/NetworkApi.kt | 7 + .../tracker/ui/activity/HomeV2Activity.kt | 14 +- .../ui/common/map/HistoryDataMapCommon.kt | 22 +- .../ui/fragment/data/RouteV2Fragment.kt | 8 +- .../ui/fragment/data/RouteV3Fragment.kt | 648 ++++++++++++++++++ .../tracker/ui/fragment/map/MapV3Fragment.kt | 135 +++- .../googlemap/HistoryDataGoogleMapFragment.kt | 20 +- .../java/com/abbidot/tracker/util/ViewUtil.kt | 2 +- .../abbidot/tracker/vm/DataDetailViewModel.kt | 17 +- .../tracker/widget/AppBarBehavior.java | 195 ++++++ .../tracker/widget/CustomLayoutManager.java | 39 ++ .../tracker/widget/NoClickSlideSeekBar.java | 84 +++ .../drawable-xhdpi/icon_bar_thumb_image.png | Bin 0 -> 428 bytes .../icon_history_danger_fence_image.png | Bin 0 -> 504 bytes .../icon_history_no_save_fence_image.png | Bin 0 -> 504 bytes .../icon_history_save_fence_image.png | Bin 0 -> 432 bytes .../drawable-xhdpi/icon_left_arrow_image.png | Bin 0 -> 252 bytes .../drawable-xhdpi/icon_right_arrow_image.png | Bin 0 -> 236 bytes .../icon_vertical_dot_line_image.png | Bin 0 -> 178 bytes .../drawable-xxhdpi/icon_bar_thumb_image.png | Bin 0 -> 633 bytes .../icon_history_danger_fence_image.png | Bin 0 -> 730 bytes .../icon_history_no_save_fence_image.png | Bin 0 -> 730 bytes .../icon_history_save_fence_image.png | Bin 0 -> 546 bytes .../drawable-xxhdpi/icon_left_arrow_image.png | Bin 0 -> 326 bytes .../icon_right_arrow_image.png | Bin 0 -> 305 bytes .../icon_vertical_dot_line_image.png | Bin 0 -> 186 bytes .../drawable-xxxhdpi/icon_bar_thumb_image.png | Bin 0 -> 797 bytes .../icon_history_danger_fence_image.png | Bin 0 -> 1001 bytes .../icon_history_no_save_fence_image.png | Bin 0 -> 1001 bytes .../icon_history_save_fence_image.png | Bin 0 -> 713 bytes .../icon_left_arrow_image.png | Bin 0 -> 399 bytes .../icon_right_arrow_image.png | Bin 0 -> 378 bytes .../icon_vertical_dot_line_image.png | Bin 0 -> 201 bytes app/src/main/res/drawable/shape8_gray_bg.xml | 4 +- .../res/drawable/shape_seek_bar_style_v3.xml | 18 + .../dialog_calender_and_time_layout.xml | 12 +- app/src/main/res/layout/fragment_route_v3.xml | 232 +++++++ .../res/layout/item_history_fence_layout.xml | 45 ++ app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/strings.xml | 5 +- .../com/abbidot/baselibrary/util/AppUtils.kt | 2 +- .../com/abbidot/baselibrary/util/Utils.kt | 3 + 50 files changed, 1584 insertions(+), 67 deletions(-) create mode 100644 app/src/main/java/com/abbidot/tracker/adapter/HistoryFenceAdapter.kt create mode 100644 app/src/main/java/com/abbidot/tracker/adapter/TopSlideLayoutManager.java create mode 100644 app/src/main/java/com/abbidot/tracker/ui/fragment/data/RouteV3Fragment.kt create mode 100644 app/src/main/java/com/abbidot/tracker/widget/AppBarBehavior.java create mode 100644 app/src/main/java/com/abbidot/tracker/widget/CustomLayoutManager.java create mode 100644 app/src/main/java/com/abbidot/tracker/widget/NoClickSlideSeekBar.java create mode 100644 app/src/main/res/drawable-xhdpi/icon_bar_thumb_image.png create mode 100644 app/src/main/res/drawable-xhdpi/icon_history_danger_fence_image.png create mode 100644 app/src/main/res/drawable-xhdpi/icon_history_no_save_fence_image.png create mode 100644 app/src/main/res/drawable-xhdpi/icon_history_save_fence_image.png create mode 100644 app/src/main/res/drawable-xhdpi/icon_left_arrow_image.png create mode 100644 app/src/main/res/drawable-xhdpi/icon_right_arrow_image.png create mode 100644 app/src/main/res/drawable-xhdpi/icon_vertical_dot_line_image.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_bar_thumb_image.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_history_danger_fence_image.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_history_no_save_fence_image.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_history_save_fence_image.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_left_arrow_image.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_right_arrow_image.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_vertical_dot_line_image.png create mode 100644 app/src/main/res/drawable-xxxhdpi/icon_bar_thumb_image.png create mode 100644 app/src/main/res/drawable-xxxhdpi/icon_history_danger_fence_image.png create mode 100644 app/src/main/res/drawable-xxxhdpi/icon_history_no_save_fence_image.png create mode 100644 app/src/main/res/drawable-xxxhdpi/icon_history_save_fence_image.png create mode 100644 app/src/main/res/drawable-xxxhdpi/icon_left_arrow_image.png create mode 100644 app/src/main/res/drawable-xxxhdpi/icon_right_arrow_image.png create mode 100644 app/src/main/res/drawable-xxxhdpi/icon_vertical_dot_line_image.png create mode 100644 app/src/main/res/drawable/shape_seek_bar_style_v3.xml create mode 100644 app/src/main/res/layout/fragment_route_v3.xml create mode 100644 app/src/main/res/layout/item_history_fence_layout.xml diff --git a/FastBleLib/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties b/FastBleLib/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties index 315de23..dd0f8d5 100644 --- a/FastBleLib/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +++ b/FastBleLib/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties @@ -1 +1 @@ -#Wed Apr 08 14:56:42 CST 2026 +#Thu Apr 09 17:00:19 CST 2026 diff --git a/app/build.gradle b/app/build.gradle index 629a992..f7b3141 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,9 +28,9 @@ android { applicationId "com.abbidot.tracker" minSdkVersion 23 targetSdkVersion 35 - versionCode 2113 -// versionName "2.1.13" - versionName "2.1.13-Beta3" + versionCode 2202 +// versionName "2.2.2" + versionName "2.2.2-Beta1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6e86bf7..497e206 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -55,7 +55,6 @@ android:protectionLevel="signature" /> - diff --git a/app/src/main/java/com/abbidot/tracker/adapter/HistoryFenceAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/HistoryFenceAdapter.kt new file mode 100644 index 0000000..784f064 --- /dev/null +++ b/app/src/main/java/com/abbidot/tracker/adapter/HistoryFenceAdapter.kt @@ -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? +) : BaseRecyclerAdapter(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 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/abbidot/tracker/adapter/NotificationV2Adapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/NotificationV2Adapter.kt index e74d003..1853e21 100644 --- a/app/src/main/java/com/abbidot/tracker/adapter/NotificationV2Adapter.kt +++ b/app/src/main/java/com/abbidot/tracker/adapter/NotificationV2Adapter.kt @@ -58,7 +58,7 @@ class NotificationV2Adapter( } private fun getRelativeTimeString(timeStamp: Long): String { - var formatDateStr = "" + val formatDateStr: String val cTimeStamp = Utils.stringToTimestamp( Utils.formatTime( timeStamp, Utils.DATE_FORMAT_PATTERN_CN2 diff --git a/app/src/main/java/com/abbidot/tracker/adapter/TopSlideLayoutManager.java b/app/src/main/java/com/abbidot/tracker/adapter/TopSlideLayoutManager.java new file mode 100644 index 0000000..acdcc25 --- /dev/null +++ b/app/src/main/java/com/abbidot/tracker/adapter/TopSlideLayoutManager.java @@ -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()); + } + } + } +} + diff --git a/app/src/main/java/com/abbidot/tracker/dialog/ShowCalenderAndTimeDialog.kt b/app/src/main/java/com/abbidot/tracker/dialog/ShowCalenderAndTimeDialog.kt index 4c46b97..6687a2f 100644 --- a/app/src/main/java/com/abbidot/tracker/dialog/ShowCalenderAndTimeDialog.kt +++ b/app/src/main/java/com/abbidot/tracker/dialog/ShowCalenderAndTimeDialog.kt @@ -25,7 +25,7 @@ import java.util.Calendar class ShowCalenderAndTimeDialog( context: Context, showCalenderTextView: TextView, - okListener: OnDialogOkListener? = null, + okListener: OnDialogSelectListener? = null, format: String = Utils.DATE_FORMAT_PATTERN_EN1, canSelectFutureDate: Boolean = false, calenderShowTimestamp: Long = 0, @@ -86,7 +86,7 @@ class ShowCalenderAndTimeDialog( 0, 23, 5, - 24, + 16, NumberPickerValueFill0Format(), this@ShowCalenderAndTimeDialog ) @@ -98,7 +98,7 @@ class ShowCalenderAndTimeDialog( 0, 59, 5, - 24, + 16, NumberPickerValueFill0Format(), this@ShowCalenderAndTimeDialog ) @@ -172,16 +172,18 @@ class ShowCalenderAndTimeDialog( }:${Utils.fill2Digits(npDialogCalenderMin.value)}:00" val timesTamp = Utils.stringToTimestamp(selectMonthYear) val nowTimestamp = System.currentTimeMillis() + if (timesTamp > nowTimestamp) { //时间戳还原 setSelectDate(nowTimestamp) mShowCalenderTextView.text = Utils.formatTime(nowTimestamp, mDateFormat) + mOkListener?.onSelectClick(this@ShowCalenderAndTimeDialog, nowTimestamp) } else { mShowCalenderTextView.text = Utils.stringToDate( selectMonthYear, Utils.DATE_FORMAT_PATTERN_CN2, mDateFormat ) + mOkListener?.onSelectClick(this@ShowCalenderAndTimeDialog, timesTamp) } - mOkListener?.onOkClick(this@ShowCalenderAndTimeDialog) dismiss() } } diff --git a/app/src/main/java/com/abbidot/tracker/retrofit2/INetworkService.kt b/app/src/main/java/com/abbidot/tracker/retrofit2/INetworkService.kt index 7cc08c7..8b41986 100644 --- a/app/src/main/java/com/abbidot/tracker/retrofit2/INetworkService.kt +++ b/app/src/main/java/com/abbidot/tracker/retrofit2/INetworkService.kt @@ -837,6 +837,16 @@ interface INetworkService { @Query("toTime") toTime: Long ): BaseResponse> + /** + * 获取设备进出围栏历史数据 + */ + @GET("data/getHistoryInOutFenceList") + suspend fun getHistoryFenceList( + @Query("deviceId") deviceId: String, + @Query("beginTimeStamp") fromTime: Long, + @Query("endTimeStamp") toTime: Long + ): BaseResponse> + /** * 设置运动目标 */ diff --git a/app/src/main/java/com/abbidot/tracker/retrofit2/NetworkApi.kt b/app/src/main/java/com/abbidot/tracker/retrofit2/NetworkApi.kt index 59fdcc3..181b31c 100644 --- a/app/src/main/java/com/abbidot/tracker/retrofit2/NetworkApi.kt +++ b/app/src/main/java/com/abbidot/tracker/retrofit2/NetworkApi.kt @@ -753,6 +753,13 @@ object NetworkApi : BaseNetworkApi(INetworkService.BASE_URL) { service.getHistoryByDay(deviceId, fromTime, toTime) } + /** + * 获取设备进出围栏历史数据 + */ + suspend fun getHistoryFenceList(deviceId: String, fromTime: Long, toTime: Long) = getResult { + service.getHistoryFenceList(deviceId, fromTime, toTime) + } + /** * 设置运动目标 */ diff --git a/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt b/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt index 4d33214..719f3f8 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt @@ -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.fragment.account.AccountV2Fragment 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.pet.PetV2Fragment import com.abbidot.tracker.util.SocketUtilManage @@ -111,7 +111,7 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding private val mFragments = mutableListOf( ActivityV2Fragment.newInstance(this), - RouteV2Fragment.newInstance(this), + RouteV3Fragment.newInstance(this), MapV3Fragment.newInstance(this), PetV2Fragment.newInstance(this), AccountV2Fragment.newInstance(this) @@ -460,7 +460,7 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding onChangeClick(mSelectPetPosition) when (mViewBinding.homeV2ViewPager2.currentItem) { 0 -> { - (mFragments[1] as RouteV2Fragment).setNeedUpdateTag() + (mFragments[1] as RouteV3Fragment).setNeedUpdateTag() (mFragments[3] as PetV2Fragment).setNeedUpdateTag() } @@ -471,13 +471,13 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding 2, 4 -> { (mFragments[0] as ActivityV2Fragment).setNeedUpdateTag() - (mFragments[1] as RouteV2Fragment).setNeedUpdateTag() + (mFragments[1] as RouteV3Fragment).setNeedUpdateTag() (mFragments[3] as PetV2Fragment).setNeedUpdateTag() } 3 -> { (mFragments[0] as ActivityV2Fragment).setNeedUpdateTag() - (mFragments[1] as RouteV2Fragment).setNeedUpdateTag() + (mFragments[1] as RouteV3Fragment).setNeedUpdateTag() } } } @@ -638,7 +638,7 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding fun refreshLocationBtnState() { when (mViewBinding.homeV2ViewPager2.currentItem) { 0 -> (mFragments[0] as ActivityV2Fragment).checkNotifyLocationState() - 1 -> (mFragments[1] as RouteV2Fragment).checkNotifyLocationState() + 1 -> (mFragments[1] as RouteV3Fragment).checkNotifyLocationState() 3 -> (mFragments[3] as PetV2Fragment).checkNotifyLocationState() } } @@ -654,7 +654,7 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding mChangePetListDialogAdapter.setSelectPetPos(mSelectPetPosition) when (mViewBinding.homeV2ViewPager2.currentItem) { 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) 3 -> (mFragments[3] as PetV2Fragment).showPetNameAndHead(position) } diff --git a/app/src/main/java/com/abbidot/tracker/ui/common/map/HistoryDataMapCommon.kt b/app/src/main/java/com/abbidot/tracker/ui/common/map/HistoryDataMapCommon.kt index 17bde2d..8ca6798 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/common/map/HistoryDataMapCommon.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/common/map/HistoryDataMapCommon.kt @@ -1,8 +1,10 @@ package com.abbidot.tracker.ui.common.map import android.content.Context +import androidx.appcompat.widget.AppCompatSeekBar import androidx.fragment.app.Fragment import com.abbidot.baselibrary.util.AppUtils +import com.abbidot.baselibrary.util.LogUtil import com.abbidot.tracker.base.BaseMapCommon import com.abbidot.tracker.bean.HistoryDataBean 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.vm.GeoCoderViewModel import com.abbidot.tracker.widget.MapMarkerInfoView -import com.abbidot.tracker.widget.VerticalTopToBottomSeekBar /** *Created by .yzq on 2022/7/5/005. @@ -26,7 +27,7 @@ class HistoryDataMapCommon : BaseMapCommon() { context: Context, markerInfoView: MapMarkerInfoView, geoCoderViewModel: GeoCoderViewModel, - verticalTopToBottomSeekBar: VerticalTopToBottomSeekBar, + verticalTopToBottomSeekBar: AppCompatSeekBar, mapLoadOk: () -> Unit ): Fragment { return if (AppUtils.isChina(AppUtils.SWITCH_MAP_TYPE)) { @@ -102,10 +103,15 @@ class HistoryDataMapCommon : BaseMapCommon() { } fun setLatLngData(data: MutableList) { - if (null != mHistoryDataBaiduMapFragment) { - mHistoryDataBaiduMapFragment!!.setLatLngData(data) - } else if (null != mHistoryDataGoogleMapFragment) { - mHistoryDataGoogleMapFragment!!.setLatLngData(data) + if (data.size == 0) return + try { + if (null != mHistoryDataBaiduMapFragment) { + mHistoryDataBaiduMapFragment!!.setLatLngData(data) + } else if (null != mHistoryDataGoogleMapFragment) { + mHistoryDataGoogleMapFragment!!.setLatLngData(data) + } + } catch (e: Exception) { + LogUtil.e("setLatLngData异常:${e.message}") } } @@ -117,6 +123,10 @@ class HistoryDataMapCommon : BaseMapCommon() { } } + fun resetMarkerInfoViewOffset() { + mHistoryDataGoogleMapFragment?.resetMarkerInfoViewOffset() + } + fun setPetUserLatLng() { if (null != mHistoryDataBaiduMapFragment) { } else if (null != mHistoryDataGoogleMapFragment) { diff --git a/app/src/main/java/com/abbidot/tracker/ui/fragment/data/RouteV2Fragment.kt b/app/src/main/java/com/abbidot/tracker/ui/fragment/data/RouteV2Fragment.kt index e67868f..7c2b941 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/fragment/data/RouteV2Fragment.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/fragment/data/RouteV2Fragment.kt @@ -449,8 +449,8 @@ class RouteV2Fragment : BaseFragment(FragmentRouteV2Bind mFromCalenderDialog = ShowCalenderAndTimeDialog( mContext!!, tvHomeRouteCalendarFrom, - object : BaseDialog.OnDialogOkListener { - override fun onOkClick(dialog: BaseDialog<*>) { + object : BaseDialog.OnDialogSelectListener { + override fun onSelectClick(dialog: BaseDialog<*>, any: Any) { mCurrentTimestamp = System.currentTimeMillis() isSelectCustomDate = true getHistoryDay(tvHomeRouteCalendarFrom) @@ -477,8 +477,8 @@ class RouteV2Fragment : BaseFragment(FragmentRouteV2Bind mToCalenderDialog = ShowCalenderAndTimeDialog( mContext!!, tvHomeRouteCalendarTo, - object : BaseDialog.OnDialogOkListener { - override fun onOkClick(dialog: BaseDialog<*>) { + object : BaseDialog.OnDialogSelectListener { + override fun onSelectClick(dialog: BaseDialog<*>, any: Any) { isSelectCustomDate = true getHistoryDay(tvHomeRouteCalendarTo) } diff --git a/app/src/main/java/com/abbidot/tracker/ui/fragment/data/RouteV3Fragment.kt b/app/src/main/java/com/abbidot/tracker/ui/fragment/data/RouteV3Fragment.kt new file mode 100644 index 0000000..40858d8 --- /dev/null +++ b/app/src/main/java/com/abbidot/tracker/ui/fragment/data/RouteV3Fragment.kt @@ -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::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() + 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() + + //充值续费或升级返回类型 + 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) { + 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) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/MapV3Fragment.kt b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/MapV3Fragment.kt index 6e00a34..795cac6 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/MapV3Fragment.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/MapV3Fragment.kt @@ -28,17 +28,20 @@ import com.abbidot.baselibrary.util.MMKVUtil import com.abbidot.baselibrary.util.Utils import com.abbidot.tracker.R import com.abbidot.tracker.adapter.HomeMapDeviceStateAdapter +import com.abbidot.tracker.adapter.SelectMapListDialogAdapter import com.abbidot.tracker.base.BaseDialog import com.abbidot.tracker.base.BaseFragment import com.abbidot.tracker.bean.BleReportDataBean import com.abbidot.tracker.bean.BleTrackDeviceBean import com.abbidot.tracker.bean.DataBean import com.abbidot.tracker.bean.MapDeviceBean +import com.abbidot.tracker.bean.MenuTxtBean import com.abbidot.tracker.constant.ConstantInt import com.abbidot.tracker.constant.ConstantString import com.abbidot.tracker.constant.GetResultCallback import com.abbidot.tracker.databinding.FragmentMapV3Binding import com.abbidot.tracker.dialog.CommonDialog1 +import com.abbidot.tracker.dialog.SelectMapListDialog import com.abbidot.tracker.dialog.SelectMapTypeDialog import com.abbidot.tracker.ui.activity.HomeV2Activity import com.abbidot.tracker.ui.activity.map.LiveActivityV3 @@ -104,6 +107,13 @@ class MapV3Fragment : BaseFragment(FragmentMapV3Binding::i private var needGpsToGCJ02 = true 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 @@ -909,28 +919,110 @@ class MapV3Fragment : BaseFragment(FragmentMapV3Binding::i } } - private fun goNavigation() { - mMapDeviceBean?.let { m -> - try { - //自动弹出手机中已经有安装地图的应用 - val uri = if (MMKVUtil.getBoolean(MMKVKey.isGpsToGCJ02)) { - val convertLatLon = - LonAndLatUtil.convertFromWGS84ToGCJ02(m.latitude, m.longitude) - "google.navigation:q=${convertLatLon[0]},${convertLatLon[1]}&mode=w".toUri() - } else { - "google.navigation:q=${m.latitude},${m.longitude}&mode=w".toUri() +// private fun goNavigation() { +// mMapDeviceBean?.let { m -> +// try { +// //自动弹出手机中已经有安装地图的应用 +// val uri = if (MMKVUtil.getBoolean(MMKVKey.isGpsToGCJ02)) { +// val convertLatLon = +// LonAndLatUtil.convertFromWGS84ToGCJ02(m.latitude, m.longitude) +// "google.navigation:q=${convertLatLon[0]},${convertLatLon[1]}&mode=w".toUri() +// } else { +// "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() + 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) + intent.setPackage(item.menuValue) + 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) + } } - 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)) + showToast(getString(R.string.txt_no_install), gravity = Gravity.CENTER) } } } override fun onClick(v: View?) { - if (isLimitClick()) return mViewBinding.apply { when (v!!) { homeMapRefreshBtn -> { @@ -964,6 +1056,7 @@ class MapV3Fragment : BaseFragment(FragmentMapV3Binding::i } homeMapLiveBtn -> { + if (isLimitClick()) return if (!isCanLive) { showToast(R.string.txt_live_works_cellular, gravity = Gravity.CENTER) return @@ -974,7 +1067,11 @@ class MapV3Fragment : BaseFragment(FragmentMapV3Binding::i ivHomeMapRefreshLocation -> notifyRefreshLocation() llHomeMapTopPet.ivTopPetBtnSmall -> showMapTypeDialog() - homeMapBluetoothBtn -> checkPermissions(1) + homeMapBluetoothBtn -> { + if (isLimitClick()) return + checkPermissions(1) + } + llHomeMapTopPet.homeDataPetNameSmall, llHomeMapTopPet.homeDataPetHeadSmall.root -> { getHomeV2Activity()?.let { if (!it.isNotifyRefreshLocation) { @@ -993,7 +1090,11 @@ class MapV3Fragment : BaseFragment(FragmentMapV3Binding::i ilHomeMapDeviceMsg.root.visibility = View.GONE } - ilHomeMapPetLocation.ivPetLocationNavigationBtn -> goNavigation() + ilHomeMapPetLocation.ivPetLocationNavigationBtn -> { + if (isLimitClick()) return +// goNavigation() + showNavigationDialog() + } } } } diff --git a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HistoryDataGoogleMapFragment.kt b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HistoryDataGoogleMapFragment.kt index e832f9f..b6294c3 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HistoryDataGoogleMapFragment.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/fragment/map/googlemap/HistoryDataGoogleMapFragment.kt @@ -3,6 +3,7 @@ package com.abbidot.tracker.ui.fragment.map.googlemap import android.content.Context import android.graphics.BitmapFactory import android.graphics.Typeface +import androidx.appcompat.widget.AppCompatSeekBar import androidx.core.view.isVisible import com.abbidot.baselibrary.constant.MMKVKey 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.vm.GeoCoderViewModel 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.model.BitmapDescriptor import com.google.android.gms.maps.model.BitmapDescriptorFactory @@ -32,7 +32,7 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() { // private val mScreenshotsViewModel: ScreenshotsViewModel by viewModels() private lateinit var mGeoCoderViewModel: GeoCoderViewModel private lateinit var mMarkerInfoView: MapMarkerInfoView - private lateinit var mVerticalTopToBottomSeekBar: VerticalTopToBottomSeekBar + private lateinit var mVerticalTopToBottomSeekBar: AppCompatSeekBar private val mMarkerOptions = MarkerOptions() private lateinit var mPetIconDescriptor: BitmapDescriptor @@ -55,7 +55,7 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() { context: Context, markerInfoView: MapMarkerInfoView, geoCoderViewModel: GeoCoderViewModel, - verticalTopToBottomSeekBar: VerticalTopToBottomSeekBar, + verticalTopToBottomSeekBar: AppCompatSeekBar, mapLoadOk: () -> Unit ) = HistoryDataGoogleMapFragment().apply { mContext = context @@ -97,9 +97,7 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() { if (getGoogleMapZoom() != cameraPosition.zoom) { setGoogleMapZoom(cameraPosition.zoom) } - mCurLatLng?.let { - if (mMarkerInfoView.isVisible) setMarkerInfoViewOffset(mMarkerInfoView, it) - } + resetMarkerInfoViewOffset() } setOnMarkerClickListener { m -> //点击数字大头针回到该位置 @@ -123,6 +121,12 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() { if (::mMapLoadOk.isInitialized) mMapLoadOk() } + fun resetMarkerInfoViewOffset() { + mCurLatLng?.let { + if (mMarkerInfoView.isVisible) setMarkerInfoViewOffset(mMarkerInfoView, it) + } + } + suspend fun setPetBean(petBean: PetBean) { if (petBean == mPetBean) { return @@ -153,7 +157,7 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() { mGoogleMap?.clear() if (data.size == 0) return - + mLatLngList.clear() var maxLat = data[0].latitude var maxLon = data[0].longitude var minLat = data[0].latitude @@ -195,7 +199,7 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() { * 滑动改变 */ fun slideChanged(progress: Int) { - setPetMarkerLatLng(mLatLngList[progress]) + if (progress < mLatLngList.size) setPetMarkerLatLng(mLatLngList[progress]) } /** diff --git a/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt b/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt index 68f9c3e..4491637 100644 --- a/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt +++ b/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt @@ -206,7 +206,7 @@ class ViewUtil private constructor() { ) { numberPicker.apply { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { - selectionDividerHeight = AppUtils.dpToPx(1) + selectionDividerHeight = AppUtils.dpToPx(0.5f).toInt() if (tSize > 0) { textSize = QMUIDisplayHelper.sp2px(context, tSize).toFloat() } diff --git a/app/src/main/java/com/abbidot/tracker/vm/DataDetailViewModel.kt b/app/src/main/java/com/abbidot/tracker/vm/DataDetailViewModel.kt index cc440e7..b4c7053 100644 --- a/app/src/main/java/com/abbidot/tracker/vm/DataDetailViewModel.kt +++ b/app/src/main/java/com/abbidot/tracker/vm/DataDetailViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope import com.abbidot.tracker.base.BaseActivity import com.abbidot.tracker.bean.ActiveTimeBean import com.abbidot.tracker.bean.HistoryDataBean +import com.abbidot.tracker.bean.MessageBean import com.abbidot.tracker.bean.SleepTimeBean import com.abbidot.tracker.retrofit2.NetworkApi import kotlinx.coroutines.launch @@ -20,6 +21,7 @@ class DataDetailViewModel : ViewModel() { val mActiveDetailLiveData = MutableLiveData>() val mSleepDetailLiveData = MutableLiveData>() val mHistoryDetailLive = MutableLiveData>>() + val mHistoryFenceEvents = MutableLiveData>>() val mSetGoalLiveData = MutableLiveData>() val mPetActivityInfoLiveData = MutableLiveData>() @@ -40,10 +42,7 @@ class DataDetailViewModel : ViewModel() { * 获取SleepTime数据 */ fun getSleepTimeByDay( - activity: BaseActivity<*>, - deviceId: String, - dayTime: String, - petId: String + activity: BaseActivity<*>, deviceId: String, dayTime: String, petId: String ) { activity.showLoading(true) 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 diff --git a/app/src/main/java/com/abbidot/tracker/widget/AppBarBehavior.java b/app/src/main/java/com/abbidot/tracker/widget/AppBarBehavior.java new file mode 100644 index 0000000..280d846 --- /dev/null +++ b/app/src/main/java/com/abbidot/tracker/widget/AppBarBehavior.java @@ -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); + } + +} diff --git a/app/src/main/java/com/abbidot/tracker/widget/CustomLayoutManager.java b/app/src/main/java/com/abbidot/tracker/widget/CustomLayoutManager.java new file mode 100644 index 0000000..210f194 --- /dev/null +++ b/app/src/main/java/com/abbidot/tracker/widget/CustomLayoutManager.java @@ -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); + } +} + diff --git a/app/src/main/java/com/abbidot/tracker/widget/NoClickSlideSeekBar.java b/app/src/main/java/com/abbidot/tracker/widget/NoClickSlideSeekBar.java new file mode 100644 index 0000000..2156bf7 --- /dev/null +++ b/app/src/main/java/com/abbidot/tracker/widget/NoClickSlideSeekBar.java @@ -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; + } + +} + + + diff --git a/app/src/main/res/drawable-xhdpi/icon_bar_thumb_image.png b/app/src/main/res/drawable-xhdpi/icon_bar_thumb_image.png new file mode 100644 index 0000000000000000000000000000000000000000..ecfc4886f45cff0d60fd2c5eadaa4fb8372a988a GIT binary patch literal 428 zcmV;d0aN~oP)KzJ@Etm?-EDGZ@BH-3b(UDVs}s$TowtLmy^6jm-o8a;xV zFYtV=(M7y|nXXkFs9qTyDq-57SmyJBP)U-?=+KVzl9`5NF$K1vF5~sI6E?Or1P7_? zlXl2nNs(FCFq@yoz{qT8hnL7z%`8`7%XI@!_@~!{kxe8AIkT70$=ElX``4|2O@R-| WAt-fY?5q?30000Eo3Gn!Rr->iC48UUr~J4pXZN3}N-)CBsd}5vs>V?% zI$CR~?fcH!Y!3?PXvr=*Fi}9eGviM$<*ZSO**f zcx$D#l^LRv))wZFDrqe+L3*6%nX|HhG;70+&a{Y31-2lkjI|YcMfQlXbI|6+lM%hW uQOMF;Sd(=2c4*_oi>Lit^}Mp0ZTkVW7aa9IA#!~H0000!otG6y}i7=yt})*xVX3;yT6A3000YgQchC}0Dpu) zzrsgHgu?C(6E6S&010qNS#tmY3labT3lag+-G2N400Cf0L_t(IPnFcsc7z}d1W-f} zUH$*>Eo3Gn!Rr->iC48UUr~J4pXZN3}N-)CBsd}5vs>V?% zI$CR~?fcH!Y!3?PXvr=*Fi}9eGviM$<*ZSO**f zcx$D#l^LRv))wZFDrqe+L3*6%nX|HhG;70+&a{Y31-2lkjI|YcMfQlXbI|6+lM%hW uQOMF;Sd(=2c4*_oi>Lit^}Mp0ZTkVW7aa9IA#!~H0000iW*Bv`{xEJ_r-@bk4&YeIu zgxt1m8=O7kLheJLVy==Pzu^504)yonpD&ny{^P~&&p=Vm0*}aI1_o{+5N5n|x9$%E z1EajBi(`m||J}*A`wkm$xNv@X_5c3^KIUzm!fTb@2A_6Le!Tc$)J?rvF;BMDH)naT zD0ZEEZB}NgzvJ;ct6p)gIM<>3L{No&?Z2}>*e7^Rloftkxh~=1wzK+kV;t(W))n1t z{_HsQ;mZe^?0rjSFwA$;5-oXm?8)NZkg8PSX)Q*Mq7hRL>TTu8P5MwI*IpJnfyJZR z&!BtZq90cl9;lf)(ONQJ%($kaz_R0!$$=oB@2oRUFnm91;MLR-DtcP!ohWaDj!#%` zR8cPXjH5mQuOEpSNWFOLn?7Yzi4uEN`T~ZX92+v~LtP$Dyv1O-cgJ6y6}RND#&cW|aD+ZTngAY3sSz|J<+ZS%r7*trhuk@A>-saxWJ@a{bNrfw?_W=<8ii S11DhkF?hQAxvXX) zI~QdYfKn_aL4Lsu_4^%u?%yQ<4nJa0`Jj{Oot* z+@?0WIj`um*v({JahPLz1S+?d7QaHE~a6zCiVPgg&ebxsLQ0CDtOB>(^b literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/icon_right_arrow_image.png b/app/src/main/res/drawable-xhdpi/icon_right_arrow_image.png new file mode 100644 index 0000000000000000000000000000000000000000..6f84105f976830232b5c1920648dfb8e27d14d6d GIT binary patch literal 236 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)r!3-puC-%4iDgFST5LfpCpOXHmrF~OM`X>X) zI~QdYfKn_aL4Lsu_4^%u?%yQ<4nJa0`Jj24)@qiyop c9;*(yIc@CCJR5%T0Ig^6boFyt=akR{0LQLVhX4Qo literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/icon_vertical_dot_line_image.png b/app/src/main/res/drawable-xhdpi/icon_vertical_dot_line_image.png new file mode 100644 index 0000000000000000000000000000000000000000..83af35c95c8272beb5ecf05868c8eacb57eb1e2e GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^OhBB&!3-qJr%kp2Qv3lvA+FD!J$wB4v3r5fQ!wym z*na^i#ZnUF7rftrq26uLO=}>Zv%n*=n1O*?2!t6g-L3lr6twhoaSV|NPfkcoWKdF5 z(@08TDOBX(c<|`V8IHmQQadaHcw=m11Wp{t;@I@ifqA1;Q;x-*2?yUgF=QNOvfLA7 RdlYC0gQu&X%Q~loCIG2?IhX(d literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/icon_bar_thumb_image.png b/app/src/main/res/drawable-xxhdpi/icon_bar_thumb_image.png new file mode 100644 index 0000000000000000000000000000000000000000..def6bc4a7d25a46bb84fdc7858ddd77d37c33661 GIT binary patch literal 633 zcmV-<0*3vGP)^ZrruDc-cT^MKs^8e00eYWPE!DX zzd-rFx)1;W010qNS#tmY3labT3lag+-G2N400HGmL_t(oN9~x~a)lraMFm>%`v1S% zTu^fq5g~o(6kj^0gUdaepvmsK>*b8G_B-#g)*2UKT>fQD9#F2b_6c184G&0>H|j8W z|CM)n@5hnQ_nH|yHekew7YdqM{=!NhYvGr;Zj*1V9@z7SAzyRq4%B|ZnQOW`gay86lI9kk3pj;&v zKAcdh1z8h8u1+m%;NUR0tIGw4@o)fFs~A`@o@d%MUAa`lu7fv&HkXW0w}DDH$(^Q2 z*7fP>Rf{)Q#RWLN`=q_I9u+~U~!_b}-C~h5KH@UoZIztiW52s*5 z<20Z061KQr@g?73aOLL3@~8l=@gkm|alBFf&b-b008E+hIKD4s&(urUwF1HM6p1d zt^1!hpxGDXq$+&bk{;bNY(sfvZLO`f>$+O2bxpr0@##7U-CB(wc`iWEK~S~agt|$q zX}IbP+P{X>oR7=*qCw$S{n>FW+g7%1Sq}YJa?70Zcx*+tWf7Dmi4)9GqX$KjB65r+ zlqC^Fj+`vUp>a!}00d4A$n(K$$r7%h+M0mJJY8kLO3ArzM=SI7Pm1pRtf%a&{oE(n$~+h17j z-alams0h2SH|=L;FN80z=Y2QspCSk63U>3`eV)%FIv}Qp7`(vl`CQ?1%!WAGaudG#_Pzr&=-Qlq^v)0U%>o&l=~dL)Y|&BYC_F?#{BswKS%9Ca6Rq1*#H0l M07*qoM6N<$f^ZB~3IG5A literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/icon_history_no_save_fence_image.png b/app/src/main/res/drawable-xxhdpi/icon_history_no_save_fence_image.png new file mode 100644 index 0000000000000000000000000000000000000000..93c4915ad9e705a44a260d32aeffb59fdf1e5e96 GIT binary patch literal 730 zcmV<00ww*4P)F1HM6p1d zt^1!hpxGDXq$+&bk{;bNY(sfvZLO`f>$+O2bxpr0@##7U-CB(wc`iWEK~S~agt|$q zX}IbP+P{X>oR7=*qCw$S{n>FW+g7%1Sq}YJa?70Zcx*+tWf7Dmi4)9GqX$KjB65r+ zlqC^Fj+`vUp>a!}00d4A$n(K$$r7%h+M0mJJY8kLO3ArzM=SI7Pm1pRtf%a&{oE(n$~+h17j z-alams0h2SH|=L;FN80z=Y2QspCSk63U>3`eV)%FIv}Qp7`(vl`CQ?1%!WAGaudG#_Pzr&=-Qlq^v)0U%>o&l=~dL)Y|&BYC_F?#{BswKS%9Ca6Rq1*#H0l M07*qoM6N<$f=_{2H~;_u literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/icon_history_save_fence_image.png b/app/src/main/res/drawable-xxhdpi/icon_history_save_fence_image.png new file mode 100644 index 0000000000000000000000000000000000000000..1249ea4502c000a6dedce068be8fe5af710577a1 GIT binary patch literal 546 zcmV+-0^R+IP)0rF)GOSQZc2rszkp_JMn3nmj$qh+ z2^|8pB$mXJB+sI`L_=xMq376?_U8LMJVVC8>y*ub**sSK$?!$NeNEJ4Vvxg<@#2%? zRClYp*sPMsBwtHQs5MUpJFD_ZVQ;l+q9AVpx?Tgu^*@5!Sggl^o<>e^w21)IBI0q(E9XrUY2n?yQB$}#D= ze=Jze?`?ZX_kkmy?dJg>GW%-ZFW5n=+UKMHeJ}0&$u)LrbJ)b(UxB|08y`ZI3q)~0 kqN7g2N4yyCnZK;S50MBTv{*D#VgLXD07*qoM6N<$g8w}CYybcN literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/icon_left_arrow_image.png b/app/src/main/res/drawable-xxhdpi/icon_left_arrow_image.png new file mode 100644 index 0000000000000000000000000000000000000000..6e4349165f2d16f25e6983746f9a447b134fdd77 GIT binary patch literal 326 zcmeAS@N?(olHy`uVBq!ia0vp^>Oic`!3-qN>`$x#Qv3lvA+GKPJ|+EAOZ%pj^iKwo zcP`2*0Hs(;g8YIR>i0YR+`mfz$mcBZh%9Dc;1&X5#!GkW{s0Bfdb&7DpTU#6#l|6djT_OvNKm`Wb~-1mhgx;rHP4davu WfsfkD_Iw6Oic`!3-qN>`$x#Qv3lvA+GKPJ|+EAOZq35_Dunz zl|EnZ1Ep9>g8YIR>K*pG&s^~y$mcBZh%9Dc;1&X5#!GkW{s0Acc)B=-Sop8K>dn-u zz`+_I@NNIIFF()7$4FdR!nT}yn!M5?rA24HGRCj@%k?BdR7}7^vhR+J#=rc$dvnb6 zpZ7d3D=R!5d8te*eRkh&rPy+h2WFgiKWT5AJ#nJ6QQ4|oxzw0u&G3iY{U%k;D!FOn z_e}M8w0iQh-CHcBt$*tNKT#^Wt6ckMf?fZl9q*R?`B(J%`@Nnug)*vh|LLTDdH$w; ylek!Zx8CZ_-rvI06@s{V{H4}SWa8&v#LoU$;D4~wgQ-A2FnGH9xvXC>mro;?GS zYYL@}fl@3bL4Lsu4)yyD3KZ&qe9i)o$YKTtZXpn6ymYtj4^Yt2)5S4FBRDxBF)^_r zkxi#z;zU8c{x#D&J2__;v8AP@t$DRF(d>j@iur*X3g$`7H?B0@Y3B_%oHL>J%7^D1 bJkAUkzA&GybD!T0G>pO1)z4*}Q$iB}e!D>| literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/icon_bar_thumb_image.png b/app/src/main/res/drawable-xxxhdpi/icon_bar_thumb_image.png new file mode 100644 index 0000000000000000000000000000000000000000..cd6cfc867cce173274c4c13d9d52d60a848e8e3c GIT binary patch literal 797 zcmV+&1LFLNP)EX0000aP)t-sM{rEJ zxw*KwxVN{rxVX5v|4x#l>xs4`h zl&sak$7wQq&H-#9e0-Fb3Cr5g>Se7p#<`PkF8s-v2HO7T*-EadR+qoQTDIO^Ncl8>WSOfsNU7pGZF-aqWp%7cIFha@8EM<;X^B zJ0bz@Nl77%iP;$mSc+{nu)~;1Y=%0JS)@`9H54VUu%>KWu~vpLL-8PWUpdGekVC5v zn8dq!#efcF#<*^i379i4I_+1X*41DX+Wu|aJ9pKJnLF6rWp7GSA&Z8a3)GEN6gse4 z4jD{R#e~u>ObHB75uvecfQjyM6Y%bJz=D5rP%k2BloA;H6?B*U4SS)eyHqs<6>~S` zFN9QJH%b`@{u<09aVRH`zQZ~e%Wqi6&vMrtt|6tZ&>VmPg(nF643x7UaaA#tQq3rI zn{{e$L!D|Oy*?diB55L>Ju~Xw`{It4jFya+OgaM42eVx+{EyAyecoj_@24GON^fl( zXl{r339I3N=fO8|(PJb!=m@7*oOi_r9}Bm{BQvNOv6BwUBRZxNgGP5{kId46BnDMT zYI0Z9UvM|}X2hgo8!GlRg*qfuq)QV@NGf)NmgcRHRA6rUULsPlVZ7-pKGNXBW680_ z`r68*ZGU8U2CL;b?(j%^8u$HS4%4hdX4GLIm6#`k4g=aHCrsM;`&%5xNQ#p>j)rvR zjy=YRERC)#ZOx9@GzxV#8WbO1I?44(Wj=*=gBH7SuQ0h)|0D?0URC2>(8awyyhjO1 z>w3a0N_H(Hid#}W63OnqUTfGxgKK=9gQ?60uVE_Fux-5@@Y4&_0d+tfPzTfjbwC|> b4+s7L>SDTI;Qq(400000NkvXXu0mjfVK-{Q literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/icon_history_danger_fence_image.png b/app/src/main/res/drawable-xxxhdpi/icon_history_danger_fence_image.png new file mode 100644 index 0000000000000000000000000000000000000000..1b1b1adf4a1363ef19ae4c28bad103b797ab330d GIT binary patch literal 1001 zcmV)z*SbE_bsR_foaZ(C-N)p9z0R3|SK|3N54E-UPLQDb$#x3#eI$YDn+p^?FUyls=cG zNexUiK&g1YGXyS81C~SqspXtdrA@K~N|GGVMUzGai&2uaXlH2iEnv(dl!$mF>0(M@ z#HuJkiX}CyXMMp7YGuhIq?8@}2Q|M6>MjXb#o~oxdt;iiOV(8^UMLbZPLiz4;)xSK_;U(KqKKT+fl<7#QjaK);q&>g%7ckID8Ikd#GsNT@eFEJC5I>hQ^`FjQ`&nrLybNEK{Up{VZ; z25PV#Q%%qtD0J9C={H9Cy`w4&l}fFSsyirpb*2i1Sp9}F!~T!4`VCcI9LRRBEL_GR zuWBJp*4HVRwikd}bfMf|BLYb)xm{DfjBZpZ0M3EsBmWDu<-BRY#M|&4!mM;rM zK|vrm7Ms_BmDVmaSYWvQyY@kEceYrHM0GDW4Y_BahE}x&Elcl$e?wta}d5LBi z)*-GRdgFw{2F0s*beGX2$(hXX>B}a;cxUuX$Y}uc0XWf*v6w`sN|~Z%8N~V7jlDQH z)8ZK@ei^;kzXVB*#`H|4qf11*Gf0so)zTG_i~(JsD?a%Y}>!EBimeh$=aj?$m9{?RiqGvF}e)HxZ X&yaQ?)z*SbE_bsR_foaZ(C-N)p9z0R3|SK|3N54E-UPLQDb$#x3#eI$YDn+p^?FUyls=cG zNexUiK&g1YGXyS81C~SqspXtdrA@K~N|GGVMUzGai&2uaXlH2iEnv(dl!$mF>0(M@ z#HuJkiX}CyXMMp7YGuhIq?8@}2Q|M6>MjXb#o~oxdt;iiOV(8^UMLbZPLiz4;)xSK_;U(KqKKT+fl<7#QjaK);q&>g%7ckID8Ikd#GsNT@eFEJC5I>hQ^`FjQ`&nrLybNEK{Up{VZ; z25PV#Q%%qtD0J9C={H9Cy`w4&l}fFSsyirpb*2i1Sp9}F!~T!4`VCcI9LRRBEL_GR zuWBJp*4HVRwikd}bfMf|BLYb)xm{DfjBZpZ0M3EsBmWDu<-BRY#M|&4!mM;rM zK|vrm7Ms_BmDVmaSYWvQyY@kEceYrHM0GDW4Y_BahE}x&Elcl$e?wta}d5LBi z)*-GRdgFw{2F0s*beGX2$(hXX>B}a;cxUuX$Y}uc0XWf*v6w`sN|~Z%8N~V7jlDQH z)8ZK@ei^;kzXVB*#`H|4qf11*Gf0so)zTG_i~(JsD?a%Y}>!EBimeh$=aj?$m9{?RiqGvF}e)HxZ X&yaQ?sxVgExxVX5uxVX5uxVgExwzjspxw*KwxU-=cIRF3v3UpFVQvg7}f8Woa&v5Th zvk1lj000SaNLh0L01FZT01FZU(%pXi0006wNkl4AY`u`uiyz&wP zRP1TtvWj5{nPftDS>~7#_;Ccxx}K}GPwisQG@gMpE8w}m4>)NUoO@hHkB!GgTr&ij zr; zT31M>&di8wB1<{~)K#1<<-59`7l#l+=J>@$V{MwzZ3^X}7(-5k&C5qtYO8!?f(VG# z_46aJ+HOS=@a0x0@rD3JLjjmo3Teb;W6{(^AemvQQc!dxplp(f{mjE^9!kJu3M=Br z46s}&xt&`ZO~Z5`?r9^ zMU|9(51}Et@&R^AF~mA?51D+)Je0T7RC^avTzT_B5>_Zt*0WRkWGssdHm0qT4N|Z0 zJ}!2a?g_-AhfD!cjk#gzMjR?Z5eM&M@`2R74XBhT5ayYADeT2FLQ8Q!r+Ny&1M=>} zJ>=;W6unxa$*XSw>oq?Cf#@13GltmMgk;V<6m9fc%k8vrZQ||KhV_j-puEFOYF_x& z+n(nU-qDURQr1t=Lwa6Ft9q<^Y`C=c*f(vUmtOwI(_E(-U~_&vhKsenUu+w7jqv_C vU}E1syZE><<7C&q-z%4yIXxrr4Hn zAL;LgiP0+qYh6g^$kp1NEt8%>0r8^Z&Zd@OPeUw7bY?5jwlnNgwx>H&V{#BNCL@?- zl-YA-c*+svws)RPHG#W5KNuDh=Ils$0C{7Aoqb9%WGaC<`;wVqx>D5JI1vdZ35ByT z>{%76{mVfqdu9hw{FM}x*{FVu;@dk8Y?zwm9>i9Upb+*pmI$?VBOE(AEQ+0NxnkJe z%OQ&2PXH!eYAz<;gw?4R<#xBl)RDl#j5$Kbtl3DV?14(byeUk=yeX^{p=gkal!y^Ac9%^zUT60Mac@&l*M9!bz&jAsA<002ovPDHLkV1n}Sr=$P? literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/icon_right_arrow_image.png b/app/src/main/res/drawable-xxxhdpi/icon_right_arrow_image.png new file mode 100644 index 0000000000000000000000000000000000000000..7291f1613839317a82fcfc55c71aa517ef96f7d0 GIT binary patch literal 378 zcmV-=0fqjFP)Wp-z-(rFGgiB=qfn=I#&+NCV=>N{)dZwxl#tq*j1;CJakNw<6*CaeOvEt&Q9dUN zL02&h9SlVq!_hKX4)iPLLX$bsH=`F(iJ-3Bm56EtmA@g1R0^R`PdO4V@|@ZrxgTyH zJ}(LkY@b$Vr82)tc)XW5dRl*UV5OxD+S5*;cqc&+^Vha|y33e7vBZccEiXzuc?A)X zkW8CBjikixM%GTnq45I9D_p&r(vz_-6hhjnyp^&xy%~AgEwM5Wtb;ko<8sawSa?Uc Y4_zA`O)^mmyZ`_I07*qoM6N<$f+$&*MgRZ+ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/icon_vertical_dot_line_image.png b/app/src/main/res/drawable-xxxhdpi/icon_vertical_dot_line_image.png new file mode 100644 index 0000000000000000000000000000000000000000..faf6cd5bc5e1784344c4a1ff9cfc4f4b2b16cc3f GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^EI@pNgBeKvzPw2SNbv{wgt)pF_&j^|?D6BrPr+bW z$IB*=+L9o@V21q;^}a!WErF~q_@If0RhjpZN* z3y%v!nu5cnwluD$(=04567D^L%nwX9ye|C3tH{X5tHf}F+hvA(3s7(iV+TWlgMeTH foXPm&feC{X7u&&CY3tVm&1Ud)^>bP0l+XkKMh-t1 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/shape8_gray_bg.xml b/app/src/main/res/drawable/shape8_gray_bg.xml index dfcc015..efdbff5 100644 --- a/app/src/main/res/drawable/shape8_gray_bg.xml +++ b/app/src/main/res/drawable/shape8_gray_bg.xml @@ -3,13 +3,13 @@ - + - + diff --git a/app/src/main/res/drawable/shape_seek_bar_style_v3.xml b/app/src/main/res/drawable/shape_seek_bar_style_v3.xml new file mode 100644 index 0000000..4590be3 --- /dev/null +++ b/app/src/main/res/drawable/shape_seek_bar_style_v3.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_calender_and_time_layout.xml b/app/src/main/res/layout/dialog_calender_and_time_layout.xml index 91a254a..dbcd04c 100644 --- a/app/src/main/res/layout/dialog_calender_and_time_layout.xml +++ b/app/src/main/res/layout/dialog_calender_and_time_layout.xml @@ -28,20 +28,20 @@ @@ -56,7 +56,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_history_fence_layout.xml b/app/src/main/res/layout/item_history_fence_layout.xml new file mode 100644 index 0000000..6ce0a35 --- /dev/null +++ b/app/src/main/res/layout/item_history_fence_layout.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index c9176ae..390a3b3 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -377,4 +377,5 @@ #00C478 #F9FFE8 #B0B0B0 + #758E94 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0c1abf2..7e3fa9f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -262,7 +262,7 @@ Google Map Gaode Map Cancel - The APP is not installed, please download and install the app first + Install the map app to navigate Active Time Goal @@ -1076,4 +1076,7 @@ Fell asleep %s ago Move %s to wake up + Baidu Map + Timeline + \ No newline at end of file diff --git a/baselibrary/src/main/java/com/abbidot/baselibrary/util/AppUtils.kt b/baselibrary/src/main/java/com/abbidot/baselibrary/util/AppUtils.kt index 44c42ff..53c0ba4 100644 --- a/baselibrary/src/main/java/com/abbidot/baselibrary/util/AppUtils.kt +++ b/baselibrary/src/main/java/com/abbidot/baselibrary/util/AppUtils.kt @@ -39,7 +39,7 @@ class AppUtils { /** - * 根据包名判断app是否安装 + * 根据包名判断app是否安装 高版本不兼容 */ fun isAppInstalled(context: Context, packageName: String): Boolean { val pm = context.packageManager diff --git a/baselibrary/src/main/java/com/abbidot/baselibrary/util/Utils.kt b/baselibrary/src/main/java/com/abbidot/baselibrary/util/Utils.kt index 60b0699..1faffe5 100644 --- a/baselibrary/src/main/java/com/abbidot/baselibrary/util/Utils.kt +++ b/baselibrary/src/main/java/com/abbidot/baselibrary/util/Utils.kt @@ -44,6 +44,9 @@ class Utils { const val DATE_FORMAT_PATTERN_EN10 = "dd/MM/yyyy HH:mm:ss" const val DATE_FORMAT_PATTERN_EN11 = "dd/MM HH:mm" const val DATE_FORMAT_PATTERN_EN12 = "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"