package com.aoleyun.sn.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PointF; import android.util.AttributeSet; import android.view.View; import androidx.annotation.Nullable; import java.util.Locale; public class FaceOverlayView extends View { private Paint pointPaint; private Paint textPaint; private PointF leftEye; private PointF rightEye; private double distance; private int imageWidth; private int imageHeight; public FaceOverlayView(Context context) { super(context); init(); } public FaceOverlayView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } private void init() { pointPaint = new Paint(); pointPaint.setColor(Color.RED); pointPaint.setStyle(Paint.Style.FILL); pointPaint.setStrokeWidth(10f); textPaint = new Paint(); textPaint.setColor(Color.YELLOW); textPaint.setTextSize(60f); textPaint.setFakeBoldText(true); textPaint.setShadowLayer(5, 0, 0, Color.BLACK); } public void updateData(double distance, PointF leftEye, PointF rightEye, int imageWidth, int imageHeight) { this.distance = distance; this.leftEye = leftEye; this.rightEye = rightEye; this.imageWidth = imageWidth; this.imageHeight = imageHeight; postInvalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (leftEye == null || rightEye == null || imageWidth <= 0 || imageHeight <= 0) { canvas.drawText("未检测到人脸", 50, 100, textPaint); return; } // 1. 获取 View 的尺寸 float viewWidth = getWidth(); float viewHeight = getHeight(); // 2. 计算缩放比例 (适配 PreviewView 的 FILL_CENTER 逻辑) // FILL_CENTER:取宽高缩放比例中较大的一个,使图像填满 View 且不拉伸,多出的部分被裁剪 float scale = Math.max(viewWidth / imageWidth, viewHeight / imageHeight); // 3. 计算偏移量(由居中裁剪产生) float postScaleWidth = imageWidth * scale; float postScaleHeight = imageHeight * scale; float offsetX = (viewWidth - postScaleWidth) / 2f; float offsetY = (viewHeight - postScaleHeight) / 2f; // 4. 坐标映射并处理镜像 // CameraX 的 PreviewView 显示前置摄像头时默认是镜像的 // 映射公式: viewX = viewWidth - (imageX * scale + offsetX) float lx = viewWidth - (leftEye.x * scale + offsetX); float ly = leftEye.y * scale + offsetY; float rx = viewWidth - (rightEye.x * scale + offsetX); float ry = rightEye.y * scale + offsetY; // 绘制眼睛点位 canvas.drawCircle(lx, ly, 15, pointPaint); canvas.drawCircle(rx, ry, 15, pointPaint); // 绘制连线,更直观 canvas.drawLine(lx, ly, rx, ry, pointPaint); canvas.drawText(String.format(Locale.getDefault(), "瞳距: %.2f", distance), 50, 100, textPaint); } }