1.优化订阅列表显示(Renew at $29.97 per month thereafter)
2.历史轨迹地图增加罗盘和当前手机位置显示 3.历史轨迹点模式增加点击可显示宠物信息 4.修复雷达停止退出还会有声音的bug
This commit is contained in:
@@ -28,9 +28,9 @@ android {
|
||||
applicationId "com.abbidot.tracker"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 35
|
||||
versionCode 2109
|
||||
// versionName "2.1.9"
|
||||
versionName "2.1.9-Beta1"
|
||||
versionCode 2110
|
||||
// versionName "2.1.10"
|
||||
versionName "2.1.10-Beta1"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
||||
@@ -47,19 +47,34 @@ class MySubscriptionAdapter(
|
||||
holder.setText(R.id.tv_my_subscription_plan_name, item.mealName)
|
||||
holder.getTextView(R.id.tv_my_subscription_auto_subscription_tips).apply {
|
||||
visibility = if (item.subscriptionStatus == ConstantInt.Open) {
|
||||
text = if (item.mealUnit == ConstantString.PackageUnitYear) String.format(
|
||||
mContext.getString(R.string.txt_auto_subscription_year),
|
||||
item.autoRenewPrice.toString()
|
||||
)
|
||||
else if (item.mealUnit == ConstantString.PackageUnitDay) String.format(
|
||||
mContext.getString(R.string.txt_auto_subscription_day),
|
||||
text = when (item.mealUnit) {
|
||||
ConstantString.PackageUnitYear -> if (item.mealPeriod > 1) String.format(
|
||||
mContext.getString(R.string.txt_auto_subscription_years),
|
||||
"${item.autoRenewPrice}",
|
||||
"${item.mealPeriod}"
|
||||
) else String.format(
|
||||
mContext.getString(R.string.txt_auto_subscription_year),
|
||||
"${item.autoRenewPrice}"
|
||||
)
|
||||
else String.format(
|
||||
|
||||
ConstantString.PackageUnitDay -> if (item.mealPeriod > 1) String.format(
|
||||
mContext.getString(R.string.txt_auto_subscription_days),
|
||||
"${item.autoRenewPrice}",
|
||||
"${item.mealPeriod}"
|
||||
) else String.format(
|
||||
mContext.getString(R.string.txt_auto_subscription_day),
|
||||
"${item.autoRenewPrice}"
|
||||
)
|
||||
|
||||
else -> if (item.mealPeriod > 1) String.format(
|
||||
mContext.getString(R.string.txt_auto_subscription_months),
|
||||
"${item.autoRenewPrice}",
|
||||
"${item.mealPeriod}"
|
||||
) else String.format(
|
||||
mContext.getString(R.string.txt_auto_subscription_month),
|
||||
item.autoRenewPrice.toString()
|
||||
"${item.autoRenewPrice}"
|
||||
)
|
||||
}
|
||||
View.VISIBLE
|
||||
} else View.GONE
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ class HistoryDataActivity :
|
||||
|
||||
mHistoryDataMapCommon = HistoryDataMapCommon()
|
||||
val fragment = mHistoryDataMapCommon.getMapFragment(
|
||||
this, MapMarkerInfoView(mContext), mGeoCoderViewModel
|
||||
this, MapMarkerInfoView(mContext), mGeoCoderViewModel,VerticalTopToBottomSeekBar(mContext)
|
||||
) {}
|
||||
supportFragmentManager.commit {
|
||||
add(R.id.history_data_map_view, fragment)
|
||||
|
||||
@@ -1088,6 +1088,7 @@ class LiveActivityV3 : BaseActivity<ActivityLiveV3Binding>(ActivityLiveV3Binding
|
||||
mFindBleDeviceViewModel.stopPlay()
|
||||
showAndHideFindLayout()
|
||||
} else {
|
||||
mFindBleDeviceViewModel.stopPlay()
|
||||
mFindBleDeviceViewModel.stopFindDevice()
|
||||
finishActivity()
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ 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.
|
||||
@@ -25,6 +26,7 @@ class HistoryDataMapCommon : BaseMapCommon() {
|
||||
context: Context,
|
||||
markerInfoView: MapMarkerInfoView,
|
||||
geoCoderViewModel: GeoCoderViewModel,
|
||||
verticalTopToBottomSeekBar: VerticalTopToBottomSeekBar,
|
||||
mapLoadOk: () -> Unit
|
||||
): Fragment {
|
||||
return if (AppUtils.isChina(AppUtils.SWITCH_MAP_TYPE)) {
|
||||
@@ -33,7 +35,7 @@ class HistoryDataMapCommon : BaseMapCommon() {
|
||||
mHistoryDataBaiduMapFragment!!
|
||||
} else {
|
||||
mHistoryDataGoogleMapFragment = HistoryDataGoogleMapFragment.newInstance(
|
||||
context, markerInfoView, geoCoderViewModel, mapLoadOk
|
||||
context, markerInfoView, geoCoderViewModel, verticalTopToBottomSeekBar, mapLoadOk
|
||||
)
|
||||
mHistoryDataGoogleMapFragment!!
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ class RouteV2Fragment : BaseFragment<FragmentRouteV2Binding>(FragmentRouteV2Bind
|
||||
root, WindowInsetsCompat.Type.statusBars()
|
||||
)
|
||||
mFragment = mHistoryDataMapCommon.getMapFragment(
|
||||
mContext!!, miHomeRouteAddressView, mGeoCoderViewModel
|
||||
mContext!!, miHomeRouteAddressView, mGeoCoderViewModel, vsbMapRouteLine
|
||||
) {
|
||||
mapLoadOk()
|
||||
}
|
||||
@@ -188,7 +188,7 @@ class RouteV2Fragment : BaseFragment<FragmentRouteV2Binding>(FragmentRouteV2Bind
|
||||
when (checkedId) {
|
||||
mViewBinding.rbHistoryRouteMapLine.id -> {
|
||||
MMKVUtil.putInt(MMKVKey.LineSelectPosition, ConstantInt.Line)
|
||||
mHistoryDataMapCommon.addSetLine(false)
|
||||
mHistoryDataMapCommon.addSetLine()
|
||||
if (mHistoryDataList.size > 0) {
|
||||
// mHistoryDataMapCommon.slideStopChanged(mHistoryDataList.size - 1)
|
||||
} else {
|
||||
@@ -198,7 +198,7 @@ class RouteV2Fragment : BaseFragment<FragmentRouteV2Binding>(FragmentRouteV2Bind
|
||||
|
||||
mViewBinding.rbHistoryRouteMapNumber.id -> {
|
||||
MMKVUtil.putInt(MMKVKey.LineSelectPosition, ConstantInt.Point)
|
||||
mHistoryDataMapCommon.addSetNumber(false)
|
||||
mHistoryDataMapCommon.addSetNumber()
|
||||
if (mHistoryDataList.size > 0) {
|
||||
// mHistoryDataMapCommon.slideStopChanged(mHistoryDataList.size - 1)
|
||||
} else {
|
||||
|
||||
@@ -301,9 +301,11 @@ class HomeTrackFragment :
|
||||
// mTrackerDFUStateDialog?.addData(this)
|
||||
if (progress == 100) {
|
||||
LogUtil.e("固件下载完成")
|
||||
mDeviceDFUViewModel.startDFU(
|
||||
mContext!!, mBleTrackDeviceBean!!.bleDevice!!, filePath
|
||||
)
|
||||
mBleTrackDeviceBean?.let { b ->
|
||||
b.bleDevice?.let { ble ->
|
||||
mDeviceDFUViewModel.startDFU(mContext!!, ble, filePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +212,6 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
*/
|
||||
fun resetFencesViewCentre(centreLatLng: LatLng) {
|
||||
mBaiduMap?.projection?.toScreenLocation(centreLatLng)?.apply {
|
||||
LogUtil.e("ddddssddfsdf$this")
|
||||
if (mFencesCircleView.isVisible) {
|
||||
mFencesCircleView.setCentreXY(this)
|
||||
} else if (mFencesRectView.isVisible) {
|
||||
|
||||
@@ -868,6 +868,7 @@ abstract class BaseGoogleMapFragment :
|
||||
) {
|
||||
//启用“我的位置”图层。
|
||||
isMyLocationEnabled = true
|
||||
}
|
||||
uiSettings.let {
|
||||
//禁止显示“我的位置”按钮。
|
||||
it.isMyLocationButtonEnabled = false
|
||||
@@ -878,7 +879,6 @@ abstract class BaseGoogleMapFragment :
|
||||
it.isTiltGesturesEnabled = false
|
||||
it.isCompassEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
onMapLoadOk(googleMap)
|
||||
}
|
||||
@@ -961,9 +961,9 @@ abstract class BaseGoogleMapFragment :
|
||||
* 由 points 组成的区域 距离手机屏幕距离screenPaddingPx 像素单位
|
||||
*/
|
||||
fun setLatLngZoom(context: Context, screenPaddingPx: Int, vararg points: LatLng) {
|
||||
val width = context.resources.displayMetrics.widthPixels
|
||||
val height = context.resources.displayMetrics.heightPixels
|
||||
val padding = width / 8
|
||||
// val width = context.resources.displayMetrics.widthPixels
|
||||
// val height = context.resources.displayMetrics.heightPixels
|
||||
// val padding = width / 8
|
||||
val builder = LatLngBounds.Builder()
|
||||
for (item in points) {
|
||||
builder.include(item)
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package com.abbidot.tracker.ui.fragment.map.googlemap
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Typeface
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.util.AppUtils
|
||||
@@ -18,6 +15,7 @@ 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
|
||||
@@ -34,6 +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 val mMarkerOptions = MarkerOptions()
|
||||
private lateinit var mPetIconDescriptor: BitmapDescriptor
|
||||
@@ -56,10 +55,12 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
context: Context,
|
||||
markerInfoView: MapMarkerInfoView,
|
||||
geoCoderViewModel: GeoCoderViewModel,
|
||||
verticalTopToBottomSeekBar: VerticalTopToBottomSeekBar,
|
||||
mapLoadOk: () -> Unit
|
||||
) = HistoryDataGoogleMapFragment().apply {
|
||||
mContext = context
|
||||
mGeoCoderViewModel = geoCoderViewModel
|
||||
mVerticalTopToBottomSeekBar = verticalTopToBottomSeekBar
|
||||
mMarkerInfoView = markerInfoView
|
||||
mMapLoadOk = mapLoadOk
|
||||
}
|
||||
@@ -100,17 +101,22 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
if (mMarkerInfoView.isVisible) setMarkerInfoViewOffset(mMarkerInfoView, it)
|
||||
}
|
||||
}
|
||||
|
||||
//检测权限,开启用户的当前位置https://developers.google.cn/maps/documentation/android-sdk/location?hl=zh-cn
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
mContext!!, Manifest.permission.ACCESS_FINE_LOCATION
|
||||
) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
|
||||
mContext!!, Manifest.permission.ACCESS_COARSE_LOCATION
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
//启用“我的位置”图层。
|
||||
isMyLocationEnabled = false
|
||||
setOnMarkerClickListener { m ->
|
||||
//点击数字大头针回到该位置
|
||||
if (m != mMarker) {
|
||||
val index = m.tag
|
||||
if (index is Int) {
|
||||
mVerticalTopToBottomSeekBar.progress = index
|
||||
mMarker?.let {
|
||||
it.position = m.position
|
||||
}
|
||||
slideStopChanged(index)
|
||||
}
|
||||
true
|
||||
} else false
|
||||
}
|
||||
|
||||
uiSettings.isCompassEnabled = true
|
||||
}
|
||||
|
||||
getLastLocation()
|
||||
@@ -267,7 +273,9 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
)
|
||||
)
|
||||
)
|
||||
it.addMarker(numberMarker)
|
||||
it.addMarker(numberMarker)?.apply {
|
||||
tag = i
|
||||
}
|
||||
}
|
||||
|
||||
//设置宠物头像和经纬度
|
||||
|
||||
757
app/src/main/java/com/abbidot/tracker/widget/FencesRectView2.kt
Normal file
757
app/src/main/java/com/abbidot/tracker/widget/FencesRectView2.kt
Normal file
@@ -0,0 +1,757 @@
|
||||
package com.abbidot.tracker.widget
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.DashPathEffect
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Point
|
||||
import android.graphics.RectF
|
||||
import android.text.TextUtils
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.util.ImageUtil
|
||||
import com.abbidot.tracker.util.ViewUtil
|
||||
import com.abbidot.tracker.widget.FencesPolygonView.Companion.POINT_A
|
||||
import com.abbidot.tracker.widget.FencesPolygonView.Companion.POINT_B
|
||||
import com.abbidot.tracker.widget.FencesPolygonView.Companion.POINT_C
|
||||
import com.abbidot.tracker.widget.FencesPolygonView.Companion.POINT_D
|
||||
import com.qmuiteam.qmui.util.QMUIDisplayHelper
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sqrt
|
||||
|
||||
/**
|
||||
*Created by .yzq on 2022/1/22/022.
|
||||
* @link
|
||||
* @description:添加围栏矩形,只针对围栏
|
||||
*
|
||||
* 按以下点组成的矩形
|
||||
* A B
|
||||
* D C
|
||||
*/
|
||||
class FencesRectView2 : View {
|
||||
|
||||
private lateinit var mContext: Context
|
||||
private var mWidth = 0
|
||||
private var mHeight = 0
|
||||
|
||||
private lateinit var mStrokePaint: Paint
|
||||
private lateinit var mFillPaint: Paint
|
||||
|
||||
private lateinit var mRectF: RectF
|
||||
|
||||
//矩形的宽高
|
||||
private var mRectWidth = 0f
|
||||
private var mRectHeight = 0f
|
||||
private var mRectLeft = 0f
|
||||
private var mRectRight = 0f
|
||||
private var mRectTop = 0f
|
||||
private var mRectBottom = 0f
|
||||
|
||||
//中心坐标点
|
||||
private var mCentreX = 0f
|
||||
private var mCentreY = 0f
|
||||
|
||||
//定位图标
|
||||
private var mLocationBitmap: Bitmap? = null
|
||||
private var mDotBitmap: Bitmap? = null
|
||||
private var mZoomBitmap: Bitmap? = null
|
||||
private var mRotateBitmap: Bitmap? = null
|
||||
|
||||
private var mDashedColor = 0
|
||||
private var mFillBgColor = 0
|
||||
|
||||
private var isRotate = false
|
||||
private var isScale = false
|
||||
private var isDrag = false
|
||||
private var mOldX = 0f
|
||||
private var mOldY = 0f
|
||||
|
||||
//是否显示距离
|
||||
private var isShowDistance = true
|
||||
private var mRectWidthDistanceText = ""
|
||||
private var mRectHeightDistanceText = ""
|
||||
private lateinit var mTextPaint: Paint
|
||||
|
||||
//旋转的角度(真实的角度单位)
|
||||
private var mRotateAngle = 0.0
|
||||
|
||||
//计算画布移动后,点击旋转图片按钮一开始的坐标角度,经过平移坐标轴算出
|
||||
private var mStartRotateAngle = 0.0
|
||||
|
||||
//是否需要测量,防止百度地图使用会执行onMeasure/地图页面上下滑动重新布局执行onMeasure
|
||||
private var isNeedMeasure = true
|
||||
|
||||
//限制边长
|
||||
var mLimitSide = 0f
|
||||
|
||||
private var mRotateScaleClickListener: OnRectViewRotateScaleClickListener? = null
|
||||
|
||||
constructor(context: Context) : super(context) {
|
||||
init(context)
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
||||
context, attrs, defStyleAttr
|
||||
) {
|
||||
init(context)
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
|
||||
init(context)
|
||||
}
|
||||
|
||||
private fun init(context: Context) {
|
||||
//禁用硬件加速,防止返回到界面多次执行onDraw
|
||||
setLayerType(LAYER_TYPE_SOFTWARE, null)
|
||||
mContext = context
|
||||
// mRectWidth = QMUIDisplayHelper.dpToPx(100).toFloat()
|
||||
// mRectHeight = QMUIDisplayHelper.dpToPx(100).toFloat()
|
||||
|
||||
mStrokePaint = Paint()
|
||||
LogUtil.e("${javaClass.canonicalName}------------------->>>init")
|
||||
mStrokePaint.style = Paint.Style.STROKE
|
||||
mStrokePaint.strokeWidth = QMUIDisplayHelper.dpToPx(1).toFloat()
|
||||
//虚线长度
|
||||
val dashPathWidth = QMUIDisplayHelper.dpToPx(6).toFloat()
|
||||
mStrokePaint.pathEffect = DashPathEffect(floatArrayOf(dashPathWidth, dashPathWidth), 0f)
|
||||
mStrokePaint.color = ContextCompat.getColor(mContext, R.color.select_color)
|
||||
|
||||
mFillPaint = Paint()
|
||||
mFillPaint.style = Paint.Style.FILL
|
||||
mFillPaint.color = ContextCompat.getColor(mContext, R.color.select_color4)
|
||||
|
||||
mTextPaint = Paint()
|
||||
val tf =
|
||||
ViewUtil.instance.setTypeface(context, context.getString(R.string.number_din_cond_font))
|
||||
mTextPaint.typeface = tf
|
||||
mTextPaint.textSize = QMUIDisplayHelper.sp2px(context, 14).toFloat()
|
||||
mTextPaint.color = ContextCompat.getColor(mContext, R.color.black)
|
||||
|
||||
mDotBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fence_dot_svg)
|
||||
mLocationBitmap =
|
||||
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fences_zone_gps_svg)
|
||||
mZoomBitmap =
|
||||
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fence_rect_zoom_svg)
|
||||
mRotateBitmap =
|
||||
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fence_rect_rotate_svg)
|
||||
|
||||
mRectF = RectF()
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
mWidth = measuredWidth
|
||||
mHeight = measuredHeight
|
||||
LogUtil.e("${javaClass.canonicalName}:onMeasure---mWidth=$mWidth,mHeight=$mHeight")
|
||||
if (isNeedMeasure) {
|
||||
mCentreX = mWidth / 2f
|
||||
mCentreY = mHeight / 2f
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
LogUtil.e("onAttachedToWindow,${javaClass.canonicalName}视图显示")
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
LogUtil.e("${javaClass.canonicalName}------>onDraw")
|
||||
super.onDraw(canvas)
|
||||
|
||||
canvas.apply {
|
||||
save()
|
||||
//只为旋转才移动坐标轴
|
||||
translate(mCentreX, mCentreY)
|
||||
rotate(mRotateAngle.toFloat())
|
||||
startDraw(this)
|
||||
restore()
|
||||
// val a = getRectABCDXYPoint(FencesRectView.POINT_A)
|
||||
// drawCircle(a[0], a[1], 50f, mTextPaint)
|
||||
// val b = getRectABCDXYPoint(FencesRectView.POINT_B)
|
||||
// drawCircle(b[0], b[1], 50f, mTextPaint)
|
||||
// val c = getRectABCDXYPoint(FencesRectView.POINT_C)
|
||||
// drawCircle(c[0], c[1], 50f, mTextPaint)
|
||||
// val d = getRectABCDXYPoint(FencesRectView.POINT_D)
|
||||
// drawCircle(d[0], d[1], 50f, mTextPaint)
|
||||
}
|
||||
}
|
||||
|
||||
private fun startDraw(canvas: Canvas) {
|
||||
LogUtil.e("startDraw:mRotateAngle=$mRotateAngle")
|
||||
|
||||
if (mRectWidth == 0f && mRectHeight == 0f) return
|
||||
|
||||
mRectLeft = -mRectWidth / 2
|
||||
mRectTop = -mRectHeight / 2
|
||||
mRectRight = mRectLeft + mRectWidth
|
||||
mRectBottom = mRectTop + mRectHeight
|
||||
|
||||
mLocationBitmap?.apply {
|
||||
val locationImageHalfWidth = width / 2f
|
||||
val locationImageHalfHeight = height / 2f
|
||||
val left = -locationImageHalfWidth
|
||||
val top = -locationImageHalfHeight
|
||||
canvas.drawBitmap(this, left, top, null)
|
||||
}
|
||||
|
||||
mRectF.apply {
|
||||
left = mRectLeft
|
||||
top = mRectTop
|
||||
right = mRectRight
|
||||
bottom = mRectBottom
|
||||
}
|
||||
canvas.drawRect(mRectF, mFillPaint)
|
||||
canvas.drawRect(mRectF, mStrokePaint)
|
||||
|
||||
mDotBitmap?.apply {
|
||||
val dotImageHalfWidth = width / 2f
|
||||
val dotImageHalfHeight = height / 2f
|
||||
canvas.drawBitmap(
|
||||
this, mRectLeft - dotImageHalfWidth, mRectTop - dotImageHalfHeight, null
|
||||
)
|
||||
canvas.drawBitmap(
|
||||
this, mRectRight - dotImageHalfWidth, mRectTop - dotImageHalfHeight, null
|
||||
)
|
||||
canvas.drawBitmap(
|
||||
this, mRectLeft - dotImageHalfWidth, mRectBottom - dotImageHalfHeight, null
|
||||
)
|
||||
if (!isShowDistance) {
|
||||
canvas.drawBitmap(
|
||||
this, mRectRight - dotImageHalfWidth, mRectBottom - dotImageHalfHeight, null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isShowDistance) {
|
||||
|
||||
mRotateBitmap?.apply {
|
||||
val startX = mRectLeft + mRectWidth / 2
|
||||
canvas.drawLine(
|
||||
startX,
|
||||
mRectTop,
|
||||
startX,
|
||||
mRectTop - QMUIDisplayHelper.dpToPx(3).toFloat(),
|
||||
mStrokePaint
|
||||
)
|
||||
canvas.drawBitmap(
|
||||
this,
|
||||
startX - width / 2,
|
||||
mRectTop - height - QMUIDisplayHelper.dpToPx(2).toFloat(),
|
||||
null
|
||||
)
|
||||
mStartRotateAngle = atan2(mRectTop - height, startX - width / 2) / Math.PI * 180
|
||||
}
|
||||
mZoomBitmap?.apply {
|
||||
canvas.drawBitmap(
|
||||
this, mRectRight - width / 2, mRectBottom - height / 2, null
|
||||
)
|
||||
}
|
||||
|
||||
canvasDistanceText(canvas)
|
||||
}
|
||||
}
|
||||
|
||||
private fun canvasDistanceText(canvas: Canvas) {
|
||||
val fontMetrics = mTextPaint.fontMetrics
|
||||
if (!TextUtils.isEmpty(mRectWidthDistanceText)) {
|
||||
//文字宽度
|
||||
val textWidth = mTextPaint.measureText(mRectWidthDistanceText)
|
||||
//文字高度
|
||||
val textHeight = fontMetrics.bottom - fontMetrics.top
|
||||
|
||||
val y = if (mHeight / 2 - mRectHeight / 2 > textHeight) {
|
||||
mRectHeight / 2 + textHeight
|
||||
} else {
|
||||
mHeight / 2 - textHeight / 6
|
||||
}
|
||||
canvas.drawText(
|
||||
mRectWidthDistanceText, -(textWidth / 2), y, mTextPaint
|
||||
)
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(mRectHeightDistanceText)) {
|
||||
//文字宽度
|
||||
val textWidth = mTextPaint.measureText(mRectHeightDistanceText)
|
||||
//文字高度
|
||||
val textHeight = fontMetrics.bottom - fontMetrics.top
|
||||
|
||||
val x = if (mWidth / 2 - mRectWidth / 2 > textWidth) {
|
||||
mRectWidth / 2 + (textHeight / 6)
|
||||
} else {
|
||||
mWidth / 2 - textWidth - textHeight / 6
|
||||
}
|
||||
canvas.drawText(
|
||||
mRectHeightDistanceText, x, (textHeight / 2), mTextPaint
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun setOnRectViewRotateScaleClickListener(onRectViewRotateScaleClickListener: OnRectViewRotateScaleClickListener) {
|
||||
mRotateScaleClickListener = onRectViewRotateScaleClickListener
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认长宽大小,初始化使用
|
||||
*/
|
||||
fun initDefaultWidthHeight(width: Int = 150, height: Int = 150) {
|
||||
if (width <= 0 && height <= 0) return
|
||||
mRectWidth = QMUIDisplayHelper.dpToPx(width).toFloat()
|
||||
mRectHeight = QMUIDisplayHelper.dpToPx(height).toFloat()
|
||||
mRotateAngle = 0.0
|
||||
postInvalidate()
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置显示的距离
|
||||
*/
|
||||
fun setShowDisDistance(widthDistance: String, heightDistance: String) {
|
||||
mRectWidthDistanceText = widthDistance
|
||||
mRectHeightDistanceText = heightDistance
|
||||
postInvalidate()
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置隐藏显示距离文字
|
||||
*/
|
||||
fun setShowHideDisDistance(show: Boolean) {
|
||||
if (isShowDistance != show) {
|
||||
isShowDistance = show
|
||||
postInvalidate()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置边框颜色和图片
|
||||
*/
|
||||
fun setColorAndImage(
|
||||
context: Context,
|
||||
dashedColorRes: Int = 0,
|
||||
fillBgColorRes: Int = 0,
|
||||
locationDrawableRes: Int = 0,
|
||||
zoomDrawableRes: Int = 0,
|
||||
dotDrawableRes: Int = 0,
|
||||
rotateDrawableRes: Int = 0,disTextColorRes: Int = 0
|
||||
) {
|
||||
var isRefresh = false
|
||||
if (dashedColorRes > 0) {
|
||||
mDashedColor = ContextCompat.getColor(context, dashedColorRes)
|
||||
mStrokePaint.color = mDashedColor
|
||||
isRefresh = true
|
||||
}
|
||||
if (fillBgColorRes > 0) {
|
||||
mFillBgColor = ContextCompat.getColor(context, fillBgColorRes)
|
||||
mFillPaint.color = mFillBgColor
|
||||
isRefresh = true
|
||||
}
|
||||
|
||||
if (locationDrawableRes > 0) {
|
||||
mLocationBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, locationDrawableRes)
|
||||
isRefresh = true
|
||||
}
|
||||
if (zoomDrawableRes > 0) {
|
||||
mZoomBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, zoomDrawableRes)
|
||||
isRefresh = true
|
||||
}
|
||||
if (rotateDrawableRes > 0) {
|
||||
mRotateBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, rotateDrawableRes)
|
||||
isRefresh = true
|
||||
}
|
||||
if (dotDrawableRes > 0) {
|
||||
mDotBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, dotDrawableRes)
|
||||
isRefresh = true
|
||||
}
|
||||
if (disTextColorRes > 0) {
|
||||
mTextPaint.color = ContextCompat.getColor(context, disTextColorRes)
|
||||
isRefresh = true
|
||||
}
|
||||
if (isRefresh) invalidate()
|
||||
}
|
||||
|
||||
private fun getCentreX() = mCentreX
|
||||
private fun getCentreY() = mCentreY
|
||||
|
||||
/**
|
||||
* 获取中心点
|
||||
*/
|
||||
fun getRectCentrePoint() = Point(mCentreX.toInt(), mCentreY.toInt())
|
||||
|
||||
/**
|
||||
* 获取矩形4个点的某一个点
|
||||
*/
|
||||
fun getRectABCDPoint(wherePoint: Int): Point {
|
||||
val points = getRectABCDXYPoint(wherePoint)
|
||||
return Point(points[0].toInt(), points[1].toInt())
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回矩形第哪个点(A,B,C,D)的坐标
|
||||
* A **** B
|
||||
* D **** C
|
||||
*/
|
||||
private fun getRectABCDXYPoint(wherePoint: Int): FloatArray {
|
||||
when (wherePoint) {
|
||||
POINT_A -> {
|
||||
val leftTop = getRotateXY(mRectLeft, mRectTop, mRotateAngle)
|
||||
return floatArrayOf(
|
||||
leftTop[0] + mCentreX, leftTop[1] + mCentreY
|
||||
)
|
||||
}
|
||||
|
||||
POINT_B -> {
|
||||
val rightTop = getRotateXY(mRectRight, mRectTop, mRotateAngle)
|
||||
return floatArrayOf(
|
||||
rightTop[0] + mCentreX, rightTop[1] + mCentreY
|
||||
)
|
||||
}
|
||||
|
||||
POINT_D -> {
|
||||
val leftBottom = getRotateXY(mRectLeft, mRectBottom, mRotateAngle)
|
||||
return floatArrayOf(
|
||||
leftBottom[0] + mCentreX, leftBottom[1] + mCentreY
|
||||
)
|
||||
}
|
||||
|
||||
POINT_C -> {
|
||||
val rightBottom = getRotateXY(mRectRight, mRectBottom, mRotateAngle)
|
||||
return floatArrayOf(
|
||||
rightBottom[0] + mCentreX, rightBottom[1] + mCentreY
|
||||
)
|
||||
}
|
||||
}
|
||||
return floatArrayOf(
|
||||
0f, 0f
|
||||
)
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onTouchEvent(event: MotionEvent?): Boolean {
|
||||
|
||||
when (event?.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
val x = event.x
|
||||
val y = event.y
|
||||
LogUtil.e("action_down,x=$x,y=$y")
|
||||
mRotateBitmap?.apply {
|
||||
LogUtil.e("x2=${width / 2f + mCentreX},x1=${-width / 2f + mCentreX}")
|
||||
LogUtil.e("y2=${-(mRectHeight / 2 + height) + mCentreY},aaa=${-mRectHeight / 2 + mCentreY}")
|
||||
|
||||
if (isClickRotate(x, y, mRotateAngle)) {
|
||||
LogUtil.e("点击了旋转")
|
||||
isRotate = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
//是否按下了放大缩小按钮
|
||||
mZoomBitmap?.apply {
|
||||
if (!isRotate && isClickScale(x, y, mRotateAngle)) {
|
||||
isScale = true
|
||||
LogUtil.e("点击了放大缩小")
|
||||
mOldX = x
|
||||
mOldY = y
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
//因为有旋转角度,需要减去中心
|
||||
if (mRectF.contains(x - mCentreX, y - mCentreY)) {
|
||||
isDrag = true
|
||||
mOldX = x
|
||||
mOldY = y
|
||||
mStrokePaint.strokeWidth = QMUIDisplayHelper.dpToPx(3).toFloat()
|
||||
mRotateScaleClickListener?.rectStartDragClick()
|
||||
invalidate()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
val x = event.x
|
||||
val y = event.y
|
||||
LogUtil.e("action_move,x=$x,y=$y,oldX=$mOldX,oldY=$mOldY")
|
||||
if (isRotate) {
|
||||
//计算手指按下画布移动后的x,y角度
|
||||
val transformAngle = atan2(y - mCentreY, x - mCentreX) / Math.PI * 180
|
||||
//计算需要旋转的角度
|
||||
mRotateAngle = transformAngle - mStartRotateAngle
|
||||
LogUtil.e("mRotateAngle=$mRotateAngle")
|
||||
invalidate()
|
||||
return true
|
||||
} else if (isScale) {
|
||||
LogUtil.e("mRectWidth=$mRectWidth,mRectHeight=$mRectHeight,x - oldX=${x - mOldX},y - oldY=${y - mOldY}")
|
||||
val transformX = x - mOldX
|
||||
val transformY = y - mOldY
|
||||
val newRectWidth = mRectWidth + transformX
|
||||
val newRectHeight = mRectHeight + transformY
|
||||
//限制缩放不能太小
|
||||
if (mLimitSide == 0f) {
|
||||
if (newRectWidth < mLocationBitmap!!.height || newRectHeight < mLocationBitmap!!.height) {
|
||||
return true
|
||||
}
|
||||
} else if (newRectWidth < mLimitSide || newRectHeight < mLimitSide) {
|
||||
return true
|
||||
}
|
||||
mRotateScaleClickListener?.rectScalingClick()
|
||||
mRectWidth = newRectWidth
|
||||
mRectHeight = newRectHeight
|
||||
mOldX = x
|
||||
mOldY = y
|
||||
invalidate()
|
||||
return true
|
||||
} else if (isDrag) {
|
||||
val transformX = x - mOldX
|
||||
val transformY = y - mOldY
|
||||
mCentreX += transformX
|
||||
mCentreY += transformY
|
||||
mOldX = x
|
||||
mOldY = y
|
||||
invalidate()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP -> {
|
||||
if (isRotate) {
|
||||
mRotateScaleClickListener?.rectRotateClick()
|
||||
isRotate = false
|
||||
}
|
||||
if (isScale) {
|
||||
mRotateScaleClickListener?.rectScaleEndClick()
|
||||
isScale = false
|
||||
}
|
||||
if (isDrag) {
|
||||
mRotateScaleClickListener?.rectEndDragClick()
|
||||
isDrag = false
|
||||
mStrokePaint.strokeWidth = QMUIDisplayHelper.dpToPx(1).toFloat()
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onTouchEvent(event)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x 是坐标轴移动以(mCentreX,mCentreY)原点的坐标
|
||||
* @param y
|
||||
* 获取以mCentreX、mCentreY为原点的坐标轴进行旋转后的XY坐标
|
||||
*/
|
||||
private fun getRotateXY(x: Float, y: Float, rotate: Double): FloatArray {
|
||||
//Math.toRadians(double angdeg) 角度转化为弧度
|
||||
//Math.toDegrees(Math.PI/2);弧度转化为角度 (π/2的角度值)
|
||||
val curAngle = atan2(y, x) / Math.PI * 180
|
||||
val sumAngle = curAngle + rotate
|
||||
//将角度化为弧度
|
||||
// val angle = Math.PI / 180 * sumAngle
|
||||
val angle = Math.toRadians(sumAngle)
|
||||
//初始坐标与中点形成的直线长度不管怎么旋转都是不会变的,用勾股定理求出然后将其作为斜边
|
||||
val c = sqrt(x.pow(2) + y.pow(2))
|
||||
//斜边乘sin值等于即可求出y坐标
|
||||
val a = sin(angle) * c
|
||||
//斜边乘cos值等于即可求出x坐标
|
||||
val b = cos(angle) * c
|
||||
//目前的xy坐标是相对于图片中点为原点的坐标轴
|
||||
return floatArrayOf((b).toFloat(), (a).toFloat())
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否点击按下了旋转,按照移动了坐标轴原点(mCentreX,mCentreY)计算初始坐标
|
||||
*/
|
||||
private fun isClickRotate(clickX: Float, clickY: Float, rotate: Double): Boolean {
|
||||
var x1 = -(mRectWidth / 2 - mRotateBitmap!!.width / 2)
|
||||
var x2 = (mRectWidth / 2 - mRotateBitmap!!.width / 2)
|
||||
var y1 = -(mRectHeight / 2 + mRotateBitmap!!.height + mRotateBitmap!!.width)
|
||||
var y2 = -(mRectHeight / 2 - mRotateBitmap!!.height)
|
||||
val minX = getRotateXY(x1, y1, rotate)
|
||||
val maxX = getRotateXY(x2, y2, rotate)
|
||||
x1 = minX[0]
|
||||
x2 = maxX[0]
|
||||
if (minX[0] > maxX[0]) {
|
||||
x1 = maxX[0]
|
||||
x2 = minX[0]
|
||||
}
|
||||
y1 = minX[1]
|
||||
y2 = maxX[1]
|
||||
if (minX[1] > maxX[1]) {
|
||||
y1 = maxX[1]
|
||||
y2 = minX[1]
|
||||
}
|
||||
|
||||
//处理旋转到某个角度时,旋转图片按钮会超出坐标范围内,不在可点击坐标范围内,把可点击的坐标范围扩大
|
||||
if (abs(x2 - x1) < mRotateBitmap!!.height) {
|
||||
if (x2 > 0) {
|
||||
x2 += mRotateBitmap!!.height
|
||||
} else {
|
||||
x1 -= mRotateBitmap!!.height
|
||||
}
|
||||
}
|
||||
if (abs(y2 - y1) < mRotateBitmap!!.height) {
|
||||
if (y2 > 0) {
|
||||
y2 += mRotateBitmap!!.height
|
||||
} else {
|
||||
y1 -= mRotateBitmap!!.height
|
||||
}
|
||||
}
|
||||
|
||||
val transformX = clickX - mCentreX
|
||||
val transformY = clickY - mCentreY
|
||||
|
||||
if (transformX in x1..x2 && transformY in y1..y2) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否点击按下了放大缩小,按照移动了坐标轴原点(mCentreX,mCentreY)计算初始坐标
|
||||
*/
|
||||
private fun isClickScale(clickX: Float, clickY: Float, rotate: Double): Boolean {
|
||||
var x1 = (mRectWidth / 2 - mZoomBitmap!!.width)
|
||||
var x2 = (mRectWidth / 2 + mZoomBitmap!!.width)
|
||||
var y1 = (mRectHeight / 2 - mRotateBitmap!!.height)
|
||||
var y2 = (mRectHeight / 2 + mRotateBitmap!!.height)
|
||||
val minX = getRotateXY(x1, y1, rotate)
|
||||
val maxX = getRotateXY(x2, y2, rotate)
|
||||
x1 = minX[0]
|
||||
x2 = maxX[0]
|
||||
if (minX[0] > maxX[0]) {
|
||||
x1 = maxX[0]
|
||||
x2 = minX[0]
|
||||
}
|
||||
y1 = minX[1]
|
||||
y2 = maxX[1]
|
||||
if (minX[1] > maxX[1]) {
|
||||
y1 = maxX[1]
|
||||
y2 = minX[1]
|
||||
}
|
||||
|
||||
val transformX = clickX - mCentreX
|
||||
val transformY = clickY - mCentreY
|
||||
|
||||
if (transformX in x1..x2 && transformY in y1..y2) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置显示编辑的矩形(利用假设方式)
|
||||
* 错误方式
|
||||
fun setRectABCDXYPoint(left: Float, top: Float, right: Float, bottom: Float) {
|
||||
//假设A没有旋转的,原点在矩形中心,正常与x轴的角度135℃
|
||||
val noRotateAngle = 135.0
|
||||
val rotateAX = left - mCentreX
|
||||
val rotateAY = top - mCentreY
|
||||
//计算现在编辑后的矩形A点的角度
|
||||
val curAngle = atan2(rotateAY, rotateAX) / Math.PI * 180
|
||||
//计算旋转了多少度
|
||||
mRotateAngle = noRotateAngle - curAngle
|
||||
//初始坐标与矩形中点形成的直线长度不管怎么旋转都是不会变的,用勾股定理求出然后将其作为斜边
|
||||
val c = sqrt(rotateAX.pow(2) + rotateAY.pow(2))
|
||||
//将角度化为弧度,计算旋转后的与x轴的角度,然后算出长和宽
|
||||
val angle = Math.toRadians(curAngle)
|
||||
//斜边乘sin值等于即可求出y坐标
|
||||
val a = sin(angle) * c
|
||||
//斜边乘cos值等于即可求出x坐标
|
||||
val b = cos(angle) * c
|
||||
mRectLeft = (-abs(b)).toFloat()
|
||||
mRectTop = (-abs(a)).toFloat()
|
||||
|
||||
// mRectWidth = abs(b * 2).toFloat()
|
||||
mRectWidth = abs(right) - abs(left)
|
||||
// mRectHeight = abs(a * 2).toFloat()
|
||||
mRectHeight = abs(bottom) - abs(top)
|
||||
|
||||
mRectRight = mRectWidth / 2
|
||||
mRectBottom = mRectHeight / 2
|
||||
|
||||
isEdit = true
|
||||
|
||||
LogUtil.e("编辑的坐标($mRectLeft,$mRectTop),($mRectRight,$mRectBottom),($mCentreX,$mCentreY)")
|
||||
postInvalidate()
|
||||
} */
|
||||
|
||||
fun setRectABCDXYPoint(
|
||||
pointCentre: Point, pointA: Point, pointB: Point, pointC: Point, pointD: Point
|
||||
) {
|
||||
mCentreX = pointCentre.x.toFloat()
|
||||
mCentreY = pointCentre.y.toFloat()
|
||||
//利用屏幕的坐标系根据勾股定理算出矩形的边长,A点和D点与坐标轴组成一个三角形
|
||||
mRectHeight = sqrt(
|
||||
(abs(pointA.x - pointD.x).toFloat()).pow(2) + (abs(pointD.y - pointA.y).toFloat()).pow(2)
|
||||
)
|
||||
//A点和B点与坐标轴组成一个三角形
|
||||
mRectWidth = sqrt(
|
||||
(abs(pointB.x - pointA.x).toFloat()).pow(2) + (abs(pointB.y - pointA.y).toFloat()).pow(2)
|
||||
)
|
||||
|
||||
val rotateAX = pointA.x - mCentreX
|
||||
val rotateAY = pointA.y - mCentreY
|
||||
//计算现在编辑后的矩形A点与x轴形成的角度
|
||||
val curAngle = atan2(rotateAY, rotateAX) / Math.PI * 180
|
||||
|
||||
//初始坐标与矩形中点形成的直线长度不管怎么旋转都是不会变的,用勾股定理求出然后将其作为斜边
|
||||
// val c = sqrt(rotateAX.pow(2) + rotateAY.pow(2))
|
||||
//将角度化为弧度,计算旋转后的与x轴的角度,然后算出长和宽
|
||||
// val angle = Math.toRadians(curAngle)
|
||||
//斜边乘sin值等于即可求出y坐标
|
||||
// val a = sin(angle) * c
|
||||
//斜边乘cos值等于即可求出x坐标
|
||||
// val b = cos(angle) * c
|
||||
|
||||
//根据矩形长宽算出没有旋转的矩形坐标
|
||||
val rectLeft = -mRectWidth / 2
|
||||
val rectTop = -mRectHeight / 2
|
||||
val rectRight = rectLeft + mRectWidth
|
||||
val rectBottom = rectTop + mRectHeight
|
||||
//计算A没有旋转的,原点在矩形中心,正常与x轴的角度
|
||||
val noRotateAngle = atan2(rectTop, rectLeft) / Math.PI * 180
|
||||
//计算旋转了多少度
|
||||
mRotateAngle = curAngle - noRotateAngle
|
||||
LogUtil.e("没有旋转时初始角度=$noRotateAngle,当前旋转后的角度curAngle=$curAngle,旋转了多少度mRotateAngle=$mRotateAngle")
|
||||
LogUtil.e("编辑的坐标($rectLeft,$rectTop),($rectRight,$rectBottom),($mCentreX,$mCentreY)")
|
||||
postInvalidate()
|
||||
}
|
||||
|
||||
fun setCentreXY(point: Point) {
|
||||
point.apply {
|
||||
if (mCentreX != x.toFloat() || mCentreY != y.toFloat()) {
|
||||
mCentreX = x.toFloat()
|
||||
mCentreY = y.toFloat()
|
||||
isNeedMeasure = false
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
LogUtil.e("onDetachedFromWindow,${javaClass.canonicalName}视图销毁")
|
||||
if (null != mDotBitmap) {
|
||||
mDotBitmap?.recycle()
|
||||
mDotBitmap = null
|
||||
}
|
||||
if (null != mLocationBitmap) {
|
||||
mLocationBitmap?.recycle()
|
||||
mLocationBitmap = null
|
||||
}
|
||||
if (null != mRotateBitmap) {
|
||||
mRotateBitmap?.recycle()
|
||||
mRotateBitmap = null
|
||||
}
|
||||
if (null != mZoomBitmap) {
|
||||
mZoomBitmap?.recycle()
|
||||
mZoomBitmap = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,12 +172,12 @@ class FencesRectView3 : View {
|
||||
super.onDraw(canvas)
|
||||
|
||||
canvas.apply {
|
||||
save()
|
||||
//只为旋转才移动坐标轴
|
||||
translate(mCentreX, mCentreY)
|
||||
rotate(mRotateAngle.toFloat())
|
||||
// save()
|
||||
// //只为旋转才移动坐标轴
|
||||
// translate(mCentreX, mCentreY)
|
||||
// rotate(mRotateAngle.toFloat())
|
||||
startDraw(this)
|
||||
restore()
|
||||
// restore()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -867,11 +867,7 @@
|
||||
<string name="txt_residual_value">Restwert</string>
|
||||
<string name="txt_month_unit">/Monat x%s</string>
|
||||
<string name="txt_auto_subscription_year">(Verlängerung zu $%s jährlich danach)</string>
|
||||
<string name="txt_auto_subscription_year1">(Verlängerung zu</string>
|
||||
<string name="txt_auto_subscription_year2">jährlich danach)</string>
|
||||
<string name="txt_auto_subscription_month">(Verlängerung zu $%s monatlich danach)</string>
|
||||
<string name="txt_auto_subscription_month1">(Verlängerung zu</string>
|
||||
<string name="txt_auto_subscription_month2">monatlich danach)</string>
|
||||
<string name="txt_about_dec">Haustiere orten und trainieren, um Verlust/Gefahren vorzubeugen.</string>
|
||||
<string name="txt_year_unit">/%s Jahr</string>
|
||||
<string name="txt_advanced_set">Erweiterte Einstellungen</string>
|
||||
|
||||
@@ -910,11 +910,7 @@
|
||||
<string name="txt_residual_value">剩余价值</string>
|
||||
<string name="txt_month_unit">/月 x%s</string>
|
||||
<string name="txt_auto_subscription_year">(此后按每年 $%s 续订)</string>
|
||||
<string name="txt_auto_subscription_year1">(此后按</string>
|
||||
<string name="txt_auto_subscription_year2">/年续费)</string>
|
||||
<string name="txt_auto_subscription_month">(此后按每月 $%s 续订)</string>
|
||||
<string name="txt_auto_subscription_month1">(此后按</string>
|
||||
<string name="txt_auto_subscription_month2">/月续费)</string>
|
||||
<string name="txt_about_dec">追踪并训练宠物,以防丢失或危险。</string>
|
||||
<string name="txt_year_unit">/%s 年</string>
|
||||
<string name="txt_advanced_set">高级设置</string>
|
||||
|
||||
@@ -968,11 +968,7 @@
|
||||
<string name="txt_residual_value">Residual Value</string>
|
||||
<string name="txt_month_unit">/month x%s</string>
|
||||
<string name="txt_auto_subscription_year">(Renew at $%s per year thereafter)</string>
|
||||
<string name="txt_auto_subscription_year1">(Renew at </string>
|
||||
<string name="txt_auto_subscription_year2">per year thereafter)</string>
|
||||
<string name="txt_auto_subscription_month">(Renew at $%s per month thereafter)</string>
|
||||
<string name="txt_auto_subscription_month1">(Renew at </string>
|
||||
<string name="txt_auto_subscription_month2">per month thereafter)</string>
|
||||
<string name="txt_about_dec">Track and train pets to prevent loss or danger.</string>
|
||||
<string name="txt_year_unit">/%s year</string>
|
||||
<string name="txt_advanced_set">Advanced Setting</string>
|
||||
@@ -1067,7 +1063,10 @@
|
||||
<string name="txt_renewal_day">Renewal: $%s/%s day on %s</string>
|
||||
<string name="txt_day_unit">/day x%s</string>
|
||||
<string name="txt_location_tip">"ABBIDOT APP collects location data,The route and distance between the current location and the device can be calculated."</string>
|
||||
<string name="txt_auto_subscription_day">(Renew at $%s per %s day thereafter)</string>
|
||||
<string name="txt_auto_subscription_day">(Renew at $%s per day thereafter)</string>
|
||||
<string name="txt_auto_subscription_days">(Renew at $%s/%s days thereafter)</string>
|
||||
<string name="txt_locating">Locating…</string>
|
||||
<string name="txt_auto_subscription_years">(Renew at $%s/%s years thereafter)</string>
|
||||
<string name="txt_auto_subscription_months">(Renew at $%s/%s months thereafter)</string>
|
||||
|
||||
</resources>
|
||||
Reference in New Issue
Block a user