Эх сурвалжийг харах

refactor(更新) :
- 新增离线激活功能
- 优化地图图层,长按和点击后列表信息居中显示
- 优化界面,缩小边距和字体大小
- 登录界面显示序列号,点击标题导出激活信息
- 修复地图图层告警时一直刷新的问题

周文健 2 сар өмнө
parent
commit
9aeda56ffc

+ 9 - 1
app/src/main/java/com/grkj/iscs_mars/model/ArcSoftLicenseConfig.kt

@@ -15,5 +15,13 @@ data class ArcSoftLicenseConfig(
     /**
     /**
      * 激活码
      * 激活码
      */
      */
-    val activeKey: String
+    val activeKey: String,
+    /**
+     * 是否在线激活
+     */
+    val activeOnline: Boolean,
+    /**
+     * 离线激活文件路径
+     */
+    val activeOfflineFilePath: String
 )
 )

+ 24 - 8
app/src/main/java/com/grkj/iscs_mars/util/ArcSoftUtil.kt

@@ -33,6 +33,7 @@ import java.io.File
 
 
 object ArcSoftUtil {
 object ArcSoftUtil {
     private val configFileName = "ArcSoftConfig.json"
     private val configFileName = "ArcSoftConfig.json"
+    private val offlineActiveFileName = "OfflineActive.dat"
     private var cameraHelper: CameraHelper? = null
     private var cameraHelper: CameraHelper? = null
     private var previewSize: Camera.Size? = null
     private var previewSize: Camera.Size? = null
     private val rgbCameraId = Camera.CameraInfo.CAMERA_FACING_BACK
     private val rgbCameraId = Camera.CameraInfo.CAMERA_FACING_BACK
@@ -62,6 +63,8 @@ object ArcSoftUtil {
         val configJson = try {
         val configJson = try {
             val arcSoftLicenseFile =
             val arcSoftLicenseFile =
                 File("${FileUtil.getRootFolder(context)?.absolutePath}${FileUtil.CONFIG_DIR}${File.separator}${configFileName}")
                 File("${FileUtil.getRootFolder(context)?.absolutePath}${FileUtil.CONFIG_DIR}${File.separator}${configFileName}")
+            val arcSoftActiveOfflineFile =
+                File("${FileUtil.getRootFolder(context)?.absolutePath}${FileUtil.CONFIG_DIR}${File.separator}${offlineActiveFileName}")
             File("${FileUtil.getRootFolder(context)?.absolutePath}${FileUtil.CONFIG_DIR}").apply {
             File("${FileUtil.getRootFolder(context)?.absolutePath}${FileUtil.CONFIG_DIR}").apply {
                 if (!exists()) {
                 if (!exists()) {
                     mkdirs()
                     mkdirs()
@@ -76,7 +79,9 @@ object ArcSoftUtil {
                 val defaultJson = ArcSoftLicenseConfig(
                 val defaultJson = ArcSoftLicenseConfig(
                     Constants.APP_ID,
                     Constants.APP_ID,
                     Constants.SDK_KEY,
                     Constants.SDK_KEY,
-                    Constants.ACTIVE_KEY
+                    Constants.ACTIVE_KEY,
+                    true,
+                    arcSoftActiveOfflineFile.absolutePath
                 ).toJson()
                 ).toJson()
                 arcSoftLicenseFile.writeText(defaultJson)
                 arcSoftLicenseFile.writeText(defaultJson)
                 defaultJson
                 defaultJson
@@ -84,6 +89,8 @@ object ArcSoftUtil {
         } catch (e: Exception) {
         } catch (e: Exception) {
             val arcSoftLicenseFile =
             val arcSoftLicenseFile =
                 File("${FileUtil.getRootFolder(context)?.absolutePath}${FileUtil.CONFIG_DIR}${File.separator}${configFileName}")
                 File("${FileUtil.getRootFolder(context)?.absolutePath}${FileUtil.CONFIG_DIR}${File.separator}${configFileName}")
+            val arcSoftActiveOfflineFile =
+                File("${FileUtil.getRootFolder(context)?.absolutePath}${FileUtil.CONFIG_DIR}${File.separator}${offlineActiveFileName}")
             LogUtil.i("获取文件报错,写一份")
             LogUtil.i("获取文件报错,写一份")
             File("${FileUtil.getRootFolder(context)?.absolutePath}${FileUtil.CONFIG_DIR}").apply {
             File("${FileUtil.getRootFolder(context)?.absolutePath}${FileUtil.CONFIG_DIR}").apply {
                 if (!exists()) {
                 if (!exists()) {
@@ -94,7 +101,9 @@ object ArcSoftUtil {
             val defaultJson = ArcSoftLicenseConfig(
             val defaultJson = ArcSoftLicenseConfig(
                 Constants.APP_ID,
                 Constants.APP_ID,
                 Constants.SDK_KEY,
                 Constants.SDK_KEY,
-                Constants.ACTIVE_KEY
+                Constants.ACTIVE_KEY,
+                true,
+                arcSoftActiveOfflineFile.absolutePath
             ).toJson()
             ).toJson()
             arcSoftLicenseFile.writeText(defaultJson)
             arcSoftLicenseFile.writeText(defaultJson)
             defaultJson
             defaultJson
@@ -102,12 +111,19 @@ object ArcSoftUtil {
         LogUtil.i("配置文件内容:${configJson}")
         LogUtil.i("配置文件内容:${configJson}")
         val arcSoftLicenseConfig: ArcSoftLicenseConfig =
         val arcSoftLicenseConfig: ArcSoftLicenseConfig =
             gson.fromJson(configJson, ArcSoftLicenseConfig::class.java)
             gson.fromJson(configJson, ArcSoftLicenseConfig::class.java)
-        val activeCode = FaceEngine.activeOnline(
-            context,
-            arcSoftLicenseConfig.activeKey,
-            arcSoftLicenseConfig.appId,
-            arcSoftLicenseConfig.sdkKey
-        )
+        val activeCode = if (arcSoftLicenseConfig.activeOnline) {
+            FaceEngine.activeOnline(
+                context,
+                arcSoftLicenseConfig.activeKey,
+                arcSoftLicenseConfig.appId,
+                arcSoftLicenseConfig.sdkKey
+            )
+        } else {
+            FaceEngine.activeOffline(
+                context,
+                arcSoftLicenseConfig.activeOfflineFilePath
+            )
+        }
         when (activeCode) {
         when (activeCode) {
             ErrorInfo.MOK -> {
             ErrorInfo.MOK -> {
                 isActivated = true
                 isActivated = true

+ 18 - 3
app/src/main/java/com/grkj/iscs_mars/view/activity/LoginActivity.kt

@@ -5,15 +5,20 @@ import android.graphics.Bitmap
 import android.view.InputDevice
 import android.view.InputDevice
 import android.view.KeyEvent
 import android.view.KeyEvent
 import android.widget.ImageView
 import android.widget.ImageView
+import com.arcsoft.face.ActiveFileInfo
+import com.arcsoft.face.FaceEngine
+import com.arcsoft.face.model.ActiveDeviceInfo
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.MyApplication.Companion.cronJobManager
 import com.grkj.iscs_mars.MyApplication.Companion.cronJobManager
 import com.grkj.iscs_mars.R
 import com.grkj.iscs_mars.R
 import com.grkj.iscs_mars.databinding.ActivityLoginBinding
 import com.grkj.iscs_mars.databinding.ActivityLoginBinding
+import com.grkj.iscs_mars.extentions.serialNo
 import com.grkj.iscs_mars.extentions.toByteArrays
 import com.grkj.iscs_mars.extentions.toByteArrays
 import com.grkj.iscs_mars.extentions.toHexStrings
 import com.grkj.iscs_mars.extentions.toHexStrings
 import com.grkj.iscs_mars.modbus.ModBusController
 import com.grkj.iscs_mars.modbus.ModBusController
 import com.grkj.iscs_mars.model.vo.user.UserInfoRespVO
 import com.grkj.iscs_mars.model.vo.user.UserInfoRespVO
 import com.grkj.iscs_mars.util.AppUtils
 import com.grkj.iscs_mars.util.AppUtils
+import com.grkj.iscs_mars.util.ArcSoftUtil
 import com.grkj.iscs_mars.util.FingerprintUtil
 import com.grkj.iscs_mars.util.FingerprintUtil
 import com.grkj.iscs_mars.util.KeyboardUtils
 import com.grkj.iscs_mars.util.KeyboardUtils
 import com.grkj.iscs_mars.util.log.LogUtil
 import com.grkj.iscs_mars.util.log.LogUtil
@@ -23,6 +28,10 @@ import com.grkj.iscs_mars.view.dialog.UrlConfigDialog
 import com.grkj.iscs_mars.view.iview.ILoginView
 import com.grkj.iscs_mars.view.iview.ILoginView
 import com.grkj.iscs_mars.view.presenter.LoginPresenter
 import com.grkj.iscs_mars.view.presenter.LoginPresenter
 import com.sik.sikcore.SIKCore
 import com.sik.sikcore.SIKCore
+import com.sik.sikcore.extension.setDebouncedClickListener
+import com.sik.sikcore.file.FileStorageUtils
+import com.sik.sikcore.file.FileUtils
+import com.sik.sikcore.shell.ShellUtils
 import com.tencent.mmkv.MMKV
 import com.tencent.mmkv.MMKV
 import com.zhy.adapter.recyclerview.CommonAdapter
 import com.zhy.adapter.recyclerview.CommonAdapter
 import com.zhy.adapter.recyclerview.base.ViewHolder
 import com.zhy.adapter.recyclerview.base.ViewHolder
@@ -38,9 +47,15 @@ class LoginActivity : BaseMvpActivity<ILoginView, LoginPresenter, ActivityLoginB
     override fun initView() {
     override fun initView() {
         MMKV.initialize(SIKCore.getApplication())
         MMKV.initialize(SIKCore.getApplication())
         cronJobManager.bindService()
         cronJobManager.bindService()
-        mBinding?.tvVersion?.text = "v${AppUtils.getPkgVerName(this)}"
-
-        mBinding?.tvVersion?.setOnClickListener {
+        mBinding?.tvVersion?.post {
+            mBinding?.tvVersion?.text = "v${AppUtils.getPkgVerName(this)}-${serialNo()}"
+        }
+        mBinding?.mainTitle?.setDebouncedClickListener {
+            val activeDeviceInfo = ActiveDeviceInfo()
+            FaceEngine.getActiveDeviceInfo(this, activeDeviceInfo)
+            ShellUtils.execCmd("echo ${activeDeviceInfo.deviceInfo} > /sdcard/iscs/activeDeviceInfo.txt")
+        }
+        mBinding?.tvVersion?.setDebouncedClickListener {
             UrlConfigDialog(this).show()
             UrlConfigDialog(this).show()
         }
         }
 
 

+ 4 - 1
app/src/main/java/com/grkj/iscs_mars/view/activity/SwitchStatusActivity.kt

@@ -22,6 +22,7 @@ import com.grkj.iscs_mars.model.eventmsg.MsgEventConstants.MSG_EVENT_SWITCH_COLL
 import com.grkj.iscs_mars.model.vo.map.MapInfoRespVO.IsMapPoint
 import com.grkj.iscs_mars.model.vo.map.MapInfoRespVO.IsMapPoint
 import com.grkj.iscs_mars.util.CommonUtils
 import com.grkj.iscs_mars.util.CommonUtils
 import com.grkj.iscs_mars.util.ToastUtils
 import com.grkj.iscs_mars.util.ToastUtils
+import com.grkj.iscs_mars.util.log.LogUtil
 import com.grkj.iscs_mars.view.base.BaseMvpActivity
 import com.grkj.iscs_mars.view.base.BaseMvpActivity
 import com.grkj.iscs_mars.view.dialog.SwitchInfoDialog
 import com.grkj.iscs_mars.view.dialog.SwitchInfoDialog
 import com.grkj.iscs_mars.view.iview.ISwitchStatusView
 import com.grkj.iscs_mars.view.iview.ISwitchStatusView
@@ -29,6 +30,7 @@ import com.grkj.iscs_mars.view.presenter.SwitchStatusPresenter
 import com.grkj.iscs_mars.view.widget.CustomSwitchStationLayer
 import com.grkj.iscs_mars.view.widget.CustomSwitchStationLayer
 import com.onlylemi.mapview.library.MapViewListener
 import com.onlylemi.mapview.library.MapViewListener
 import com.sik.sikcore.extension.setDebouncedClickListener
 import com.sik.sikcore.extension.setDebouncedClickListener
+import com.sik.sikcore.extension.toJson
 import com.sik.sikcore.thread.ThreadUtils
 import com.sik.sikcore.thread.ThreadUtils
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.launch
@@ -48,7 +50,7 @@ class SwitchStatusActivity :
 
 
     override fun initView() {
     override fun initView() {
         switchInfoDialog = SwitchInfoDialog(this)
         switchInfoDialog = SwitchInfoDialog(this)
-        switchInfoDialog.popupGravity = Gravity.TOP
+        switchInfoDialog.popupGravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
         mBinding?.cbBack?.setDebouncedClickListener {
         mBinding?.cbBack?.setDebouncedClickListener {
             finish()
             finish()
         }
         }
@@ -86,6 +88,7 @@ class SwitchStatusActivity :
         val switchData = ModBusController.getSwitchData()
         val switchData = ModBusController.getSwitchData()
         itemBinding.switchName.text = item.entityName
         itemBinding.switchName.text = item.entityName
         itemBinding.switchId.text = context.getString(R.string.switch_id, item.pointSerialNumber)
         itemBinding.switchId.text = context.getString(R.string.switch_id, item.pointSerialNumber)
+        LogUtil.i("开关数据:${switchData.toJson()}")
         val switchStatus = switchData
         val switchStatus = switchData
             .find { it.idx == item.pointSerialNumber?.toInt() }?.enabled
             .find { it.idx == item.pointSerialNumber?.toInt() }?.enabled
             ?: (item.switchStatus == "1")
             ?: (item.switchStatus == "1")

+ 1 - 0
app/src/main/java/com/grkj/iscs_mars/view/dialog/SwitchInfoDialog.kt

@@ -22,6 +22,7 @@ class SwitchInfoDialog(context: Context) : BasePopupWindow(context) {
         setBackground(null)
         setBackground(null)
         setFitSize(true)
         setFitSize(true)
         setOverlayMask(false)
         setOverlayMask(false)
+        setAutoMirrorEnable(true)
         binding = DialogSwitchInfoBinding.bind(contentView)
         binding = DialogSwitchInfoBinding.bind(contentView)
     }
     }
 
 

+ 3 - 0
app/src/main/java/com/grkj/iscs_mars/view/widget/CustomMarkLayer.kt

@@ -14,6 +14,9 @@ import com.onlylemi.mapview.library.utils.MapMath
 import kotlin.math.cos
 import kotlin.math.cos
 import kotlin.math.sin
 import kotlin.math.sin
 
 
+/**
+ * 首页地图区域图层
+ */
 class CustomMarkLayer @JvmOverloads constructor(
 class CustomMarkLayer @JvmOverloads constructor(
     mapView: MapView?,
     mapView: MapView?,
     private var pointList: List<CustomPoint> = mutableListOf()
     private var pointList: List<CustomPoint> = mutableListOf()

+ 25 - 8
app/src/main/java/com/grkj/iscs_mars/view/widget/CustomSwitchStationLayer.kt

@@ -59,10 +59,10 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
 
 
             if (hasAnyAlarm(points, switches)) {
             if (hasAnyAlarm(points, switches)) {
                 mapView?.refresh()
                 mapView?.refresh()
-                mapView?.postDelayed(this, FRAME_INTERVAL) // 🔑 用 this 引用自己
             } else {
             } else {
                 mapView?.refresh()
                 mapView?.refresh()
             }
             }
+            mapView?.postDelayed(this, FRAME_INTERVAL) // 🔑 用 this 引用自己
         }
         }
     }
     }
 
 
@@ -79,9 +79,12 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
     // 长按探测
     // 长按探测
     private val longPressTimeoutMs: Long =
     private val longPressTimeoutMs: Long =
         android.view.ViewConfiguration.getLongPressTimeout().toLong()
         android.view.ViewConfiguration.getLongPressTimeout().toLong()
+
     // 建议更宽容一些(x1.5):
     // 建议更宽容一些(x1.5):
     private val touchSlop: Float =
     private val touchSlop: Float =
-        android.view.ViewConfiguration.get(mapView?.context ?: SIKCore.getApplication()).scaledTouchSlop * 1.5f
+        android.view.ViewConfiguration.get(
+            mapView?.context ?: SIKCore.getApplication()
+        ).scaledTouchSlop * 1.5f
     private val touchSlopSq: Float = touchSlop * touchSlop
     private val touchSlopSq: Float = touchSlop * touchSlop
 
 
     private var pendingLongPress = false
     private var pendingLongPress = false
@@ -101,10 +104,15 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
             val centerMapX = p.pos.x + switchSize / 2f
             val centerMapX = p.pos.x + switchSize / 2f
             val centerMapY = p.pos.y + switchSize / 2f
             val centerMapY = p.pos.y + switchSize / 2f
 
 
-            mapView?.animateCenterOnPoint(centerMapX, centerMapY, longPressCenterDurationMs, lastKnownZoom)
             mapView?.postDelayed({
             mapView?.postDelayed({
                 val screen = mapToScreen(centerMapX, centerMapY)
                 val screen = mapToScreen(centerMapX, centerMapY)
-                onLongPressListener?.invoke(p, screen.x, screen.y, centerMapX, centerMapY)
+                onLongPressListener?.invoke(
+                    p,
+                    screen.x,
+                    screen.y - switchSize / 2 - 4,
+                    centerMapX,
+                    centerMapY
+                )
             }, longPressCenterDurationMs)
             }, longPressCenterDurationMs)
         }
         }
     }
     }
@@ -236,7 +244,7 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
                 if (pendingLongPress && !longPressTriggered) {
                 if (pendingLongPress && !longPressTriggered) {
                     val dx = event.x - downScreenX
                     val dx = event.x - downScreenX
                     val dy = event.y - downScreenY
                     val dy = event.y - downScreenY
-                    if (dx*dx + dy*dy > touchSlopSq) {
+                    if (dx * dx + dy * dy > touchSlopSq) {
                         pendingLongPress = false
                         pendingLongPress = false
                         mapView.removeCallbacks(longPressRunnable)
                         mapView.removeCallbacks(longPressRunnable)
                     }
                     }
@@ -266,14 +274,24 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
                 // ① 只缩放:以当前屏幕中心为 pivot,把 scale 动到 targetScale
                 // ① 只缩放:以当前屏幕中心为 pivot,把 scale 动到 targetScale
                 val curCenter = currentMapCenter()
                 val curCenter = currentMapCenter()
                 if (curCenter != null) {
                 if (curCenter != null) {
-                    mapView?.animateCenterOnPoint(curCenter.x, curCenter.y, clickZoomDurationMs, targetScale)
+                    mapView?.animateCenterOnPoint(
+                        curCenter.x,
+                        curCenter.y,
+                        clickZoomDurationMs,
+                        targetScale
+                    )
                 } else {
                 } else {
                     // 万一拿不到中心,就直接在下一步里统一做
                     // 万一拿不到中心,就直接在下一步里统一做
                 }
                 }
 
 
                 // ② 再居中到目标点(保持 targetScale),确保最后居中
                 // ② 再居中到目标点(保持 targetScale),确保最后居中
                 mapView?.postDelayed({
                 mapView?.postDelayed({
-                    mapView?.animateCenterOnPoint(targetMapX, targetMapY, clickCenterDurationMs, targetScale)
+                    mapView?.animateCenterOnPoint(
+                        targetMapX,
+                        targetMapY,
+                        clickCenterDurationMs,
+                        targetScale
+                    )
                 }, clickZoomDurationMs)
                 }, clickZoomDurationMs)
 
 
                 // ③ 动画完成后再 selectPoint(此时位置稳定)
                 // ③ 动画完成后再 selectPoint(此时位置稳定)
@@ -316,7 +334,6 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
     }
     }
 
 
 
 
-
     override fun draw(
     override fun draw(
         canvas: Canvas, currentMatrix: Matrix, currentZoom: Float, currentRotateDegrees: Float
         canvas: Canvas, currentMatrix: Matrix, currentZoom: Float, currentRotateDegrees: Float
     ) {
     ) {

+ 31 - 14
app/src/main/java/com/onlylemi/mapview/library/MapView.java

@@ -177,6 +177,9 @@ public class MapView extends TextureView implements TextureView.SurfaceTextureLi
                 startTouch.set(event.getX(), event.getY());
                 startTouch.set(event.getX(), event.getY());
                 lastMove.set(event.getX(), event.getY());
                 lastMove.set(event.getX(), event.getY());
                 currentTouchState = TOUCH_STATE_SCROLL;
                 currentTouchState = TOUCH_STATE_SCROLL;
+                for (MapBaseLayer layer : layers) {
+                    layer.onTouch(event);
+                }
                 break;
                 break;
             case MotionEvent.ACTION_POINTER_DOWN:
             case MotionEvent.ACTION_POINTER_DOWN:
                 if (event.getPointerCount() == 2) {
                 if (event.getPointerCount() == 2) {
@@ -217,6 +220,9 @@ public class MapView extends TextureView implements TextureView.SurfaceTextureLi
                     currentMatrix.postScale(scale, scale, mid.x, mid.y);
                     currentMatrix.postScale(scale, scale, mid.x, mid.y);
                 }
                 }
                 lastMove.set(event.getX(), event.getY());
                 lastMove.set(event.getX(), event.getY());
+                for (MapBaseLayer layer : layers) {
+                    layer.onTouch(event);
+                }
                 refresh();
                 refresh();
                 break;
                 break;
         }
         }
@@ -372,30 +378,41 @@ public class MapView extends TextureView implements TextureView.SurfaceTextureLi
      * @param scale    缩放等级
      * @param scale    缩放等级
      */
      */
     public void animateCenterOnPoint(final float x, final float y, long duration, float scale) {
     public void animateCenterOnPoint(final float x, final float y, long duration, float scale) {
-        // 1. 计算目标偏移
-        float[] pts = {x, y};
-        currentMatrix.mapPoints(pts);
-        final float targetDx = getWidth() / 2f - pts[0];
-        final float targetDy = getHeight() / 2f - pts[1];
-        final float startZoom = currentZoom;
-        final float targetZoom = scale; // 终极目标缩放
+        // 0. 容错
+        if (duration <= 0) duration = 300;
+        if (currentZoom <= 0f) currentZoom = 1f;
 
 
-        // 2. 记录初始矩阵
+        // 1. 记录初始状态
+        final float startZoom = currentZoom;
+        final float targetZoom = scale;
         final Matrix startMatrix = new Matrix(currentMatrix);
         final Matrix startMatrix = new Matrix(currentMatrix);
 
 
-        // 3. ValueAnimator 插值执行平移
+        // 2. 动画驱动:每帧先缩放,再根据当帧矩阵计算把点居中需要的平移
         ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
         ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
         animator.setDuration(duration);
         animator.setDuration(duration);
         animator.setInterpolator(new AccelerateDecelerateInterpolator());
         animator.setInterpolator(new AccelerateDecelerateInterpolator());
         animator.addUpdateListener(animation -> {
         animator.addUpdateListener(animation -> {
             float frac = (float) animation.getAnimatedValue();
             float frac = (float) animation.getAnimatedValue();
-            // 当前帧缩放值(线性插值)
+            // 本帧的缩放值(线性或可替换为更合适的插值)
             float currentScale = startZoom + (targetZoom - startZoom) * frac;
             float currentScale = startZoom + (targetZoom - startZoom) * frac;
+
+            // 用起始矩阵为基准重建当帧矩阵
             currentMatrix.set(startMatrix);
             currentMatrix.set(startMatrix);
-            // 围绕目标点进行缩放
-            currentMatrix.postScale(currentScale / startZoom, currentScale / startZoom, x, y);
-            currentMatrix.postTranslate(targetDx * frac, targetDy * frac);
-            // 更新成员变量
+
+            // 2.1 围绕“世界坐标 (x,y)”进行缩放
+            float scaleFactor = currentScale / startZoom;
+            currentMatrix.postScale(scaleFactor, scaleFactor, x, y);
+
+            // 2.2 计算此时 (x,y) 在屏幕坐标的位置
+            float[] pts = {x, y};
+            currentMatrix.mapPoints(pts);
+
+            // 2.3 计算把该点移到屏幕中心所需的平移,并直接应用
+            float dx = getWidth()  / 2f - pts[0];
+            float dy = getHeight() / 2f - pts[1];
+            currentMatrix.postTranslate(dx, dy);
+
+            // 3. 更新状态并重绘
             currentZoom = currentScale;
             currentZoom = currentScale;
             refresh();
             refresh();
         });
         });

+ 7 - 0
app/src/main/res/drawable/divider_vertical_small.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="line">
+    <size
+        android:width="1dp"
+        android:height="@dimen/common_spacing_small" />
+</shape>

+ 1 - 0
app/src/main/res/layout/activity_login.xml

@@ -16,6 +16,7 @@
         android:orientation="horizontal" />
         android:orientation="horizontal" />
 
 
     <TextView
     <TextView
+        android:id="@+id/main_title"
         style="@style/CommonTextView"
         style="@style/CommonTextView"
         android:layout_above="@id/rv_type"
         android:layout_above="@id/rv_type"
         android:layout_centerHorizontal="true"
         android:layout_centerHorizontal="true"

+ 3 - 3
app/src/main/res/layout/activity_switch_status.xml

@@ -31,7 +31,7 @@
                 android:id="@+id/point_list"
                 android:id="@+id/point_list"
                 android:layout_width="wrap_content"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:layout_height="match_parent"
-                android:layout_marginLeft="20dp"
+                android:layout_marginLeft="12dp"
                 android:background="@drawable/common_layout_bg"
                 android:background="@drawable/common_layout_bg"
                 android:orientation="vertical"
                 android:orientation="vertical"
                 android:padding="@dimen/common_spacing"
                 android:padding="@dimen/common_spacing"
@@ -73,8 +73,8 @@
 
 
             <ImageView
             <ImageView
                 android:id="@+id/cb_show"
                 android:id="@+id/cb_show"
-                android:layout_width="40dp"
-                android:layout_height="40dp"
+                android:layout_width="24dp"
+                android:layout_height="24dp"
                 android:src="@drawable/icon_chevron_left"
                 android:src="@drawable/icon_chevron_left"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintStart_toStartOf="parent"

+ 6 - 6
app/src/main/res/layout/dialog_switch_info.xml

@@ -6,9 +6,9 @@
         android:layout_width="wrap_content"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_height="wrap_content"
         android:background="@drawable/common_layout_bg"
         android:background="@drawable/common_layout_bg"
-        android:divider="@drawable/divider_vertical"
+        android:divider="@drawable/divider_vertical_small"
         android:orientation="vertical"
         android:orientation="vertical"
-        android:padding="@dimen/common_spacing"
+        android:padding="@dimen/common_spacing_small"
         android:showDividers="middle">
         android:showDividers="middle">
 
 
         <TextView
         <TextView
@@ -16,7 +16,7 @@
             android:layout_width="wrap_content"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_height="wrap_content"
             android:textColor="@color/white"
             android:textColor="@color/white"
-            android:textSize="@dimen/common_text_size_big"
+            android:textSize="@dimen/common_text_size"
             android:textStyle="bold"
             android:textStyle="bold"
             tools:text="Switch station 5" />
             tools:text="Switch station 5" />
 
 
@@ -25,7 +25,7 @@
             android:layout_width="wrap_content"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_height="wrap_content"
             android:textColor="@color/white"
             android:textColor="@color/white"
-            android:textSize="@dimen/common_text_size"
+            android:textSize="@dimen/common_text_size_small"
             tools:text="ID:" />
             tools:text="ID:" />
 
 
         <LinearLayout
         <LinearLayout
@@ -39,7 +39,7 @@
                 android:layout_height="wrap_content"
                 android:layout_height="wrap_content"
                 android:text="@string/switch_status_tv"
                 android:text="@string/switch_status_tv"
                 android:textColor="@color/white"
                 android:textColor="@color/white"
-                android:textSize="@dimen/common_text_size" />
+                android:textSize="@dimen/common_text_size_small" />
 
 
             <TextView
             <TextView
                 android:id="@+id/switch_status"
                 android:id="@+id/switch_status"
@@ -47,7 +47,7 @@
                 android:layout_height="wrap_content"
                 android:layout_height="wrap_content"
                 android:background="@drawable/bg_switch_off"
                 android:background="@drawable/bg_switch_off"
                 android:textColor="@color/white"
                 android:textColor="@color/white"
-                android:textSize="@dimen/common_text_size"
+                android:textSize="@dimen/common_text_size_small"
                 android:paddingHorizontal="@dimen/common_spacing_small"
                 android:paddingHorizontal="@dimen/common_spacing_small"
                 android:paddingVertical="@dimen/common_spacing_smallest"
                 android:paddingVertical="@dimen/common_spacing_smallest"
                 android:textStyle="bold"
                 android:textStyle="bold"

+ 6 - 6
app/src/main/res/layout/item_switch.xml

@@ -7,9 +7,9 @@
         android:layout_width="match_parent"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_height="wrap_content"
         android:background="@drawable/common_layout_bg"
         android:background="@drawable/common_layout_bg"
-        android:divider="@drawable/divider_vertical"
+        android:divider="@drawable/divider_vertical_small"
         android:orientation="vertical"
         android:orientation="vertical"
-        android:padding="@dimen/common_spacing"
+        android:padding="@dimen/common_spacing_small"
         android:showDividers="middle">
         android:showDividers="middle">
 
 
         <TextView
         <TextView
@@ -17,7 +17,7 @@
             android:layout_width="wrap_content"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_height="wrap_content"
             android:textColor="@color/white"
             android:textColor="@color/white"
-            android:textSize="@dimen/common_text_size_big"
+            android:textSize="@dimen/common_text_size"
             android:textStyle="bold"
             android:textStyle="bold"
             tools:text="Switch station 5" />
             tools:text="Switch station 5" />
 
 
@@ -26,7 +26,7 @@
             android:layout_width="wrap_content"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_height="wrap_content"
             android:textColor="@color/white"
             android:textColor="@color/white"
-            android:textSize="@dimen/common_text_size"
+            android:textSize="@dimen/common_text_size_small"
             tools:text="ID:" />
             tools:text="ID:" />
 
 
         <LinearLayout
         <LinearLayout
@@ -40,7 +40,7 @@
                 android:layout_height="wrap_content"
                 android:layout_height="wrap_content"
                 android:text="@string/switch_status_tv"
                 android:text="@string/switch_status_tv"
                 android:textColor="@color/white"
                 android:textColor="@color/white"
-                android:textSize="@dimen/common_text_size" />
+                android:textSize="@dimen/common_text_size_small" />
 
 
             <TextView
             <TextView
                 android:id="@+id/switch_status"
                 android:id="@+id/switch_status"
@@ -48,7 +48,7 @@
                 android:layout_height="wrap_content"
                 android:layout_height="wrap_content"
                 android:background="@drawable/bg_switch_off"
                 android:background="@drawable/bg_switch_off"
                 android:textColor="@color/white"
                 android:textColor="@color/white"
-                android:textSize="@dimen/common_text_size"
+                android:textSize="@dimen/common_text_size_small"
                 android:paddingHorizontal="@dimen/common_spacing_small"
                 android:paddingHorizontal="@dimen/common_spacing_small"
                 android:paddingVertical="@dimen/common_spacing_smallest"
                 android:paddingVertical="@dimen/common_spacing_smallest"
                 android:textStyle="bold"
                 android:textStyle="bold"