矩形围栏修改为每个角都可以拖动,且对角固定不动
This commit is contained in:
@@ -30,8 +30,8 @@ android {
|
|||||||
targetSdkVersion 35
|
targetSdkVersion 35
|
||||||
versionCode 2601
|
versionCode 2601
|
||||||
// versionName "2.6.1"
|
// versionName "2.6.1"
|
||||||
versionName "2.6.1-Beta2"
|
versionName "2.6.1-Beta3"
|
||||||
4
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
ndk {
|
ndk {
|
||||||
|
|||||||
@@ -618,7 +618,7 @@ open class AddAndEditFencesZoneBaseActivity :
|
|||||||
R.color.red_color3,
|
R.color.red_color3,
|
||||||
R.drawable.icon_fences_zone_gps_red_svg,
|
R.drawable.icon_fences_zone_gps_red_svg,
|
||||||
R.drawable.icon_fence_rect_zoom_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
|
R.drawable.icon_fence_rect_red_rotate_svg
|
||||||
)
|
)
|
||||||
fencesZonePolygonView.setColorAndImage(
|
fencesZonePolygonView.setColorAndImage(
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import com.abbidot.tracker.util.LonAndLatUtil
|
|||||||
import com.abbidot.tracker.vm.GeoCoderViewModel
|
import com.abbidot.tracker.vm.GeoCoderViewModel
|
||||||
import com.abbidot.tracker.widget.FencesCircleView
|
import com.abbidot.tracker.widget.FencesCircleView
|
||||||
import com.abbidot.tracker.widget.FencesPolygonView
|
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
|
import com.google.android.gms.maps.model.LatLng
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,7 +30,7 @@ class FencesAddEditMapCommon : BaseMapCommon() {
|
|||||||
context: Context,
|
context: Context,
|
||||||
fencesBean: FencesBean,
|
fencesBean: FencesBean,
|
||||||
fencesCircleView: FencesCircleView,
|
fencesCircleView: FencesCircleView,
|
||||||
fencesRectView: FencesRectView,
|
fencesRectView: FencesRectView2,
|
||||||
fencesPolygonView: FencesPolygonView,
|
fencesPolygonView: FencesPolygonView,
|
||||||
isEdit: Boolean,
|
isEdit: Boolean,
|
||||||
onActivityCallBack: OnActivityCallBack?,
|
onActivityCallBack: OnActivityCallBack?,
|
||||||
|
|||||||
@@ -823,7 +823,15 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
|||||||
isMoveCamera = false
|
isMoveCamera = false
|
||||||
}
|
}
|
||||||
mHomeMapCommon.startRefreshUserLocation()
|
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) {
|
if (isShowFence) {
|
||||||
fences?.let { fences ->
|
fences?.let { fences ->
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import com.abbidot.tracker.util.LonAndLatUtil
|
|||||||
import com.abbidot.tracker.util.Util
|
import com.abbidot.tracker.util.Util
|
||||||
import com.abbidot.tracker.widget.FencesCircleView
|
import com.abbidot.tracker.widget.FencesCircleView
|
||||||
import com.abbidot.tracker.widget.FencesPolygonView
|
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.location.BDLocation
|
||||||
import com.baidu.mapapi.map.BaiduMap
|
import com.baidu.mapapi.map.BaiduMap
|
||||||
import com.baidu.mapapi.map.MapStatus
|
import com.baidu.mapapi.map.MapStatus
|
||||||
@@ -31,7 +31,7 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
|||||||
private lateinit var mFencesBean: FencesBean
|
private lateinit var mFencesBean: FencesBean
|
||||||
private var isEditFences = false
|
private var isEditFences = false
|
||||||
private lateinit var mFencesCircleView: FencesCircleView
|
private lateinit var mFencesCircleView: FencesCircleView
|
||||||
private lateinit var mFencesRectView: FencesRectView
|
private lateinit var mFencesRectView: FencesRectView2
|
||||||
private lateinit var mFencesPolygonView: FencesPolygonView
|
private lateinit var mFencesPolygonView: FencesPolygonView
|
||||||
private var mOnActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack? = null
|
private var mOnActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack? = null
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
|||||||
context: Context,
|
context: Context,
|
||||||
fencesBean: FencesBean,
|
fencesBean: FencesBean,
|
||||||
fencesCircleView: FencesCircleView,
|
fencesCircleView: FencesCircleView,
|
||||||
fencesRectView: FencesRectView,
|
fencesRectView: FencesRectView2,
|
||||||
fencesPolygonView: FencesPolygonView,
|
fencesPolygonView: FencesPolygonView,
|
||||||
isEdit: Boolean,
|
isEdit: Boolean,
|
||||||
onActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack?,
|
onActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack?,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import com.abbidot.tracker.ui.common.map.FencesAddEditMapCommon
|
|||||||
import com.abbidot.tracker.util.Util
|
import com.abbidot.tracker.util.Util
|
||||||
import com.abbidot.tracker.widget.FencesCircleView
|
import com.abbidot.tracker.widget.FencesCircleView
|
||||||
import com.abbidot.tracker.widget.FencesPolygonView
|
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.GoogleMap
|
||||||
import com.google.android.gms.maps.model.LatLng
|
import com.google.android.gms.maps.model.LatLng
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
@@ -28,7 +28,7 @@ class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {
|
|||||||
private lateinit var mFencesBean: FencesBean
|
private lateinit var mFencesBean: FencesBean
|
||||||
private var isEditFences = false
|
private var isEditFences = false
|
||||||
private lateinit var mFencesCircleView: FencesCircleView
|
private lateinit var mFencesCircleView: FencesCircleView
|
||||||
private lateinit var mFencesRectView: FencesRectView
|
private lateinit var mFencesRectView: FencesRectView2
|
||||||
private lateinit var mFencesPolygonView: FencesPolygonView
|
private lateinit var mFencesPolygonView: FencesPolygonView
|
||||||
private var mOnActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack? = null
|
private var mOnActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack? = null
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {
|
|||||||
context: Context,
|
context: Context,
|
||||||
fencesBean: FencesBean,
|
fencesBean: FencesBean,
|
||||||
fencesCircleView: FencesCircleView,
|
fencesCircleView: FencesCircleView,
|
||||||
fencesRectView: FencesRectView,
|
fencesRectView: FencesRectView2,
|
||||||
fencesPolygonView: FencesPolygonView,
|
fencesPolygonView: FencesPolygonView,
|
||||||
isEdit: Boolean,
|
isEdit: Boolean,
|
||||||
onActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack?,
|
onActivityCallBack: FencesAddEditMapCommon.OnActivityCallBack?,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import kotlin.math.sqrt
|
|||||||
/**
|
/**
|
||||||
*Created by .yzq on 2022/1/22/022.
|
*Created by .yzq on 2022/1/22/022.
|
||||||
* @link
|
* @link
|
||||||
* @description:添加围栏矩形,只针对围栏
|
* @description:添加围栏矩形,只针对围栏,固定一个角拖动,其他角会跟随拖动
|
||||||
*
|
*
|
||||||
* 按以下点组成的矩形
|
* 按以下点组成的矩形
|
||||||
* A B
|
* A B
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import com.qmuiteam.qmui.util.QMUIDisplayHelper
|
|||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.atan2
|
import kotlin.math.atan2
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
|
import kotlin.math.max
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
@@ -32,7 +33,7 @@ import kotlin.math.sqrt
|
|||||||
/**
|
/**
|
||||||
*Created by .yzq on 2022/1/22/022.
|
*Created by .yzq on 2022/1/22/022.
|
||||||
* @link
|
* @link
|
||||||
* @description:添加围栏矩形,只针对围栏
|
* @description:添加围栏矩形,只针对围栏,拖动哪个角就哪个角就变化,其他角会保持不动
|
||||||
*
|
*
|
||||||
* 按以下点组成的矩形
|
* 按以下点组成的矩形
|
||||||
* A B
|
* A B
|
||||||
@@ -63,8 +64,8 @@ class FencesRectView2 : View {
|
|||||||
|
|
||||||
//定位图标
|
//定位图标
|
||||||
private var mLocationBitmap: Bitmap? = null
|
private var mLocationBitmap: Bitmap? = null
|
||||||
private var mDotBitmap: Bitmap? = null
|
private var mZoomBitmap1: Bitmap? = null
|
||||||
private var mZoomBitmap: Bitmap? = null
|
private var mZoomBitmap2: Bitmap? = null
|
||||||
private var mRotateBitmap: Bitmap? = null
|
private var mRotateBitmap: Bitmap? = null
|
||||||
|
|
||||||
private var mDashedColor = 0
|
private var mDashedColor = 0
|
||||||
@@ -76,6 +77,23 @@ class FencesRectView2 : View {
|
|||||||
private var mOldX = 0f
|
private var mOldX = 0f
|
||||||
private var mOldY = 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 isShowDistance = true
|
||||||
private var mRectWidthDistanceText = ""
|
private var mRectWidthDistanceText = ""
|
||||||
@@ -137,11 +155,12 @@ class FencesRectView2 : View {
|
|||||||
mTextPaint.textSize = QMUIDisplayHelper.sp2px(context, 14).toFloat()
|
mTextPaint.textSize = QMUIDisplayHelper.sp2px(context, 14).toFloat()
|
||||||
mTextPaint.color = ContextCompat.getColor(mContext, R.color.black)
|
mTextPaint.color = ContextCompat.getColor(mContext, R.color.black)
|
||||||
|
|
||||||
mDotBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fence_dot_svg)
|
|
||||||
mLocationBitmap =
|
mLocationBitmap =
|
||||||
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fences_zone_gps_svg)
|
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fences_zone_gps_svg)
|
||||||
mZoomBitmap =
|
mZoomBitmap1 =
|
||||||
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fence_rect_zoom_svg)
|
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fence_rect_zoom_svg)
|
||||||
|
mZoomBitmap2 =
|
||||||
|
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fence_rect_zoom)
|
||||||
mRotateBitmap =
|
mRotateBitmap =
|
||||||
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fence_rect_rotate_svg)
|
ImageUtil.getBitmapFromDrawableAndSvg(context, R.drawable.icon_fence_rect_rotate_svg)
|
||||||
|
|
||||||
@@ -175,14 +194,6 @@ class FencesRectView2 : View {
|
|||||||
rotate(mRotateAngle.toFloat())
|
rotate(mRotateAngle.toFloat())
|
||||||
startDraw(this)
|
startDraw(this)
|
||||||
restore()
|
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, mFillPaint)
|
||||||
canvas.drawRect(mRectF, mStrokePaint)
|
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) {
|
if (isShowDistance) {
|
||||||
|
|
||||||
@@ -250,12 +242,22 @@ class FencesRectView2 : View {
|
|||||||
mRectTop - height - QMUIDisplayHelper.dpToPx(2).toFloat(),
|
mRectTop - height - QMUIDisplayHelper.dpToPx(2).toFloat(),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
mStartRotateAngle = atan2(mRectTop - height, startX - width / 2) / Math.PI * 180
|
|
||||||
}
|
}
|
||||||
mZoomBitmap?.apply {
|
mZoomBitmap1?.apply {
|
||||||
canvas.drawBitmap(
|
canvas.drawBitmap(
|
||||||
this, mRectRight - width / 2, mRectBottom - height / 2, null
|
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)
|
canvasDistanceText(canvas)
|
||||||
@@ -339,9 +341,10 @@ class FencesRectView2 : View {
|
|||||||
dashedColorRes: Int = 0,
|
dashedColorRes: Int = 0,
|
||||||
fillBgColorRes: Int = 0,
|
fillBgColorRes: Int = 0,
|
||||||
locationDrawableRes: Int = 0,
|
locationDrawableRes: Int = 0,
|
||||||
zoomDrawableRes: Int = 0,
|
zoom1DrawableRes: Int = 0,
|
||||||
dotDrawableRes: Int = 0,
|
zoom2DrawableRes: Int = 0,
|
||||||
rotateDrawableRes: Int = 0,disTextColorRes: Int = 0
|
rotateDrawableRes: Int = 0,
|
||||||
|
disTextColorRes: Int = 0
|
||||||
) {
|
) {
|
||||||
var isRefresh = false
|
var isRefresh = false
|
||||||
if (dashedColorRes > 0) {
|
if (dashedColorRes > 0) {
|
||||||
@@ -359,18 +362,18 @@ class FencesRectView2 : View {
|
|||||||
mLocationBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, locationDrawableRes)
|
mLocationBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, locationDrawableRes)
|
||||||
isRefresh = true
|
isRefresh = true
|
||||||
}
|
}
|
||||||
if (zoomDrawableRes > 0) {
|
if (zoom1DrawableRes > 0) {
|
||||||
mZoomBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, zoomDrawableRes)
|
mZoomBitmap1 = ImageUtil.getBitmapFromDrawableAndSvg(context, zoom1DrawableRes)
|
||||||
|
isRefresh = true
|
||||||
|
}
|
||||||
|
if (zoom2DrawableRes > 0) {
|
||||||
|
mZoomBitmap2 = ImageUtil.getBitmapFromDrawableAndSvg(context, zoom2DrawableRes)
|
||||||
isRefresh = true
|
isRefresh = true
|
||||||
}
|
}
|
||||||
if (rotateDrawableRes > 0) {
|
if (rotateDrawableRes > 0) {
|
||||||
mRotateBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, rotateDrawableRes)
|
mRotateBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, rotateDrawableRes)
|
||||||
isRefresh = true
|
isRefresh = true
|
||||||
}
|
}
|
||||||
if (dotDrawableRes > 0) {
|
|
||||||
mDotBitmap = ImageUtil.getBitmapFromDrawableAndSvg(context, dotDrawableRes)
|
|
||||||
isRefresh = true
|
|
||||||
}
|
|
||||||
if (disTextColorRes > 0) {
|
if (disTextColorRes > 0) {
|
||||||
mTextPaint.color = ContextCompat.getColor(context, disTextColorRes)
|
mTextPaint.color = ContextCompat.getColor(context, disTextColorRes)
|
||||||
isRefresh = true
|
isRefresh = true
|
||||||
@@ -442,28 +445,38 @@ class FencesRectView2 : View {
|
|||||||
val x = event.x
|
val x = event.x
|
||||||
val y = event.y
|
val y = event.y
|
||||||
LogUtil.e("action_down,x=$x,y=$y")
|
LogUtil.e("action_down,x=$x,y=$y")
|
||||||
|
//1. 旋转按钮(优先,旋转状态下禁止其他手势)
|
||||||
mRotateBitmap?.apply {
|
mRotateBitmap?.apply {
|
||||||
LogUtil.e("x2=${width / 2f + mCentreX},x1=${-width / 2f + mCentreX}")
|
LogUtil.e("x2=${width / 2f + mCentreX},x1=${-width / 2f + mCentreX}")
|
||||||
LogUtil.e("y2=${-(mRectHeight / 2 + height) + mCentreY},aaa=${-mRectHeight / 2 + mCentreY}")
|
LogUtil.e("y2=${-(mRectHeight / 2 + height) + mCentreY},aaa=${-mRectHeight / 2 + mCentreY}")
|
||||||
|
|
||||||
if (isClickRotate(x, y, mRotateAngle)) {
|
if (isClickRotate(x, y, mRotateAngle)) {
|
||||||
LogUtil.e("点击了旋转")
|
LogUtil.e("点击了旋转")
|
||||||
|
//按下瞬间记录起始角度 = 当前旋转的等效起始角度,这样MOVE里 transformAngle - mStartRotateAngle 保留已有旋转并叠加增量
|
||||||
|
mStartRotateAngle =
|
||||||
|
atan2(y - mCentreY, x - mCentreX) / Math.PI * 180 - mRotateAngle
|
||||||
isRotate = true
|
isRotate = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//是否按下了放大缩小按钮
|
//2. 矩形的4个角点,按下后拖角、对角不动(优先于角点上的放大按钮,因为放大按钮功能已被角点拖覆盖)
|
||||||
mZoomBitmap?.apply {
|
if (isClickCorner(x, y)) {
|
||||||
if (!isRotate && isClickScale(x, y, mRotateAngle)) {
|
LogUtil.e("点击了角点:$mCornerDragPoint")
|
||||||
isScale = true
|
isCornerDrag = true
|
||||||
LogUtil.e("点击了放大缩小")
|
return true
|
||||||
mOldX = x
|
|
||||||
mOldY = y
|
|
||||||
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)) {
|
if (mRectF.contains(x - mCentreX, y - mCentreY)) {
|
||||||
isDrag = true
|
isDrag = true
|
||||||
mOldX = x
|
mOldX = x
|
||||||
@@ -487,26 +500,34 @@ class FencesRectView2 : View {
|
|||||||
LogUtil.e("mRotateAngle=$mRotateAngle")
|
LogUtil.e("mRotateAngle=$mRotateAngle")
|
||||||
invalidate()
|
invalidate()
|
||||||
return true
|
return true
|
||||||
} else if (isScale) {
|
}
|
||||||
LogUtil.e("mRectWidth=$mRectWidth,mRectHeight=$mRectHeight,x - oldX=${x - mOldX},y - oldY=${y - mOldY}")
|
// else if (isScale) {
|
||||||
val transformX = x - mOldX
|
// LogUtil.e("mRectWidth=$mRectWidth,mRectHeight=$mRectHeight,x - oldX=${x - mOldX},y - oldY=${y - mOldY}")
|
||||||
val transformY = y - mOldY
|
// val transformX = x - mOldX
|
||||||
val newRectWidth = mRectWidth + transformX
|
// val transformY = y - mOldY
|
||||||
val newRectHeight = mRectHeight + transformY
|
// val newRectWidth = mRectWidth + transformX
|
||||||
//限制缩放不能太小
|
// val newRectHeight = mRectHeight + transformY
|
||||||
if (mLimitSide == 0f) {
|
// //限制缩放不能太小
|
||||||
if (newRectWidth < mLocationBitmap!!.height || newRectHeight < mLocationBitmap!!.height) {
|
// if (mLimitSide == 0f) {
|
||||||
return true
|
// if (newRectWidth < mLocationBitmap!!.height || newRectHeight < mLocationBitmap!!.height) {
|
||||||
}
|
// isHasLimitSide = true
|
||||||
} else if (newRectWidth < mLimitSide || newRectHeight < mLimitSide) {
|
// return true
|
||||||
return true
|
// }
|
||||||
}
|
// } else if (newRectWidth < mLimitSide || newRectHeight < mLimitSide) {
|
||||||
mRotateScaleClickListener?.rectScalingClick()
|
// isHasLimitSide = true
|
||||||
mRectWidth = newRectWidth
|
// mRotateScaleClickListener?.rectMinSizeClick()
|
||||||
mRectHeight = newRectHeight
|
// return true
|
||||||
mOldX = x
|
// }
|
||||||
mOldY = y
|
// mRotateScaleClickListener?.rectScalingClick()
|
||||||
invalidate()
|
// mRectWidth = newRectWidth
|
||||||
|
// mRectHeight = newRectHeight
|
||||||
|
// mOldX = x
|
||||||
|
// mOldY = y
|
||||||
|
// invalidate()
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
else if (isCornerDrag) {
|
||||||
|
moveCorner(x, y)
|
||||||
return true
|
return true
|
||||||
} else if (isDrag) {
|
} else if (isDrag) {
|
||||||
val transformX = x - mOldX
|
val transformX = x - mOldX
|
||||||
@@ -521,25 +542,42 @@ class FencesRectView2 : View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MotionEvent.ACTION_UP -> {
|
MotionEvent.ACTION_UP -> {
|
||||||
if (isRotate) {
|
handleActionUpOrCancel()
|
||||||
mRotateScaleClickListener?.rectRotateClick()
|
}
|
||||||
isRotate = false
|
|
||||||
}
|
MotionEvent.ACTION_CANCEL -> {
|
||||||
if (isScale) {
|
handleActionUpOrCancel()
|
||||||
mRotateScaleClickListener?.rectScaleEndClick()
|
|
||||||
isScale = false
|
|
||||||
}
|
|
||||||
if (isDrag) {
|
|
||||||
mRotateScaleClickListener?.rectEndDragClick()
|
|
||||||
isDrag = false
|
|
||||||
mStrokePaint.strokeWidth = QMUIDisplayHelper.dpToPx(1).toFloat()
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.onTouchEvent(event)
|
return super.onTouchEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ACTION_UP 和 ACTION_CANCEL 共用的收尾:重置所有手势状态
|
||||||
|
* ACTION_CANCEL 在父 View(如百度地图)拦截触摸时触发,必须正确清理
|
||||||
|
*/
|
||||||
|
private fun handleActionUpOrCancel() {
|
||||||
|
mHitMinThisGesture = false
|
||||||
|
if (isRotate) {
|
||||||
|
mRotateScaleClickListener?.rectRotateClick()
|
||||||
|
isRotate = false
|
||||||
|
}
|
||||||
|
if (isScale) {
|
||||||
|
mRotateScaleClickListener?.rectScaleEndClick()
|
||||||
|
isScale = false
|
||||||
|
}
|
||||||
|
if (isCornerDrag) {
|
||||||
|
mRotateScaleClickListener?.rectScaleEndClick()
|
||||||
|
isCornerDrag = false
|
||||||
|
}
|
||||||
|
if (isDrag) {
|
||||||
|
mRotateScaleClickListener?.rectEndDragClick()
|
||||||
|
isDrag = false
|
||||||
|
mStrokePaint.strokeWidth = QMUIDisplayHelper.dpToPx(1).toFloat()
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param x 是坐标轴移动以(mCentreX,mCentreY)原点的坐标
|
* @param x 是坐标轴移动以(mCentreX,mCentreY)原点的坐标
|
||||||
* @param y
|
* @param y
|
||||||
@@ -563,14 +601,19 @@ class FencesRectView2 : View {
|
|||||||
return floatArrayOf((b).toFloat(), (a).toFloat())
|
return floatArrayOf((b).toFloat(), (a).toFloat())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private fun isClick(
|
||||||
* 是否点击按下了旋转,按照移动了坐标轴原点(mCentreX,mCentreY)计算初始坐标
|
clickX: Float,
|
||||||
*/
|
clickY: Float,
|
||||||
private fun isClickRotate(clickX: Float, clickY: Float, rotate: Double): Boolean {
|
xX1: Float,
|
||||||
var x1 = -(mRectWidth / 2 - mRotateBitmap!!.width / 2)
|
xX2: Float,
|
||||||
var x2 = (mRectWidth / 2 - mRotateBitmap!!.width / 2)
|
yY1: Float,
|
||||||
var y1 = -(mRectHeight / 2 + mRotateBitmap!!.height + mRotateBitmap!!.width)
|
yY2: Float,
|
||||||
var y2 = -(mRectHeight / 2 - mRotateBitmap!!.height)
|
rotate: Double
|
||||||
|
): Boolean {
|
||||||
|
var x1 = xX1
|
||||||
|
var x2 = xX2
|
||||||
|
var y1 = yY1
|
||||||
|
var y2 = yY2
|
||||||
val minX = getRotateXY(x1, y1, rotate)
|
val minX = getRotateXY(x1, y1, rotate)
|
||||||
val maxX = getRotateXY(x2, y2, rotate)
|
val maxX = getRotateXY(x2, y2, rotate)
|
||||||
x1 = minX[0]
|
x1 = minX[0]
|
||||||
@@ -586,63 +629,161 @@ class FencesRectView2 : View {
|
|||||||
y2 = minX[1]
|
y2 = minX[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
//处理旋转到某个角度时,旋转图片按钮会超出坐标范围内,不在可点击坐标范围内,把可点击的坐标范围扩大
|
//旋转到某些角度时按钮投影会变小,加一个小触摸容差保证可点
|
||||||
if (abs(x2 - x1) < mRotateBitmap!!.height) {
|
val padding = QMUIDisplayHelper.dpToPx(8).toFloat()
|
||||||
if (x2 > 0) {
|
x1 -= padding
|
||||||
x2 += mRotateBitmap!!.height
|
x2 += padding
|
||||||
} else {
|
y1 -= padding
|
||||||
x1 -= mRotateBitmap!!.height
|
y2 += padding
|
||||||
}
|
|
||||||
}
|
|
||||||
if (abs(y2 - y1) < mRotateBitmap!!.height) {
|
|
||||||
if (y2 > 0) {
|
|
||||||
y2 += mRotateBitmap!!.height
|
|
||||||
} else {
|
|
||||||
y1 -= mRotateBitmap!!.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val transformX = clickX - mCentreX
|
val transformX = clickX - mCentreX
|
||||||
val transformY = clickY - mCentreY
|
val transformY = clickY - mCentreY
|
||||||
|
|
||||||
if (transformX in x1..x2 && transformY in y1..y2) {
|
return transformX in x1..x2 && transformY in y1..y2
|
||||||
return true
|
}
|
||||||
}
|
|
||||||
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)计算初始坐标
|
* 是否点击按下了放大缩小,按照移动了坐标轴原点(mCentreX,mCentreY)计算初始坐标
|
||||||
*/
|
*/
|
||||||
private fun isClickScale(clickX: Float, clickY: Float, rotate: Double): Boolean {
|
private fun isClickScale(clickX: Float, clickY: Float, rotate: Double): Boolean {
|
||||||
var x1 = (mRectWidth / 2 - mZoomBitmap!!.width)
|
val x1 = (mRectWidth / 2 - mZoomBitmap1!!.width / 2)
|
||||||
var x2 = (mRectWidth / 2 + mZoomBitmap!!.width)
|
val x2 = (mRectWidth / 2 + mZoomBitmap1!!.width / 2)
|
||||||
var y1 = (mRectHeight / 2 - mRotateBitmap!!.height)
|
val y1 = (mRectHeight / 2 - mZoomBitmap1!!.height)
|
||||||
var y2 = (mRectHeight / 2 + mRotateBitmap!!.height)
|
val y2 = (mRectHeight / 2 + mZoomBitmap1!!.height)
|
||||||
val minX = getRotateXY(x1, y1, rotate)
|
return isClick(clickX, clickY, x1, x2, y1, y2, 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]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否按下了矩形的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 transformX = clickX - mCentreX
|
||||||
val transformY = clickY - mCentreY
|
val transformY = clickY - mCentreY
|
||||||
|
val localX = transformX * cosAngle + transformY * sinAngle
|
||||||
if (transformX in x1..x2 && transformY in y1..y2) {
|
val localY = -transformX * sinAngle + transformY * cosAngle
|
||||||
return true
|
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
|
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() {
|
override fun onDetachedFromWindow() {
|
||||||
super.onDetachedFromWindow()
|
super.onDetachedFromWindow()
|
||||||
LogUtil.e("onDetachedFromWindow,${javaClass.canonicalName}视图销毁")
|
LogUtil.e("onDetachedFromWindow,${javaClass.canonicalName}视图销毁")
|
||||||
if (null != mDotBitmap) {
|
listOf(mLocationBitmap, mRotateBitmap, mZoomBitmap1, mZoomBitmap2).forEach { bm ->
|
||||||
mDotBitmap?.recycle()
|
if (bm != null && !bm.isRecycled) bm.recycle()
|
||||||
mDotBitmap = null
|
|
||||||
}
|
|
||||||
if (null != mLocationBitmap) {
|
|
||||||
mLocationBitmap?.recycle()
|
|
||||||
mLocationBitmap = null
|
|
||||||
}
|
|
||||||
if (null != mRotateBitmap) {
|
|
||||||
mRotateBitmap?.recycle()
|
|
||||||
mRotateBitmap = null
|
|
||||||
}
|
|
||||||
if (null != mZoomBitmap) {
|
|
||||||
mZoomBitmap?.recycle()
|
|
||||||
mZoomBitmap = null
|
|
||||||
}
|
}
|
||||||
|
mLocationBitmap = null
|
||||||
|
mRotateBitmap = null
|
||||||
|
mZoomBitmap1 = null
|
||||||
|
mZoomBitmap2 = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
app:fences_circle_dashed_color="@color/select_color"
|
app:fences_circle_dashed_color="@color/select_color"
|
||||||
app:fences_circle_fill_bg_color="@color/select_color4" />
|
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:id="@+id/fences_zone_rect_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|||||||
Reference in New Issue
Block a user