From 59b3ad72fed16388e9561fb4ea7caec966e8b278 Mon Sep 17 00:00:00 2001
From: lvmeng <848755140@qq.com>
Date: Wed, 11 Feb 2026 17:00:08 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=BA=E8=84=B8=E8=AF=86?=
=?UTF-8?q?=E5=88=AB=E6=98=BE=E7=A4=BA=E5=BD=A2=E7=8A=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../presentation/MainScreenPresentation.kt | 51 --------
.../presentation/pay/FacePayPresentation.kt | 58 +--------
.../dualscreen/view/HollowOvalInRectView.kt | 122 ++++++++++++++++++
.../main/res/layout/presentation_face_pay.xml | 52 ++------
.../res/layout/presentation_main_screen.xml | 35 ++---
5 files changed, 144 insertions(+), 174 deletions(-)
create mode 100644 app/src/main/java/com/sw/dualscreen/view/HollowOvalInRectView.kt
diff --git a/app/src/main/java/com/sw/dualscreen/presentation/MainScreenPresentation.kt b/app/src/main/java/com/sw/dualscreen/presentation/MainScreenPresentation.kt
index 3166daa..1fc8b9c 100644
--- a/app/src/main/java/com/sw/dualscreen/presentation/MainScreenPresentation.kt
+++ b/app/src/main/java/com/sw/dualscreen/presentation/MainScreenPresentation.kt
@@ -905,62 +905,11 @@ class MainScreenPresentation(
displayOrientation: Int,
scale: Float
): ViewGroup.LayoutParams {
-// val layoutParams = previewView.layoutParams
-// val measuredWidth = previewView.measuredWidth
-// val measuredHeight = previewView.measuredHeight
-// var ratio = (previewSize.height.toFloat()) / previewSize.width.toFloat()
-// if (ratio > 1) {
-// ratio = 1 / ratio
-// }
-// if (displayOrientation % 180 == 0) {
-// layoutParams.width = measuredWidth
-// layoutParams.height = (measuredWidth * ratio).toInt()
-// } else {
-// layoutParams.height = measuredHeight
-// layoutParams.width = (measuredHeight * ratio).toInt()
-// }
-// if (scale < 1f) {
-// val rgbParam = rgbPreview.layoutParams
-// layoutParams.width = (rgbParam.width * scale).toInt()
-// layoutParams.height = (rgbParam.height * scale).toInt()
-// } else {
-// layoutParams.width = (layoutParams.width * scale).toInt()
-// layoutParams.height = (layoutParams.height * scale).toInt()
-// }
-//
-// val metrics = DisplayMetrics()
-// activity.windowManager.defaultDisplay.getMetrics(metrics)
-//
-// if (layoutParams.width >= metrics.widthPixels) {
-// val viewRatio = layoutParams.width / (metrics.widthPixels.toFloat())
-// layoutParams.width = (layoutParams.width / viewRatio).toInt()
-// layoutParams.height = (layoutParams.height / viewRatio).toInt()
-// }
-// if (layoutParams.height >= metrics.heightPixels) {
-// val viewRatio = layoutParams.height / (metrics.heightPixels.toFloat())
-// layoutParams.width = (layoutParams.width / viewRatio).toInt()
-// layoutParams.height = (layoutParams.height / viewRatio).toInt()
-// }
-
-// Timber.tag(TAG).d("initRgbCamera:metrics(${metrics.widthPixels},${metrics.heightPixels})")
-
-
- //val layoutParams = previewView.layoutParams
- //layoutParams.width = 1024
- //layoutParams.height = 768
-// val w = 600.dp //(912.dp * scale).toInt()
-// val h = 900.dp //684.dp
-// val w = 500.dp
-// val h = 850.dp
val w = 600.dp
val h = 1068.dp
- //(1024*scale).toInt()
val layoutParams = FrameLayout.LayoutParams(w, h);
-// val layoutParams = FrameLayout.LayoutParams(480, 320);
-// val layoutParams = FrameLayout.LayoutParams(912.dp, 684.dp);
previewView.setLayoutParams(layoutParams)
faceRectView.setLayoutParams(layoutParams)
-
return layoutParams
}
diff --git a/app/src/main/java/com/sw/dualscreen/presentation/pay/FacePayPresentation.kt b/app/src/main/java/com/sw/dualscreen/presentation/pay/FacePayPresentation.kt
index e85db20..d295c8a 100644
--- a/app/src/main/java/com/sw/dualscreen/presentation/pay/FacePayPresentation.kt
+++ b/app/src/main/java/com/sw/dualscreen/presentation/pay/FacePayPresentation.kt
@@ -280,58 +280,9 @@ class FacePayPresentation(
displayOrientation: Int,
scale: Float
): ViewGroup.LayoutParams {
-// val layoutParams = previewView.layoutParams
-// val measuredWidth = previewView.measuredWidth
-// val measuredHeight = previewView.measuredHeight
-// var ratio = (previewSize.height.toFloat()) / previewSize.width.toFloat()
-// if (ratio > 1) {
-// ratio = 1 / ratio
-// }
-// if (displayOrientation % 180 == 0) {
-// layoutParams.width = measuredWidth
-// layoutParams.height = (measuredWidth * ratio).toInt()
-// } else {
-// layoutParams.height = measuredHeight
-// layoutParams.width = (measuredHeight * ratio).toInt()
-// }
-// if (scale < 1f) {
-// val rgbParam = rgbPreview.getLayoutParams()
-// layoutParams.width = (rgbParam.width * scale).toInt()
-// layoutParams.height = (rgbParam.height * scale).toInt()
-// } else {
-// layoutParams.width = (layoutParams.width * scale).toInt()
-// layoutParams.height = (layoutParams.height * scale).toInt()
-// }
-//
-// val metrics = DisplayMetrics()
-// activity.windowManager.defaultDisplay.getMetrics(metrics)
-//
-// if (layoutParams.width >= metrics.widthPixels) {
-// val viewRatio = layoutParams.width / (metrics.widthPixels.toFloat())
-// layoutParams.width = (layoutParams.width / viewRatio).toInt()
-// layoutParams.height = (layoutParams.height / viewRatio).toInt()
-// }
-// if (layoutParams.height >= metrics.heightPixels) {
-// val viewRatio = layoutParams.height / (metrics.heightPixels.toFloat())
-// layoutParams.width = (layoutParams.width / viewRatio).toInt()
-// layoutParams.height = (layoutParams.height / viewRatio).toInt()
-// }
-
-
-// val layoutParams = previewView.layoutParams
-// layoutParams.width = (608.dp * 1.5).roundToInt()
-// layoutParams.height = (456.dp * 1.5).roundToInt()
-// layoutParams.width = (608.dp * 1.5).roundToInt()
-// layoutParams.height = (456.dp * 1.5).roundToInt()
-// layoutParams.width = 1024
-// layoutParams.height = 768
-// val w = 500.dp
-// val h = 850.dp
- val w = 600.dp
+ val w = (600.dp * 1.5).toInt()
val h = 1068.dp
-// val w = 720.dp
-// val h = 1280.dp
- val layoutParams = FrameLayout.LayoutParams(w, h);
+ val layoutParams = FrameLayout.LayoutParams(w, h)
previewView.setLayoutParams(layoutParams)
faceRectView.setLayoutParams(layoutParams)
@@ -472,9 +423,10 @@ class FacePayPresentation(
)
irFaceRectTransformer = FaceRectTransformer(
-// previewSizeIr.width, previewSizeIr.height,
+ previewSizeIr.width, previewSizeIr.height,
+// layoutParams.width, layoutParams.height,
layoutParams.width, layoutParams.height,
- layoutParams.width, layoutParams.height, displayOrientation, cameraId, isMirror,
+ displayOrientation, cameraId, isMirror,
ConfigUtil.isDrawIrRectHorizontalMirror(context),
ConfigUtil.isDrawIrRectVerticalMirror(context)
)
diff --git a/app/src/main/java/com/sw/dualscreen/view/HollowOvalInRectView.kt b/app/src/main/java/com/sw/dualscreen/view/HollowOvalInRectView.kt
new file mode 100644
index 0000000..a49577f
--- /dev/null
+++ b/app/src/main/java/com/sw/dualscreen/view/HollowOvalInRectView.kt
@@ -0,0 +1,122 @@
+package com.sw.dualscreen.view
+
+import androidx.core.graphics.toColorInt
+import android.content.Context
+import android.graphics.*
+import android.util.AttributeSet
+import android.view.View
+
+/**
+ * 带镂空椭圆的矩形自定义View
+ * 矩形尺寸:400dp × 510dp,背景色 #FFF4FAFF
+ * 镂空椭圆尺寸:400dp × 436dp,居中显示
+ */
+class HollowOvalInRectView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : View(context, attrs, defStyleAttr) {
+
+ // 基础尺寸配置(dp)
+ private val rectWidthDp = 400f // 矩形宽度
+ private val rectHeightDp = 510f // 矩形高度
+ private val ovalWidthDp = 400f // 椭圆宽度
+ private val ovalHeightDp = 436f // 椭圆高度
+
+ // 转换后的像素尺寸
+ private val rectWidth: Float
+ private val rectHeight: Float
+ private var ovalWidth: Float
+ private var ovalHeight: Float
+
+ // 矩形背景画笔(颜色 #FFF4FAFF)
+ private val rectPaint = Paint().apply {
+ isAntiAlias = true
+ color = "#FFF4FAFF".toColorInt() // 矩形背景色
+// color = "#FFFFFF".toColorInt() // 矩形背景色
+ style = Paint.Style.FILL
+ }
+
+ // 镂空椭圆画笔(核心:DST_OUT模式实现镂空)
+ private val hollowOvalPaint = Paint().apply {
+ isAntiAlias = true
+ color = Color.BLACK // 颜色不影响镂空效果,仅需非透明即可
+ style = Paint.Style.FILL
+ xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
+ }
+
+ // 椭圆路径(复用避免重复创建)
+ private val ovalPath = Path()
+
+ init {
+ // dp转px,保证多设备尺寸一致
+ val density = resources.displayMetrics.density
+ rectWidth = rectWidthDp * density
+ rectHeight = rectHeightDp * density
+ ovalWidth = ovalWidthDp * density
+ ovalHeight = ovalHeightDp * density
+
+ // 关键配置:关闭硬件加速保证Xfermode生效
+ setLayerType(LAYER_TYPE_HARDWARE, null)
+ // 视图背景透明,避免干扰
+ setBackgroundColor(Color.TRANSPARENT)
+ }
+
+ /**
+ * 强制设置View尺寸为指定的矩形尺寸
+ */
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ val targetWidth = MeasureSpec.makeMeasureSpec(rectWidth.toInt(), MeasureSpec.EXACTLY)
+ val targetHeight = MeasureSpec.makeMeasureSpec(rectHeight.toInt(), MeasureSpec.EXACTLY)
+ super.onMeasure(targetWidth, targetHeight)
+ }
+
+ /**
+ * 核心绘制逻辑:先画矩形,再画镂空椭圆
+ */
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+
+ // 保存画布图层,确保Xfermode生效
+ val layerId = canvas.saveLayer(0f, 0f, width.toFloat(), height.toFloat(), null)
+
+ // 1. 绘制底层矩形(背景色 #FFF4FAFF)
+ canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), rectPaint)
+
+ // 2. 计算椭圆居中坐标(椭圆宽度和矩形宽度一致,仅垂直居中)
+ val ovalTop = (rectHeight - ovalHeight) / 2 // 椭圆顶部偏移
+ val ovalBottom = ovalTop + ovalHeight // 椭圆底部坐标
+
+ // 3. 绘制镂空椭圆(居中)
+ ovalPath.reset()
+ ovalPath.addOval(
+ 0f, // 左:和矩形左对齐(宽度一致)
+ ovalTop, // 上:垂直居中
+ rectWidth, // 右:和矩形右对齐
+ ovalBottom, // 下
+ Path.Direction.CW
+ )
+ canvas.drawPath(ovalPath, hollowOvalPaint)
+
+ // 恢复画布状态
+ canvas.restoreToCount(layerId)
+ }
+
+ // 扩展方法:支持动态修改矩形背景色
+ fun updateRectBackgroundColor(colorHex: String) {
+ try {
+ rectPaint.color = Color.parseColor(colorHex)
+ invalidate() // 重绘视图
+ } catch (e: IllegalArgumentException) {
+ e.printStackTrace()
+ }
+ }
+
+ // 扩展方法:支持动态修改椭圆尺寸(可选)
+ fun updateOvalSize(widthDp: Float, heightDp: Float) {
+ val density = resources.displayMetrics.density
+ ovalWidth = widthDp * density
+ ovalHeight = heightDp * density
+ invalidate()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/presentation_face_pay.xml b/app/src/main/res/layout/presentation_face_pay.xml
index 49b7c19..0497b4f 100644
--- a/app/src/main/res/layout/presentation_face_pay.xml
+++ b/app/src/main/res/layout/presentation_face_pay.xml
@@ -69,7 +69,7 @@
+ android:layout_height="510dp">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -149,7 +125,7 @@
android:layout_weight="1"
android:background="#FFF4FAFF" />
-
@@ -165,7 +141,6 @@
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/presentation_main_screen.xml b/app/src/main/res/layout/presentation_main_screen.xml
index ecd00a8..2e0e279 100644
--- a/app/src/main/res/layout/presentation_main_screen.xml
+++ b/app/src/main/res/layout/presentation_main_screen.xml
@@ -72,23 +72,6 @@
android:src="@drawable/face_mask"
android:visibility="gone" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -121,22 +104,15 @@
-
-
-
-
-
-
-
+ android:textSize="22sp"
+ tools:ignore="HardcodedText" />
+
+
+
+
+
\ No newline at end of file