|
|
@@ -1,5 +1,6 @@
|
|
|
package com.grkj.iscs_mars.view.widget
|
|
|
|
|
|
+import android.graphics.Bitmap
|
|
|
import android.graphics.Canvas
|
|
|
import android.graphics.Color
|
|
|
import android.graphics.Matrix
|
|
|
@@ -23,14 +24,14 @@ class CustomMarkLayer @JvmOverloads constructor(
|
|
|
) : MapBaseLayer(mapView) {
|
|
|
private var listener: MarkIsClickListener? = null
|
|
|
private var textSize = 18f
|
|
|
- private var horizontalPadding = 10f
|
|
|
+ private var horizontalPadding = 5f
|
|
|
private var isClickMark: Boolean = false
|
|
|
private var num: Int
|
|
|
private lateinit var paint: Paint
|
|
|
private var btnIndex: Int
|
|
|
private var currentZoom = 0f
|
|
|
private var currentDegree = 0f
|
|
|
- private var mBitmapSize = 80 // 默认图标大小
|
|
|
+ private var mBitmapSize = 48 // 默认图标大小
|
|
|
private var isClickIcon: Boolean = false
|
|
|
private var isFirst: Boolean = true
|
|
|
|
|
|
@@ -77,9 +78,9 @@ class CustomMarkLayer @JvmOverloads constructor(
|
|
|
val fm = paint.fontMetrics
|
|
|
val height = fm.descent - fm.ascent
|
|
|
|
|
|
- val labelLeft = goal[0] - width / 2f - horizontalPadding * 2f
|
|
|
- val labelTop = goal[1] - height / 2f - horizontalPadding / 2f
|
|
|
- val labelRight = goal[0] + width / 2f + horizontalPadding * 2f
|
|
|
+ val labelLeft = goal[0] - width / 2f - horizontalPadding * 2f
|
|
|
+ val labelTop = goal[1] - height / 2f - horizontalPadding / 2f
|
|
|
+ val labelRight = goal[0] + width / 2f + horizontalPadding * 2f
|
|
|
val labelBottom = goal[1] + height / 2f + horizontalPadding / 2f
|
|
|
|
|
|
if (sx > labelLeft && sx < labelRight && sy > labelTop && sy < labelBottom) {
|
|
|
@@ -95,23 +96,24 @@ class CustomMarkLayer @JvmOverloads constructor(
|
|
|
if (list.isEmpty()) continue
|
|
|
|
|
|
// icon 顶点的屏幕 Y(与 onDraw 保持)
|
|
|
- val iconTopY = goal[1] - height / 2f - horizontalPadding / 2f - 10f - mBitmapSize / 2f
|
|
|
+ val iconTopY = goal[1] - height / 2f - horizontalPadding / 2f - 10f - mBitmapSize
|
|
|
|
|
|
for (j in list.indices) {
|
|
|
// 与 onDraw 的水平排布保持一致
|
|
|
val ticketX = when {
|
|
|
list.size % 2 == 0 -> { // 偶数
|
|
|
if (j + 1 <= list.size / 2) {
|
|
|
- goal[0] - mBitmapSize / 2f * (list.size / 2 - j)
|
|
|
+ goal[0] - mBitmapSize * (list.size / 2 - j)
|
|
|
} else {
|
|
|
- goal[0] + mBitmapSize / 2f * (j - list.size / 2)
|
|
|
+ goal[0] + mBitmapSize * (j - list.size / 2)
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
else -> { // 奇数
|
|
|
if (j + 1 <= list.size / 2) {
|
|
|
- goal[0] - mBitmapSize / 2f * (list.size / 2 - j + 0.5f)
|
|
|
+ goal[0] - mBitmapSize * (list.size / 2 - j + 0.5f)
|
|
|
} else {
|
|
|
- goal[0] + mBitmapSize / 2f * (j - list.size / 2 - 0.5f)
|
|
|
+ goal[0] + mBitmapSize * (j - list.size / 2 - 0.5f)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -138,17 +140,17 @@ class CustomMarkLayer @JvmOverloads constructor(
|
|
|
break
|
|
|
}
|
|
|
|
|
|
- // 命中 2.2:点击到序号条(与 onDraw 的 number 矩形一致)
|
|
|
- val numberText = if (point.ticketList.size > 3 && j == list.size - 1) "${j + 1}+" else (j + 1).toString()
|
|
|
- val numberWidth = paint.measureText(numberText)
|
|
|
- val numberHeight = fm.descent - fm.ascent
|
|
|
+ val badgeSize = mBitmapSize * 0.9f
|
|
|
+ val gap = horizontalPadding
|
|
|
+
|
|
|
+ val iconCenterX = iconLeft + mBitmapSize / 2f
|
|
|
|
|
|
- val numberRectLeft = goal[0] - numberWidth / 2f - horizontalPadding * 1.5f
|
|
|
- val numberRectTop = iconTop - horizontalPadding * 2f - numberHeight - horizontalPadding / 2f
|
|
|
- val numberRectRight = goal[0] + numberWidth / 2f + horizontalPadding * 1.5f
|
|
|
- val numberRectBottom = numberRectTop + numberHeight + horizontalPadding * 2f
|
|
|
+ val badgeBottom = iconTop - gap
|
|
|
+ val badgeTop = badgeBottom - badgeSize
|
|
|
+ val badgeLeft = iconCenterX - badgeSize / 2f
|
|
|
+ val badgeRight = iconCenterX + badgeSize / 2f
|
|
|
|
|
|
- val hitBadge = sx > numberRectLeft && sx < numberRectRight && sy > numberRectTop && sy < numberRectBottom
|
|
|
+ val hitBadge = sx > badgeLeft && sx < badgeRight && sy > badgeTop && sy < badgeBottom
|
|
|
if (hitBadge) {
|
|
|
num = i
|
|
|
btnIndex = j
|
|
|
@@ -220,65 +222,72 @@ class CustomMarkLayer @JvmOverloads constructor(
|
|
|
val list = point.ticketList.take(3)
|
|
|
if (list.isNotEmpty()) {
|
|
|
for (j in list.indices) {
|
|
|
- val ticketX = if (list.size % 2 == 0) { // 偶数个
|
|
|
+ // —— 图标水平排布(保留你的算法,不改)——
|
|
|
+ val ticketX = if (list.size % 2 == 0) { // 偶数
|
|
|
if (j + 1 <= list.size / 2) {
|
|
|
- goal[0] - mBitmapSize / 2 * (list.size / 2 - j)
|
|
|
+ goal[0] - mBitmapSize * (list.size / 2 - j)
|
|
|
} else {
|
|
|
- goal[0] + mBitmapSize / 2 * (j - list.size / 2)
|
|
|
+ goal[0] + mBitmapSize * (j - list.size / 2)
|
|
|
}
|
|
|
- } else { // 奇数个
|
|
|
+ } else { // 奇数
|
|
|
if (j + 1 <= list.size / 2) {
|
|
|
- goal[0] - mBitmapSize / 2 * (list.size / 2 - j + 0.5f)
|
|
|
+ goal[0] - mBitmapSize * (list.size / 2 - j + 0.5f)
|
|
|
} else {
|
|
|
- goal[0] + mBitmapSize / 2 * (j - list.size / 2 - 0.5f)
|
|
|
+ goal[0] + mBitmapSize * (j - list.size / 2 - 0.5f)
|
|
|
}
|
|
|
}
|
|
|
val ticketY =
|
|
|
- goal[1] - height / 2 - horizontalPadding / 2 - 10 - mBitmapSize / 2
|
|
|
+ goal[1] - height / 2f - horizontalPadding / 2f - 10f - mBitmapSize
|
|
|
|
|
|
- // 绘制图标
|
|
|
+ // —— 绘制图标(严格按 mBitmapSize 大小)——
|
|
|
val srcBm = if (point.ticketList.size > 3 && j == 2)
|
|
|
point.ticketList[j + 1].bitmap!!
|
|
|
else
|
|
|
list[j].bitmap!!
|
|
|
|
|
|
- val iconBm = iconCache.get(srcBm, mBitmapSize) // ← 关键:先缩放到 60px
|
|
|
+ val iconBm = iconCache.get(srcBm, mBitmapSize) // 返回正方形 mBitmapSize×mBitmapSize
|
|
|
+ iconBm.density = Bitmap.DENSITY_NONE
|
|
|
canvas.drawBitmap(iconBm, ticketX, ticketY, paint)
|
|
|
|
|
|
- // 计算序号背景的位置和大小
|
|
|
- val numberText =
|
|
|
- if (point.ticketList.size > 3 && j == list.size - 1) "${j + 1}+" else (j + 1).toString()
|
|
|
- val numberWidth = paint.measureText(numberText)
|
|
|
- val numberHeight = paint.fontMetrics.descent - paint.fontMetrics.ascent
|
|
|
- val numberRectLeft =
|
|
|
- goal[0] - numberWidth / 2 - horizontalPadding * 1.5f
|
|
|
- val numberRectTop =
|
|
|
- ticketY - horizontalPadding * 2 - numberHeight - horizontalPadding / 2
|
|
|
- val numberRectRight =
|
|
|
- goal[0] + numberWidth / 2 + horizontalPadding * 1.5f
|
|
|
- val numberRectBottom =
|
|
|
- numberRectTop + numberHeight + horizontalPadding * 2
|
|
|
-
|
|
|
- // 绘制序号背景
|
|
|
+ // ===== 序号徽章:正上方、大小=图标的90%、与图标垂直间隔=horizontalPadding =====
|
|
|
+ val iconLeft = ticketX
|
|
|
+ val iconTop = ticketY
|
|
|
+ val iconCenterX = iconLeft + mBitmapSize / 2f
|
|
|
+
|
|
|
+ val badgeSize = mBitmapSize * 0.9f // 宽高都为图标90%
|
|
|
+ val gap = horizontalPadding // 与图标的间隔 = 一个 padding
|
|
|
+ val badgeBottom = iconTop - gap
|
|
|
+ val badgeTop = badgeBottom - badgeSize
|
|
|
+ val badgeLeft = iconCenterX - badgeSize / 2f
|
|
|
+ val badgeRight = iconCenterX + badgeSize / 2f
|
|
|
+
|
|
|
+ // 背景
|
|
|
+ paint.style = Paint.Style.FILL
|
|
|
paint.color = Color.parseColor("#00AAFF")
|
|
|
canvas.drawRoundRect(
|
|
|
- numberRectLeft,
|
|
|
- numberRectTop,
|
|
|
- numberRectRight,
|
|
|
- numberRectBottom,
|
|
|
- 5f,
|
|
|
- 5f,
|
|
|
- paint
|
|
|
+ badgeLeft, badgeTop, badgeRight, badgeBottom,
|
|
|
+ badgeSize * 0.15f, badgeSize * 0.15f, paint
|
|
|
)
|
|
|
|
|
|
- // 绘制序号
|
|
|
+ // 文本(最后一个显示 "x+" 的规则保留)
|
|
|
+ val numberText =
|
|
|
+ if (point.ticketList.size > 3 && j == list.size - 1) "${j + 1}+" else (j + 1).toString()
|
|
|
+
|
|
|
+ // 让文字尽量塞进徽章(不会改变图标/徽章尺寸,只调字号)
|
|
|
+ val keepTextSize = paint.textSize
|
|
|
+ val targetMax = badgeSize * 0.7f
|
|
|
+ var w = paint.measureText(numberText)
|
|
|
+ if (w > targetMax) {
|
|
|
+ val scale = targetMax / w
|
|
|
+ paint.textSize = keepTextSize * scale
|
|
|
+ w = paint.measureText(numberText)
|
|
|
+ }
|
|
|
paint.color = Color.WHITE
|
|
|
- canvas.drawText(
|
|
|
- numberText,
|
|
|
- goal[0] - numberWidth / 2,
|
|
|
- numberRectBottom - horizontalPadding - paint.fontMetrics.descent,
|
|
|
- paint
|
|
|
- )
|
|
|
+ val fmNum = paint.fontMetrics
|
|
|
+ val textX = iconCenterX - w / 2f
|
|
|
+ val textY = badgeTop + (badgeSize - (fmNum.descent - fmNum.ascent)) / 2f - fmNum.ascent
|
|
|
+ canvas.drawText(numberText, textX, textY, paint)
|
|
|
+ paint.textSize = keepTextSize
|
|
|
}
|
|
|
}
|
|
|
// 定位点,仅调试用,不要显示
|
|
|
@@ -295,19 +304,6 @@ class CustomMarkLayer @JvmOverloads constructor(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private fun rotatePoint(
|
|
|
- oriX: Float, oriY: Float, desX: Float, desY: Float, rotateDegrees: Float
|
|
|
- ): Pair<Float, Float> {
|
|
|
- // 将度数转换为弧度
|
|
|
- val theta = Math.toRadians(rotateDegrees.toDouble())
|
|
|
-
|
|
|
- // 计算旋转后的坐标
|
|
|
- val newX = (oriX - desX) * cos(theta) - (oriY - desY) * sin(theta) + desX
|
|
|
- val newY = (oriX - desX) * sin(theta) + ((oriY - desY) * cos(theta)) + desY
|
|
|
-
|
|
|
- return Pair(newX.toFloat(), newY.toFloat())
|
|
|
- }
|
|
|
-
|
|
|
fun setMarkIsClickListener(listener: MarkIsClickListener?) {
|
|
|
this.listener = listener
|
|
|
}
|