矩形围栏修改为每个角都可以拖动,且对角固定不动

This commit is contained in:
2026-10-13 18:12:04 +08:00
parent ea8d083cdc
commit c161f90b0e
9 changed files with 304 additions and 164 deletions

View File

@@ -30,8 +30,8 @@ android {
targetSdkVersion 35
versionCode 2601
// versionName "2.6.1"
versionName "2.6.1-Beta2"
4
versionName "2.6.1-Beta3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {

View File

@@ -618,7 +618,7 @@ open class AddAndEditFencesZoneBaseActivity :
R.color.red_color3,
R.drawable.icon_fences_zone_gps_red_svg,
R.drawable.icon_fence_rect_zoom_red_svg,
R.drawable.icon_fence_dot_red_svg,
R.drawable.icon_fence_rect_zoom_red,
R.drawable.icon_fence_rect_red_rotate_svg
)
fencesZonePolygonView.setColorAndImage(

View File

@@ -14,7 +14,7 @@ import com.abbidot.tracker.util.LonAndLatUtil
import com.abbidot.tracker.vm.GeoCoderViewModel
import com.abbidot.tracker.widget.FencesCircleView
import com.abbidot.tracker.widget.FencesPolygonView
import com.abbidot.tracker.widget.FencesRectView
import com.abbidot.tracker.widget.FencesRectView2
import com.google.android.gms.maps.model.LatLng
/**
@@ -30,7 +30,7 @@ class FencesAddEditMapCommon : BaseMapCommon() {
context: Context,
fencesBean: FencesBean,
fencesCircleView: FencesCircleView,
fencesRectView: FencesRectView,
fencesRectView: FencesRectView2,
fencesPolygonView: FencesPolygonView,
isEdit: Boolean,
onActivityCallBack: OnActivityCallBack?,

View File

@@ -823,7 +823,15 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
isMoveCamera = false
}
mHomeMapCommon.startRefreshUserLocation()
mHomeMapCommon.updateOtherPetLatLng(otherPets)
getHomeV2Activity()?.let { m ->
m.getPet(false)?.let { p ->
//删除当前选中宠物
otherPets?.let { o ->
mHomeMapCommon.updateOtherPetLatLng(o.filter { it.petId != p.petId }
.toMutableList())
}
}
}
if (isShowFence) {
fences?.let { fences ->

View File

@@ -13,7 +13,7 @@ import com.abbidot.tracker.util.LonAndLatUtil
import com.abbidot.tracker.util.Util
import com.abbidot.tracker.widget.FencesCircleView
import com.abbidot.tracker.widget.FencesPolygonView
import com.abbidot.tracker.widget.FencesRectView
import com.abbidot.tracker.widget.FencesRectView2
import com.baidu.location.BDLocation
import com.baidu.mapapi.map.BaiduMap
import com.baidu.mapapi.map.MapStatus
@@ -31,7 +31,7 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
private lateinit var mFencesBean: FencesBean
private var isEditFences = false
private lateinit var mFencesCircleView: FencesCircleView
private lateinit var mFencesRectView: FencesRectView
private lateinit var mFencesRectView: FencesRectView2
private lateinit var mFencesPolygonView: FencesPolygonView
private var mOnActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack? = null
@@ -45,7 +45,7 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
context: Context,
fencesBean: FencesBean,
fencesCircleView: FencesCircleView,
fencesRectView: FencesRectView,
fencesRectView: FencesRectView2,
fencesPolygonView: FencesPolygonView,
isEdit: Boolean,
onActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack?,

View File

@@ -12,7 +12,7 @@ import com.abbidot.tracker.ui.common.map.FencesAddEditMapCommon
import com.abbidot.tracker.util.Util
import com.abbidot.tracker.widget.FencesCircleView
import com.abbidot.tracker.widget.FencesPolygonView
import com.abbidot.tracker.widget.FencesRectView
import com.abbidot.tracker.widget.FencesRectView2
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.LatLng
import kotlin.math.abs
@@ -28,7 +28,7 @@ class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {
private lateinit var mFencesBean: FencesBean
private var isEditFences = false
private lateinit var mFencesCircleView: FencesCircleView
private lateinit var mFencesRectView: FencesRectView
private lateinit var mFencesRectView: FencesRectView2
private lateinit var mFencesPolygonView: FencesPolygonView
private var mOnActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack? = null
@@ -46,7 +46,7 @@ class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {
context: Context,
fencesBean: FencesBean,
fencesCircleView: FencesCircleView,
fencesRectView: FencesRectView,
fencesRectView: FencesRectView2,
fencesPolygonView: FencesPolygonView,
isEdit: Boolean,
onActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack?,

View File

@@ -32,7 +32,7 @@ import kotlin.math.sqrt
/**
*Created by .yzq on 2022/1/22/022.
* @link
* @description:添加围栏矩形,只针对围栏
* @description:添加围栏矩形,只针对围栏,固定一个角拖动,其他角会跟随拖动
*
* 按以下点组成的矩形
* A B

View File

@@ -25,6 +25,7 @@ import com.qmuiteam.qmui.util.QMUIDisplayHelper
import kotlin.math.abs
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.max
import kotlin.math.pow
import kotlin.math.sin
import kotlin.math.sqrt
@@ -32,7 +33,7 @@ import kotlin.math.sqrt
/**
*Created by .yzq on 2022/1/22/022.
* @link
* @description:添加围栏矩形,只针对围栏
* @description:添加围栏矩形,只针对围栏,拖动哪个角就哪个角就变化,其他角会保持不动
*
* 按以下点组成的矩形
* A B
@@ -63,8 +64,8 @@ class FencesRectView2 : View {
//定位图标
private var mLocationBitmap: Bitmap? = null
private var mDotBitmap: Bitmap? = null
private var mZoomBitmap: Bitmap? = null
private var mZoomBitmap1: Bitmap? = null
private var mZoomBitmap2: Bitmap? = null
private var mRotateBitmap: Bitmap? = null
private var mDashedColor = 0
@@ -76,6 +77,23 @@ class FencesRectView2 : View {
private var mOldX = 0f
private var mOldY = 0f
//是否正在拖动4个角中的一个
private var isCornerDrag = false
//当前拖动的是哪个角(POINT_A/B/C/D)
private var mCornerDragPoint = 0
//拖动时保持不动的对角屏幕坐标
private var mFixedCornerX = 0f
private var mFixedCornerY = 0f
//本手势是否已触碰过最小尺寸,保证每次手势只弹一次提示
private var mHitMinThisGesture = false
//按下时localX/localY的正负号(1或-1),拖动中变号说明越过了对角,钉住不动
private var mInitialLocalXSign = 0
private var mInitialLocalYSign = 0
//是否显示距离
private var isShowDistance = true
private var mRectWidthDistanceText = ""
@@ -137,11 +155,12 @@ class FencesRectView2 : View {
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 =
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)
@@ -175,14 +194,6 @@ class FencesRectView2 : View {
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)
}
}
@@ -213,25 +224,6 @@ class FencesRectView2 : View {
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) {
@@ -250,12 +242,22 @@ class FencesRectView2 : View {
mRectTop - height - QMUIDisplayHelper.dpToPx(2).toFloat(),
null
)
mStartRotateAngle = atan2(mRectTop - height, startX - width / 2) / Math.PI * 180
}
mZoomBitmap?.apply {
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)
@@ -339,9 +341,10 @@ class FencesRectView2 : View {
dashedColorRes: Int = 0,
fillBgColorRes: Int = 0,
locationDrawableRes: Int = 0,
zoomDrawableRes: Int = 0,
dotDrawableRes: Int = 0,
rotateDrawableRes: Int = 0,disTextColorRes: Int = 0
zoom1DrawableRes: Int = 0,
zoom2DrawableRes: Int = 0,
rotateDrawableRes: Int = 0,
disTextColorRes: Int = 0
) {
var isRefresh = false
if (dashedColorRes > 0) {
@@ -359,18 +362,18 @@ class FencesRectView2 : View {
mLocationBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, locationDrawableRes)
isRefresh = true
}
if (zoomDrawableRes > 0) {
mZoomBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, zoomDrawableRes)
if (zoom1DrawableRes > 0) {
mZoomBitmap1 = ImageUtil.getBitmapFromDrawableAndSvg(context, zoom1DrawableRes)
isRefresh = true
}
if (zoom2DrawableRes > 0) {
mZoomBitmap2 = ImageUtil.getBitmapFromDrawableAndSvg(context, zoom2DrawableRes)
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
@@ -442,28 +445,38 @@ class FencesRectView2 : View {
val x = event.x
val y = event.y
LogUtil.e("action_down,x=$x,y=$y")
//1. 旋转按钮(优先,旋转状态下禁止其他手势)
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("点击了旋转")
//按下瞬间记录起始角度 = 当前旋转的等效起始角度,这样MOVE里 transformAngle - mStartRotateAngle 保留已有旋转并叠加增量
mStartRotateAngle =
atan2(y - mCentreY, x - mCentreX) / Math.PI * 180 - mRotateAngle
isRotate = true
return true
}
}
//是否按下了放大缩小按钮
mZoomBitmap?.apply {
if (!isRotate && isClickScale(x, y, mRotateAngle)) {
isScale = true
LogUtil.e("点击了放大缩小")
mOldX = x
mOldY = y
//2. 矩形的4个角点,按下后拖角、对角不动(优先于角点上的放大按钮,因为放大按钮功能已被角点拖覆盖)
if (isClickCorner(x, y)) {
LogUtil.e("点击了角点:$mCornerDragPoint")
isCornerDrag = true
return true
}
}
//3. 放大缩小按钮(作为后备,在非角点区域)
// mZoomBitmap1?.apply {
// if (isClickScale(x, y, mRotateAngle)) {
// isScale = true
// LogUtil.e("点击了放大缩小")
// mOldX = x
// mOldY = y
// return true
// }
// }
//因为有旋转角度,需要减去中心
//4. 整体拖动(需要在矩形区域内,且旋转时判断不准,可接受)
if (mRectF.contains(x - mCentreX, y - mCentreY)) {
isDrag = true
mOldX = x
@@ -487,26 +500,34 @@ class FencesRectView2 : View {
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()
// 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) {
// isHasLimitSide = true
// return true
// }
// } else if (newRectWidth < mLimitSide || newRectHeight < mLimitSide) {
// isHasLimitSide = true
// mRotateScaleClickListener?.rectMinSizeClick()
// return true
// }
// mRotateScaleClickListener?.rectScalingClick()
// mRectWidth = newRectWidth
// mRectHeight = newRectHeight
// mOldX = x
// mOldY = y
// invalidate()
// return true
// }
else if (isCornerDrag) {
moveCorner(x, y)
return true
} else if (isDrag) {
val transformX = x - mOldX
@@ -521,6 +542,22 @@ class FencesRectView2 : View {
}
MotionEvent.ACTION_UP -> {
handleActionUpOrCancel()
}
MotionEvent.ACTION_CANCEL -> {
handleActionUpOrCancel()
}
}
return super.onTouchEvent(event)
}
/**
* ACTION_UP 和 ACTION_CANCEL 共用的收尾:重置所有手势状态
* ACTION_CANCEL 在父 View(如百度地图)拦截触摸时触发,必须正确清理
*/
private fun handleActionUpOrCancel() {
mHitMinThisGesture = false
if (isRotate) {
mRotateScaleClickListener?.rectRotateClick()
isRotate = false
@@ -529,6 +566,10 @@ class FencesRectView2 : View {
mRotateScaleClickListener?.rectScaleEndClick()
isScale = false
}
if (isCornerDrag) {
mRotateScaleClickListener?.rectScaleEndClick()
isCornerDrag = false
}
if (isDrag) {
mRotateScaleClickListener?.rectEndDragClick()
isDrag = false
@@ -536,9 +577,6 @@ class FencesRectView2 : View {
invalidate()
}
}
}
return super.onTouchEvent(event)
}
/**
* @param x 是坐标轴移动以(mCentreX,mCentreY)原点的坐标
@@ -563,14 +601,19 @@ class FencesRectView2 : View {
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)
private fun isClick(
clickX: Float,
clickY: Float,
xX1: Float,
xX2: Float,
yY1: Float,
yY2: Float,
rotate: Double
): Boolean {
var x1 = xX1
var x2 = xX2
var y1 = yY1
var y2 = yY2
val minX = getRotateXY(x1, y1, rotate)
val maxX = getRotateXY(x2, y2, rotate)
x1 = minX[0]
@@ -586,63 +629,161 @@ class FencesRectView2 : View {
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 padding = QMUIDisplayHelper.dpToPx(8).toFloat()
x1 -= padding
x2 += padding
y1 -= padding
y2 += padding
val transformX = clickX - mCentreX
val transformY = clickY - mCentreY
if (transformX in x1..x2 && transformY in y1..y2) {
return true
return transformX in x1..x2 && transformY in y1..y2
}
return false
/**
* 是否点击按下了旋转,按照移动了坐标轴原点(mCentreX,mCentreY)计算初始坐标
* 按钮绘制在矩形上边中点正上方,点击范围紧贴按钮自身大小
*/
private fun isClickRotate(clickX: Float, clickY: Float, rotate: Double): Boolean {
val halfW = mRotateBitmap!!.width / 2f
val halfH = mRotateBitmap!!.height / 2f
//按钮中心在本地坐标的位置(以矩形中心为原点,未旋转)
val btnCx = 0f
val btnCy = -(mRectHeight / 2f + halfH + QMUIDisplayHelper.dpToPx(2).toFloat())
val x1 = btnCx - halfW
val x2 = btnCx + halfW
val y1 = btnCy - halfH
val y2 = btnCy + halfH
return isClick(clickX, clickY, x1, x2, y1, y2, rotate)
}
/**
* 是否点击按下了放大缩小,按照移动了坐标轴原点(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 x1 = (mRectWidth / 2 - mZoomBitmap1!!.width / 2)
val x2 = (mRectWidth / 2 + mZoomBitmap1!!.width / 2)
val y1 = (mRectHeight / 2 - mZoomBitmap1!!.height)
val y2 = (mRectHeight / 2 + mZoomBitmap1!!.height)
return isClick(clickX, clickY, x1, x2, y1, y2, rotate)
}
/**
* 是否按下了矩形的4个角中的一个,按下时记录当前拖动的角和需要保持不动的对角坐标
*/
private fun isClickCorner(clickX: Float, clickY: Float): Boolean {
if (mRectWidth == 0f && mRectHeight == 0f) return false
//因为有旋转角度,先把点击的坐标逆旋转回矩形本地坐标系(以矩形中心为原点)
val angle = Math.toRadians(mRotateAngle)
val cosAngle = cos(angle).toFloat()
val sinAngle = sin(angle).toFloat()
val transformX = clickX - mCentreX
val transformY = clickY - mCentreY
if (transformX in x1..x2 && transformY in y1..y2) {
val localX = transformX * cosAngle + transformY * sinAngle
val localY = -transformX * sinAngle + transformY * cosAngle
for (corner in intArrayOf(POINT_A, POINT_B, POINT_C, POINT_D)) {
val cornerXY = getRectLocalCornerXY(corner)
val offsetX = localX - cornerXY[0]
val offsetY = localY - cornerXY[1]
if (sqrt(offsetX.pow(2) + offsetY.pow(2)) <= getCornerTouchRadius()) {
mCornerDragPoint = corner
//记录需要保持不动的对角(屏幕坐标)
val fixedXY = getRectABCDXYPoint(getOppositePoint(corner))
mFixedCornerX = fixedXY[0]
mFixedCornerY = fixedXY[1]
//记录角点在本地坐标系中的正负号,拖动中变号说明越过了对角
mInitialLocalXSign = if (cornerXY[0] >= 0f) 1 else -1
mInitialLocalYSign = if (cornerXY[1] >= 0f) 1 else -1
return true
}
}
return false
}
/**
* 角点的触摸范围(圆形半径),基于实际绘制在角点的按钮尺寸,外加手指容差
*/
private fun getCornerTouchRadius(): Float {
val cornerIconHalf = listOfNotNull(mZoomBitmap1, mZoomBitmap2)
.maxOfOrNull { max(it.width, it.height) / 2f } ?: 0f
return cornerIconHalf + QMUIDisplayHelper.dpToPx(10)
}
/**
* 获取矩形某个角在本地坐标系(以矩形中心为原点,未旋转)的坐标
*/
private fun getRectLocalCornerXY(wherePoint: Int): FloatArray {
val halfWidth = mRectWidth / 2f
val halfHeight = mRectHeight / 2f
return when (wherePoint) {
POINT_A -> floatArrayOf(-halfWidth, -halfHeight)
POINT_B -> floatArrayOf(halfWidth, -halfHeight)
POINT_D -> floatArrayOf(-halfWidth, halfHeight)
else -> floatArrayOf(halfWidth, halfHeight)//POINT_C
}
}
/**
* 获取对角的点,A对C,B对D
*/
private fun getOppositePoint(wherePoint: Int): Int {
return when (wherePoint) {
POINT_A -> POINT_C
POINT_B -> POINT_D
POINT_C -> POINT_A
POINT_D -> POINT_B
else -> wherePoint
}
}
/**
* 拖动角点,对角保持不动,只改变当前拖动角的位置
* 对角指向手指的向量投影到矩形的宽高方向得到新的宽高,中心点取对角与拖动角连线的中点
*/
private fun moveCorner(moveX: Float, moveY: Float) {
//保持不动的对角指向手指位置的向量
val vectorX = moveX - mFixedCornerX
val vectorY = moveY - mFixedCornerY
val angle = Math.toRadians(mRotateAngle)
val cosAngle = cos(angle).toFloat()
val sinAngle = sin(angle).toFloat()
//把向量逆旋转回矩形本地坐标系,得到在宽、高方向上的投影
val localX = vectorX * cosAngle + vectorY * sinAngle
val localY = -vectorX * sinAngle + vectorY * cosAngle
//拖动中localX/localY变号说明手指已越过对角,钉住不动防止闪跳
val xSignFlipped = mInitialLocalXSign != 0 && (localX > 0f) != (mInitialLocalXSign > 0)
val ySignFlipped = mInitialLocalYSign != 0 && (localY > 0f) != (mInitialLocalYSign > 0)
//限制边长不能小于最小值,达到最小值后钉住不动,不允许翻过对角
val minSide =
if (mLimitSide == 0f) (mLocationBitmap?.height ?: 0).toFloat() else mLimitSide
if (xSignFlipped || ySignFlipped ||
(minSide > 0f && (abs(localX) < minSide || abs(localY) < minSide))
) {
if (!mHitMinThisGesture) {
mHitMinThisGesture = true
mRotateScaleClickListener?.rectMinSizeClick()
}
//已是最小值或越过对角,直接返回保持当前状态,不更新矩形
return
}
//脱离最小值,清标志
if (mHitMinThisGesture) {
mHitMinThisGesture = false
}
//限制后的本地坐标再转回屏幕坐标系
val newVectorX = localX * cosAngle - localY * sinAngle
val newVectorY = localX * sinAngle + localY * cosAngle
mRectWidth = abs(localX)
mRectHeight = abs(localY)
//中心点=对角与拖动角连线的中点,保证对角的位置不会动
mCentreX = mFixedCornerX + newVectorX / 2f
mCentreY = mFixedCornerY + newVectorY / 2f
mRotateScaleClickListener?.rectScalingClick()
invalidate()
}
/**
* 设置显示编辑的矩形(利用假设方式)
* 错误方式
@@ -736,22 +877,13 @@ class FencesRectView2 : View {
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
LogUtil.e("onDetachedFromWindow,${javaClass.canonicalName}视图销毁")
if (null != mDotBitmap) {
mDotBitmap?.recycle()
mDotBitmap = null
listOf(mLocationBitmap, mRotateBitmap, mZoomBitmap1, mZoomBitmap2).forEach { bm ->
if (bm != null && !bm.isRecycled) bm.recycle()
}
if (null != mLocationBitmap) {
mLocationBitmap?.recycle()
mLocationBitmap = null
}
if (null != mRotateBitmap) {
mRotateBitmap?.recycle()
mRotateBitmap = null
}
if (null != mZoomBitmap) {
mZoomBitmap?.recycle()
mZoomBitmap = null
}
mZoomBitmap1 = null
mZoomBitmap2 = null
}
}

View File

@@ -31,7 +31,7 @@
app:fences_circle_dashed_color="@color/select_color"
app:fences_circle_fill_bg_color="@color/select_color4" />
<com.abbidot.tracker.widget.FencesRectView
<com.abbidot.tracker.widget.FencesRectView2
android:id="@+id/fences_zone_rect_view"
android:layout_width="match_parent"
android:layout_height="match_parent"