Browse Source

refactor(更新) :
- 优化 CustomMarkLayer 中票号图标及序号徽章的绘制和点击逻辑
- 重构序号徽章的绘制方式,其尺寸和位置现在相对于图标大小动态计算
- 增加徽章内文本的动态缩放功能,以确保文本完整显示
- 更新了徽章的点击事件判定范围,以匹配新的绘制逻辑
- 调整了默认图标大小(`mBitmapSize`)、水平内边距和多个图标的水平间距
- 将 WorkshopFragment 中加载票据图标的尺寸从 80x80 调整为 60x60
- 移除了 CustomMarkLayer 中未使用的 `rotatePoint` 方法

周文健 1 tháng trước cách đây
mục cha
commit
6f319235e8

+ 8 - 8
app/src/main/java/com/grkj/iscs_mars/view/fragment/WorkshopFragment.kt

@@ -103,14 +103,14 @@ class WorkshopFragment(val changePage: (PageChangeBO) -> Unit) :
                                             Constants.getTicketKey(5)
                                         ),
                                         R.mipmap.ticket_type_placeholder,
-                                        80, 80
+                                        60, 60
                                     ) { itBitmap ->
                                         itTicket.bitmap =
                                             itBitmap ?: BitmapUtil.getResizedBitmapFromMipmap(
                                                 requireContext(),
                                                 R.mipmap.ticket_type_placeholder,
-                                                80,
-                                                80
+                                                60,
+                                                60
                                             )
                                     }
                                 } else {
@@ -118,8 +118,8 @@ class WorkshopFragment(val changePage: (PageChangeBO) -> Unit) :
                                         itTicket.bitmap = BitmapUtil.getResizedBitmapFromMipmap(
                                             requireContext(),
                                             R.mipmap.ticket_type_placeholder,
-                                            80,
-                                            80
+                                            60,
+                                            60
                                         )
                                     } else {
                                         BitmapUtil.loadBitmapFromUrl(
@@ -129,14 +129,14 @@ class WorkshopFragment(val changePage: (PageChangeBO) -> Unit) :
                                                 Constants.getTicketKey(itTicket.ticketType.toInt())
                                             ),
                                             R.mipmap.ticket_type_placeholder,
-                                            80, 80
+                                            60, 60
                                         ) { itBitmap ->
                                             itTicket.bitmap =
                                                 itBitmap ?: BitmapUtil.getResizedBitmapFromMipmap(
                                                     requireContext(),
                                                     R.mipmap.ticket_type_placeholder,
-                                                    80,
-                                                    80
+                                                    60,
+                                                    60
                                                 )
                                         }
                                     }

+ 66 - 70
app/src/main/java/com/grkj/iscs_mars/view/widget/CustomMarkLayer.kt

@@ -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
     }