1.完成Nearby 显示定位策略
2.多边形围栏距离限制
This commit is contained in:
@@ -28,9 +28,9 @@ android {
|
|||||||
applicationId "com.abbidot.tracker"
|
applicationId "com.abbidot.tracker"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 35
|
targetSdkVersion 35
|
||||||
versionCode 2108
|
versionCode 2109
|
||||||
// versionName "2.1.8"
|
// versionName "2.1.9"
|
||||||
versionName "2.1.8-Beta1"
|
versionName "2.1.9-Beta1"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
|||||||
@@ -43,11 +43,13 @@ import com.abbidot.tracker.ui.activity.map.LiveActivityV3
|
|||||||
import com.abbidot.tracker.ui.common.map.HomeMapCommonV3
|
import com.abbidot.tracker.ui.common.map.HomeMapCommonV3
|
||||||
import com.abbidot.tracker.util.Util
|
import com.abbidot.tracker.util.Util
|
||||||
import com.abbidot.tracker.util.ViewUtil
|
import com.abbidot.tracker.util.ViewUtil
|
||||||
|
import com.abbidot.tracker.util.bluetooth.SRBleCmdUtil
|
||||||
import com.abbidot.tracker.util.bluetooth.SRBleUtil
|
import com.abbidot.tracker.util.bluetooth.SRBleUtil
|
||||||
import com.abbidot.tracker.vm.CountDownTimerViewModel
|
import com.abbidot.tracker.vm.CountDownTimerViewModel
|
||||||
import com.abbidot.tracker.vm.FencesMapViewModel
|
import com.abbidot.tracker.vm.FencesMapViewModel
|
||||||
import com.abbidot.tracker.vm.MapViewModel
|
import com.abbidot.tracker.vm.MapViewModel
|
||||||
import com.clj.fastble.BleManager
|
import com.clj.fastble.BleManager
|
||||||
|
import com.google.android.gms.maps.model.LatLng
|
||||||
import com.hjq.permissions.XXPermissions
|
import com.hjq.permissions.XXPermissions
|
||||||
import com.hjq.permissions.permission.PermissionLists
|
import com.hjq.permissions.permission.PermissionLists
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@@ -243,7 +245,6 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
|||||||
|
|
||||||
mCountDownTimerViewModel.mCountDownEndLiveData.observe(this) {
|
mCountDownTimerViewModel.mCountDownEndLiveData.observe(this) {
|
||||||
mCountDownTimerViewModel.isStartCountDown = true
|
mCountDownTimerViewModel.isStartCountDown = true
|
||||||
LogUtil.e("22222222222")
|
|
||||||
mViewBinding.llHomeMapTopPet.homeDataPetNameSmall.text =
|
mViewBinding.llHomeMapTopPet.homeDataPetNameSmall.text =
|
||||||
getHomeV2Activity()?.getPet()?.petName
|
getHomeV2Activity()?.getPet()?.petName
|
||||||
}
|
}
|
||||||
@@ -291,6 +292,22 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
|||||||
if (macID == reportData.mac) updateBleReportData(reportData)
|
if (macID == reportData.mac) updateBleReportData(reportData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//设备获取手机位置
|
||||||
|
XEventBus.observe(this, EventName.BleGetLocation) { mac: String ->
|
||||||
|
getHomeV2Activity()?.getPet(false)?.apply {
|
||||||
|
if (macID == mac) {
|
||||||
|
mHomeMapCommon.getUserGoogleLatLng()?.let { latLng: LatLng ->
|
||||||
|
SRBleUtil.instance.getConnectMacDevice(mac)?.let { ble ->
|
||||||
|
SRBleUtil.instance.writeData(
|
||||||
|
ble.bleDevice, SRBleCmdUtil.instance.getPhoneLocation(
|
||||||
|
latLng.latitude, latLng.longitude
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
//接收蓝牙连接状态
|
//接收蓝牙连接状态
|
||||||
XEventBus.observe(this, EventName.ConnectDeviceState) { trackBle: BleTrackDeviceBean ->
|
XEventBus.observe(this, EventName.ConnectDeviceState) { trackBle: BleTrackDeviceBean ->
|
||||||
getHomeV2Activity()?.getPet(false)?.apply {
|
getHomeV2Activity()?.getPet(false)?.apply {
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {
|
|||||||
LogUtil.e("setScaleLimitDistance,$stepDistance,$limitRadius,$limitSide,${cameraPosition.zoom}")
|
LogUtil.e("setScaleLimitDistance,$stepDistance,$limitRadius,$limitSide,${cameraPosition.zoom}")
|
||||||
mFencesCircleView.mLimitRadius = limitRadius.toFloat()
|
mFencesCircleView.mLimitRadius = limitRadius.toFloat()
|
||||||
mFencesRectView.mLimitSide = limitSide.toFloat()
|
mFencesRectView.mLimitSide = limitSide.toFloat()
|
||||||
|
mFencesPolygonView.mLimitSide = limitSide.toFloat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -367,5 +367,12 @@ class SRBleCmdUtil private constructor() {
|
|||||||
byteArray = byteArray.plus(longTo2ByteArray(duration))
|
byteArray = byteArray.plus(longTo2ByteArray(duration))
|
||||||
return getCrc8Cmd(byteArray)
|
return getCrc8Cmd(byteArray)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPhoneLocation(lat: Double, lon: Double): ByteArray {
|
||||||
|
var byteArray = byteArrayOf(0x23, CMD_READ.toByte(), 0)
|
||||||
|
byteArray = byteArray.plus(longTo4ByteArray((lon * 1000000).toLong()))
|
||||||
|
byteArray = byteArray.plus(longTo4ByteArray((lat * 1000000).toLong()))
|
||||||
|
return getCrc8Cmd(byteArray)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -226,6 +226,9 @@ class SRBleUtil private constructor() {
|
|||||||
openBleReportNotify(
|
openBleReportNotify(
|
||||||
bleDevice, notifyServiceUUID, bleNotifyCharacteristicUUID
|
bleDevice, notifyServiceUUID, bleNotifyCharacteristicUUID
|
||||||
)
|
)
|
||||||
|
} else if (data0 == 0x23 && data1 == 0x00) {
|
||||||
|
LogUtil.e("${bleDevice.mac},获取手机定位")
|
||||||
|
XEventBus.post(EventName.BleGetLocation, bleDevice.mac)
|
||||||
} else {
|
} else {
|
||||||
val deviceData = ReceiveDeviceData(bleDevice, data, bleDevice.mac)
|
val deviceData = ReceiveDeviceData(bleDevice, data, bleDevice.mac)
|
||||||
XEventBus.post(EventName.DeviceReceiveData, deviceData)
|
XEventBus.post(EventName.DeviceReceiveData, deviceData)
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ class FencesPolygonView : View {
|
|||||||
private var mOutHideRectWidth = 0f
|
private var mOutHideRectWidth = 0f
|
||||||
private var mOutHideRectHeight = 0f
|
private var mOutHideRectHeight = 0f
|
||||||
|
|
||||||
|
//限制边长
|
||||||
|
var mLimitSide = 0f
|
||||||
|
|
||||||
//定位图标
|
//定位图标
|
||||||
private var mLocationBitmap: Bitmap? = null
|
private var mLocationBitmap: Bitmap? = null
|
||||||
private var mDotBitmap: Bitmap? = null
|
private var mDotBitmap: Bitmap? = null
|
||||||
@@ -334,7 +337,12 @@ class FencesPolygonView : View {
|
|||||||
if (intersectTFEF) {
|
if (intersectTFEF) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||||
|
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mOutHideRectWidth = tempRect.width()
|
||||||
|
mOutHideRectHeight = tempRect.height()
|
||||||
mAPoint.x = x
|
mAPoint.x = x
|
||||||
mAPoint.y = y
|
mAPoint.y = y
|
||||||
isInvalidate = true
|
isInvalidate = true
|
||||||
@@ -391,6 +399,12 @@ class FencesPolygonView : View {
|
|||||||
if (intersectTAFA) {
|
if (intersectTAFA) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||||
|
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mOutHideRectWidth = tempRect.width()
|
||||||
|
mOutHideRectHeight = tempRect.height()
|
||||||
mFPoint.x = x
|
mFPoint.x = x
|
||||||
mFPoint.y = y
|
mFPoint.y = y
|
||||||
isInvalidate = true
|
isInvalidate = true
|
||||||
@@ -446,6 +460,12 @@ class FencesPolygonView : View {
|
|||||||
if (intersectTDED) {
|
if (intersectTDED) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||||
|
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mOutHideRectWidth = tempRect.width()
|
||||||
|
mOutHideRectHeight = tempRect.height()
|
||||||
mEPoint.x = x
|
mEPoint.x = x
|
||||||
mEPoint.y = y
|
mEPoint.y = y
|
||||||
isInvalidate = true
|
isInvalidate = true
|
||||||
@@ -501,6 +521,12 @@ class FencesPolygonView : View {
|
|||||||
if (intersectTEFE) {
|
if (intersectTEFE) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||||
|
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mOutHideRectWidth = tempRect.width()
|
||||||
|
mOutHideRectHeight = tempRect.height()
|
||||||
mDPoint.x = x
|
mDPoint.x = x
|
||||||
mDPoint.y = y
|
mDPoint.y = y
|
||||||
isInvalidate = true
|
isInvalidate = true
|
||||||
@@ -556,6 +582,12 @@ class FencesPolygonView : View {
|
|||||||
if (intersectTFAF) {
|
if (intersectTFAF) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||||
|
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mOutHideRectWidth = tempRect.width()
|
||||||
|
mOutHideRectHeight = tempRect.height()
|
||||||
mCPoint.x = x
|
mCPoint.x = x
|
||||||
mCPoint.y = y
|
mCPoint.y = y
|
||||||
isInvalidate = true
|
isInvalidate = true
|
||||||
@@ -611,6 +643,12 @@ class FencesPolygonView : View {
|
|||||||
if (intersectTAAB) {
|
if (intersectTAAB) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
val tempRect = getTempRect(mTouchPointTag, mTempPoint)
|
||||||
|
if (mLimitSide > 0 && (tempRect.width() < mLimitSide || tempRect.height() < mLimitSide)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mOutHideRectWidth = tempRect.width()
|
||||||
|
mOutHideRectHeight = tempRect.height()
|
||||||
mBPoint.x = x
|
mBPoint.x = x
|
||||||
mBPoint.y = y
|
mBPoint.y = y
|
||||||
isInvalidate = true
|
isInvalidate = true
|
||||||
@@ -657,12 +695,65 @@ class FencesPolygonView : View {
|
|||||||
return super.onTouchEvent(event)
|
return super.onTouchEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTempRect(touchPointTag: String, tempPoint: Point) {
|
private fun getTempRect(touchPointTag: String, tempPoint: PointBean): RectF {
|
||||||
when (touchPointTag) {
|
when (touchPointTag) {
|
||||||
mTageA -> {
|
mTageA -> {
|
||||||
|
val listX =
|
||||||
|
listOf(tempPoint.x, mBPoint.x, mCPoint.x, mDPoint.x, mEPoint.x, mFPoint.x)
|
||||||
|
val listY =
|
||||||
|
listOf(tempPoint.y, mBPoint.y, mCPoint.y, mDPoint.y, mEPoint.y, mFPoint.y)
|
||||||
|
return getTRect(listX, listY)
|
||||||
|
}
|
||||||
|
|
||||||
|
mTageB -> {
|
||||||
|
val listX =
|
||||||
|
listOf(mAPoint.x, tempPoint.x, mCPoint.x, mDPoint.x, mEPoint.x, mFPoint.x)
|
||||||
|
val listY =
|
||||||
|
listOf(mAPoint.y, tempPoint.y, mCPoint.y, mDPoint.y, mEPoint.y, mFPoint.y)
|
||||||
|
return getTRect(listX, listY)
|
||||||
|
}
|
||||||
|
|
||||||
|
mTageC -> {
|
||||||
|
val listX =
|
||||||
|
listOf(mAPoint.x, mBPoint.x, tempPoint.x, mDPoint.x, mEPoint.x, mFPoint.x)
|
||||||
|
val listY =
|
||||||
|
listOf(mAPoint.y, mBPoint.y, tempPoint.y, mDPoint.y, mEPoint.y, mFPoint.y)
|
||||||
|
return getTRect(listX, listY)
|
||||||
|
}
|
||||||
|
|
||||||
|
mTageD -> {
|
||||||
|
val listX =
|
||||||
|
listOf(mAPoint.x, mBPoint.x, mCPoint.x, tempPoint.x, mEPoint.x, mFPoint.x)
|
||||||
|
val listY =
|
||||||
|
listOf(mAPoint.y, mBPoint.y, mCPoint.y, tempPoint.y, mEPoint.y, mFPoint.y)
|
||||||
|
return getTRect(listX, listY)
|
||||||
|
}
|
||||||
|
|
||||||
|
mTageE -> {
|
||||||
|
val listX =
|
||||||
|
listOf(mAPoint.x, mBPoint.x, mCPoint.x, mDPoint.x, tempPoint.x, mFPoint.x)
|
||||||
|
val listY =
|
||||||
|
listOf(mAPoint.y, mBPoint.y, mCPoint.y, mDPoint.y, tempPoint.y, mFPoint.y)
|
||||||
|
return getTRect(listX, listY)
|
||||||
|
}
|
||||||
|
|
||||||
|
mTageF -> {
|
||||||
|
val listX =
|
||||||
|
listOf(mAPoint.x, mBPoint.x, mCPoint.x, mDPoint.x, mEPoint.x, tempPoint.x)
|
||||||
|
val listY =
|
||||||
|
listOf(mAPoint.y, mBPoint.y, mCPoint.y, mDPoint.y, mEPoint.y, tempPoint.y)
|
||||||
|
return getTRect(listX, listY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return RectF()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTRect(listX: List<Float>, listY: List<Float>): RectF {
|
||||||
|
val minX = listX.min()
|
||||||
|
val minY = listY.min()
|
||||||
|
val maxX = listX.max()
|
||||||
|
val maxY = listY.max()
|
||||||
|
return RectF(minX, minY, maxX, maxY)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun crossProduct(p1: PointBean, p2: PointBean, p3: PointBean): Float {
|
private fun crossProduct(p1: PointBean, p2: PointBean, p3: PointBean): Float {
|
||||||
|
|||||||
818
app/src/main/java/com/abbidot/tracker/widget/FencesRectView3.kt
Normal file
818
app/src/main/java/com/abbidot/tracker/widget/FencesRectView3.kt
Normal file
@@ -0,0 +1,818 @@
|
|||||||
|
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 FencesRectView3 : 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 mZoomBitmap1: Bitmap? = null
|
||||||
|
private var mZoomBitmap2: 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)
|
||||||
|
mZoomBitmap1 =
|
||||||
|
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fence_rect_zoom_svg)
|
||||||
|
mZoomBitmap2 =
|
||||||
|
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fence_rect_zoom)
|
||||||
|
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=$isNeedMeasure,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()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startDraw(canvas: Canvas) {
|
||||||
|
|
||||||
|
// if (mRectWidth == 0f && mRectHeight == 0f) return
|
||||||
|
|
||||||
|
|
||||||
|
mRectF.apply {
|
||||||
|
left = mRectLeft
|
||||||
|
top = mRectTop
|
||||||
|
right = mRectRight
|
||||||
|
bottom = mRectBottom
|
||||||
|
}
|
||||||
|
|
||||||
|
mLocationBitmap?.apply {
|
||||||
|
canvas.drawBitmap(
|
||||||
|
this, mRectF.centerX() - width / 2, mRectF.centerY() - height / 2, null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
mZoomBitmap1?.apply {
|
||||||
|
canvas.drawBitmap(
|
||||||
|
this, mRectRight - width / 2, mRectBottom - height / 2, null
|
||||||
|
)
|
||||||
|
canvas.drawBitmap(
|
||||||
|
this, mRectLeft - width / 2, mRectTop - height / 2, null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
mZoomBitmap2?.apply {
|
||||||
|
canvas.drawBitmap(
|
||||||
|
this, mRectRight - width / 2, mRectTop - height / 2, null
|
||||||
|
)
|
||||||
|
canvas.drawBitmap(
|
||||||
|
this, mRectLeft - 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
|
||||||
|
|
||||||
|
canvas.drawText(
|
||||||
|
mRectWidthDistanceText,
|
||||||
|
mRectF.centerX() - textWidth / 2,
|
||||||
|
mRectBottom + textHeight,
|
||||||
|
mTextPaint
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(mRectHeightDistanceText)) {
|
||||||
|
//文字宽度
|
||||||
|
val textWidth = mTextPaint.measureText(mRectHeightDistanceText)
|
||||||
|
//文字高度
|
||||||
|
val textHeight = fontMetrics.bottom - fontMetrics.top
|
||||||
|
|
||||||
|
canvas.drawText(
|
||||||
|
mRectHeightDistanceText,
|
||||||
|
mRectRight + textWidth / 10,
|
||||||
|
mRectF.centerY() + 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) {
|
||||||
|
mZoomBitmap1 = 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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var mClickTag = 0
|
||||||
|
|
||||||
|
@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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//是否按下了放大缩小按钮
|
||||||
|
mZoomBitmap1?.apply {
|
||||||
|
// if (!isRotate && isClickScale(x, y, mRotateAngle)) {
|
||||||
|
if (!isRotate) {
|
||||||
|
if (x > mRectF.left - width / 2 && x < mRectF.left + width / 2 && y > mRectF.top - height / 2 && y < mRectF.top + height / 2) {
|
||||||
|
isScale = true
|
||||||
|
mClickTag = 1
|
||||||
|
LogUtil.e("点击了放大缩小")
|
||||||
|
mOldX = x
|
||||||
|
mOldY = y
|
||||||
|
return true
|
||||||
|
} else if (isClickScale(x, y, mRotateAngle)) {
|
||||||
|
isScale = true
|
||||||
|
mClickTag = 3
|
||||||
|
LogUtil.e("点击了放大缩小")
|
||||||
|
mOldX = x
|
||||||
|
mOldY = y
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mZoomBitmap2?.apply {
|
||||||
|
if (!isRotate) {
|
||||||
|
if (x > mRectF.right - width / 2 && x < mRectF.right + width / 2 && y > mRectF.top - height / 2 && y < mRectF.top + height / 2) {
|
||||||
|
isScale = true
|
||||||
|
mClickTag = 2
|
||||||
|
LogUtil.e("点击了放大缩小")
|
||||||
|
mOldX = x
|
||||||
|
mOldY = y
|
||||||
|
return true
|
||||||
|
} else if (x > mRectF.left - width / 2 && x < mRectF.left + width / 2 && y > mRectF.bottom - height / 2 && y < mRectF.bottom + height / 2) {
|
||||||
|
isScale = true
|
||||||
|
mClickTag = 4
|
||||||
|
LogUtil.e("点击了放大缩小")
|
||||||
|
mOldX = x
|
||||||
|
mOldY = y
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//因为有旋转角度,需要减去中心
|
||||||
|
if (mRectF.contains(x, y)) {
|
||||||
|
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
|
||||||
|
when (mClickTag) {
|
||||||
|
1 -> {
|
||||||
|
mRectLeft = x
|
||||||
|
mRectTop = y
|
||||||
|
}
|
||||||
|
|
||||||
|
2 -> {
|
||||||
|
mRectRight = x
|
||||||
|
mRectTop = y
|
||||||
|
}
|
||||||
|
|
||||||
|
3 -> {
|
||||||
|
mRectRight = x
|
||||||
|
mRectBottom = y
|
||||||
|
}
|
||||||
|
|
||||||
|
4 -> {
|
||||||
|
mRectLeft = x
|
||||||
|
mRectBottom = y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
invalidate()
|
||||||
|
return true
|
||||||
|
} else if (isDrag) {
|
||||||
|
val transformX = x - mOldX
|
||||||
|
val transformY = y - mOldY
|
||||||
|
mRectLeft += transformX
|
||||||
|
mRectTop += transformY
|
||||||
|
mRectRight += transformX
|
||||||
|
mRectBottom += 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 - mZoomBitmap1!!.width)
|
||||||
|
var x2 = (mRectWidth / 2 + mZoomBitmap1!!.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
|
||||||
|
mRectLeft = - mRectWidth / 2
|
||||||
|
mRectTop = - mRectHeight / 2
|
||||||
|
mRectRight = mRectWidth / 2
|
||||||
|
mRectBottom = mRectHeight / 2
|
||||||
|
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 != mZoomBitmap1) {
|
||||||
|
mZoomBitmap1?.recycle()
|
||||||
|
mZoomBitmap1 = null
|
||||||
|
}
|
||||||
|
if (null != mZoomBitmap2) {
|
||||||
|
mZoomBitmap2?.recycle()
|
||||||
|
mZoomBitmap2 = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BIN
app/src/main/res/drawable-xhdpi/icon_fence_rect_zoom.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/icon_fence_rect_zoom.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 531 B |
BIN
app/src/main/res/drawable-xxhdpi/icon_fence_rect_zoom.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/icon_fence_rect_zoom.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 778 B |
BIN
app/src/main/res/drawable-xxxhdpi/icon_fence_rect_zoom.png
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/icon_fence_rect_zoom.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
@@ -5,7 +5,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context=".ui.activity.account.FencesAddActivity">
|
tools:context=".deprecated.ui.activity.profile.FencesAddActivity">
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/fences_add_bar"
|
android:id="@+id/fences_add_bar"
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import androidx.annotation.StringDef
|
|||||||
EventName.RefreshMessage,
|
EventName.RefreshMessage,
|
||||||
EventName.BluetoothSwitch,
|
EventName.BluetoothSwitch,
|
||||||
EventName.BleReport,
|
EventName.BleReport,
|
||||||
|
EventName.BleGetLocation,
|
||||||
EventName.BleReportData,
|
EventName.BleReportData,
|
||||||
EventName.LogReport,
|
EventName.LogReport,
|
||||||
EventName.ActionConDeviceState
|
EventName.ActionConDeviceState
|
||||||
@@ -104,5 +105,7 @@ annotation class EventName {
|
|||||||
|
|
||||||
//日志上报数据
|
//日志上报数据
|
||||||
const val LogReport = "logReport"
|
const val LogReport = "logReport"
|
||||||
|
//设备获取手机位置
|
||||||
|
const val BleGetLocation = "bleGetLocation"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user