注释解释

This commit is contained in:
2026-06-12 17:20:31 +08:00
parent 78d2d2cd79
commit d30c025874

View File

@@ -45,7 +45,7 @@ class StrikePositionActivity : AppCompatActivity() {
private var selectedZone: Zone = Zone.CHEST
// Touch tracking for ImageView (captured in onTouch, used in ACTION_UP for click detection)
// ImageView 的触控追踪(在 onTouch 中捕获ACTION_UP 用于点击检测)
private var lastTouchX = 0f
private var lastTouchY = 0f
@@ -67,7 +67,7 @@ class StrikePositionActivity : AppCompatActivity() {
binding.ivBack.setOnClickListener { finish() }
binding.btnSubmit.setOnClickListener { showConfirmDialog() }
// Use OnTouchListener to track touch coordinates
// 使用 OnTouchListen 来跟踪触摸坐标
binding.ivHumanBody.setOnTouchListener { _, event ->
lastTouchX = event.x
lastTouchY = event.y
@@ -77,7 +77,7 @@ class StrikePositionActivity : AppCompatActivity() {
false
}
// OnClick fires on ACTION_UP; coordinates captured from lastTouchX/Y
// OnClick 对ACTION_UP开火;坐标来自lastTouchXY
binding.ivHumanBody.setOnClickListener {
val imageView = it as ImageView
val (nx, ny) = resolveTapLocation(lastTouchX, lastTouchY, imageView)
@@ -100,10 +100,12 @@ class StrikePositionActivity : AppCompatActivity() {
}
/**
* Converts a screen coordinate (from onTouch) into a normalised [0..1] offset
* inside the drawable, accounting for:
* - ImageView scaling (scaleType="fitCenter" adds letterboxing)
* - Letterbox / pillarbox margins when image aspect ≠ view aspect
* 这段代码将触摸坐标转换为图片内部的归一化位置:
*
* 1. 计算图片等比缩放后的实际尺寸
* 2. 计算letterbox/pillarbox的偏移量
* 3. 将触摸点限制在图片有效区域内
* 4. 返回相对于图片的归一化坐标(0-1范围)
*/
private fun resolveTapLocation(rawX: Float, rawY: Float, imageView: ImageView): Pair<Float, Float> {
val drawable = imageView.drawable ?: return Pair(0f, 0f)
@@ -114,22 +116,22 @@ class StrikePositionActivity : AppCompatActivity() {
val intrinsicWidth = drawable.intrinsicWidth.toFloat()
val intrinsicHeight = drawable.intrinsicHeight.toFloat()
// scale: the uniform factor the image is scaled by to fit the view
// 比例:图像被缩放以适应视图的均匀因子
val scale = min(ivWidth / intrinsicWidth, ivHeight / intrinsicHeight)
// Physical pixel size of the drawable after scaling
// 缩放后绘制的物理像素大小
val drawnW = intrinsicWidth * scale
val drawnH = intrinsicHeight * scale
// Letterbox offsets (top / left) when aspect ratios differ
// 当宽高比不同时,信箱偏移(左上角)
val drawableLeft = (ivWidth - drawnW) / 2f
val drawableTop = (ivHeight - drawnH) / 2f
// Clamp touch to the actual drawable area
// 夹紧触地接触实际可绘制区域
val clampedX = max(drawableLeft, min(rawX, drawableLeft + drawnW))
val clampedY = max(drawableTop, min(rawY, drawableTop + drawnH))
// Normalised offset [0..1] within the drawable
// 可绘制物内的归一化偏移 [0..1]
val normalizedX = (clampedX - drawableLeft) / drawnW
val normalizedY = (clampedY - drawableTop) / drawnH
@@ -137,14 +139,11 @@ class StrikePositionActivity : AppCompatActivity() {
}
/**
* Zones are divided by:
* - Horizontal boundary at ny = 0.5 → top = HEAD, bottom = shoulders
* - Vertical boundary 1 at nx = 1/3 → left = LEFT_SHOULDER
* - Vertical boundary 2 at nx = 2/3 → right = RIGHT_SHOULDER, middle = CHEST
* 这段代码根据归一化坐标确定触摸区域:
*
* If the touch falls within ±tolerance of any boundary line, the nearest
* zone centre (Euclidean distance in normalised space) is used to avoid
* arbitrary assignments at boundary pixels.
* 1. 将图片分为头部、左肩、胸部、右肩四个区域
* 2. 边界附近±0.04范围内,使用最近区域中心避免误判
* 3. 上半部分为头部下半部分按1/3和2/3垂直线划分
*/
private fun zoneForLocation(nx: Float, ny: Float): Zone {
val hBoundary = 0.5f
@@ -168,7 +167,14 @@ class StrikePositionActivity : AppCompatActivity() {
}
}
/** Returns the Zone whose normalised centre is closest (Euclidean) to (nx, ny). */
/**
* 这段代码找到距离触摸点最近的区域:
*
* 1. 遍历所有Zone计算与触摸点的欧氏距离平方
* 2. 返回距离最小的Zone作为结果
* 3. 若无匹配则默认返回CHEST
* */
private fun nearestZone(nx: Float, ny: Float): Zone {
return Zone.values().minByOrNull { zone ->
val dx = nx - zone.normalizedX
@@ -178,12 +184,12 @@ class StrikePositionActivity : AppCompatActivity() {
}
/**
* Positions the marker (ivStrikeMarker) at the zone's centre, clamped so the
* marker never goes out of the ivHumanBody bounds.
*
* Because the marker is a child of ivHumanBody and starts at its center
* (layout_gravity="center"), we compute the offset from that center point
* and apply it via translationX/Y so the marker's layout bounds stay intact.
这段代码更新标记位置到区域中心:
1. 根据Zone的归一化坐标计算目标位置
2. 限制标记不超出图片边界Y仅限制上限
3. 相对于ImageView中心计算偏移量并应用
4. 支持动画或即时移动两种方式
*/
private fun updateMarkerPosition(zone: Zone, animated: Boolean) {
if (humanBodyWidth <= 0 || humanBodyHeight <= 0) return
@@ -198,9 +204,7 @@ class StrikePositionActivity : AppCompatActivity() {
val rawX = humanBodyWidth * zone.normalizedX
val rawY = humanBodyHeight * zone.normalizedY
// Clamp X so the marker never extends beyond the drawable edges.
// Y clamp only has an upper bound — HEAD at normalizedY=0 is allowed to go
// all the way to the top (translationY can be negative).
//用X夹住使标记永远不会超出可绘制的边缘。Y钳只有一个上界——在归一化Y=0处的HEAD可以一直达到顶端平移Y可以为负
val clampedX = min(max(rawX, halfMarkerW), humanBodyWidth - halfMarkerW)
val clampedY = min(rawY, humanBodyHeight - halfMarkerH)