Панель статуса сдвигается к носу вместе с контейнером (panelOffsetX): центр панели = центр контейнера

This commit is contained in:
2026-08-25 02:39:43 +03:00
parent 4f4a551c91
commit 74701a2108
3 changed files with 43 additions and 2 deletions
@@ -66,6 +66,7 @@ import pw.binom.viewmate.glasses.ui.Side
import pw.binom.viewmate.glasses.ui.px import pw.binom.viewmate.glasses.ui.px
import pw.binom.viewmate.glasses.ui.scaleOffsetX import pw.binom.viewmate.glasses.ui.scaleOffsetX
import pw.binom.viewmate.glasses.ui.verticalOffsetY import pw.binom.viewmate.glasses.ui.verticalOffsetY
import pw.binom.viewmate.glasses.ui.panelOffsetX
class MainActivity : BaseEventActivity() { class MainActivity : BaseEventActivity() {
private var resumeAfterScreenOn = false private var resumeAfterScreenOn = false
@@ -504,7 +505,10 @@ fun ConnectionScreen() {
} }
StatusPanelCompose( StatusPanelCompose(
modifier = Modifier.align(Alignment.BottomCenter).padding(bottom = 10.dp), modifier = Modifier
.align(Alignment.BottomCenter)
.offset(x = panelOffsetX(side, screenWidthPx, scale).px)
.padding(bottom = 10.dp),
scale = scale, // панель масштабируется вместе с контентом, но прибита к низу scale = scale, // панель масштабируется вместе с контентом, но прибита к низу
) )
} }
@@ -140,7 +140,10 @@ fun GlassesMovieScreen(
} }
StatusPanelCompose( StatusPanelCompose(
modifier = Modifier.align(Alignment.BottomCenter).padding(bottom = 10.dp), modifier = Modifier
.align(Alignment.BottomCenter)
.offset(x = panelOffsetX(side, screenWidthPx, scale).px)
.padding(bottom = 10.dp),
scale = scale, // панель масштабируется вместе с контентом, но прибита к низу scale = scale, // панель масштабируется вместе с контентом, но прибита к низу
) )
} }
@@ -170,6 +173,14 @@ fun verticalOffsetY(screenHeightPx: Int, scale: Float, vertical: Float): Int =
fun videoOffsetY(containerHeightPx: Int, videoHeightPx: Int, vertical: Float): Int = fun videoOffsetY(containerHeightPx: Int, videoHeightPx: Int, vertical: Float): Int =
((1f - vertical) * (containerHeightPx - videoHeightPx).coerceAtLeast(0)).toInt() ((1f - vertical) * (containerHeightPx - videoHeightPx).coerceAtLeast(0)).toInt()
/**
* Горизонтальный сдвиг панели статуса к центру (к носу), чтобы её центр совпадал
* с центром контейнера при любом масштабе: LEFT — вправо, RIGHT — влево,
* на половину хода контейнера ((1 - scale) * W / 2).
*/
fun panelOffsetX(side: Side, screenWidthPx: Int, scale: Float): Int =
((1f - scale) * screenWidthPx / 2f).toInt() * if (side == Side.LEFT) 1 else -1
/** Отладочный режим: красный квадрат вместо видео (проверка масштаба/позиций скрином). Перед финалом — false. */ /** Отладочный режим: красный квадрат вместо видео (проверка масштаба/позиций скрином). Перед финалом — false. */
private const val SCALE_DEBUG_SQUARE = false private const val SCALE_DEBUG_SQUARE = false
@@ -6,6 +6,7 @@ import pw.binom.viewmate.glasses.ui.Side
import pw.binom.viewmate.glasses.ui.scaleOffsetX import pw.binom.viewmate.glasses.ui.scaleOffsetX
import pw.binom.viewmate.glasses.ui.verticalOffsetY import pw.binom.viewmate.glasses.ui.verticalOffsetY
import pw.binom.viewmate.glasses.ui.videoOffsetY import pw.binom.viewmate.glasses.ui.videoOffsetY
import pw.binom.viewmate.glasses.ui.panelOffsetX
/** /**
* scaleOffsetX — смещение контейнера глаза к центру (к носу): * scaleOffsetX — смещение контейнера глаза к центру (к носу):
@@ -88,4 +89,29 @@ class ScaleOffsetTest {
fun videoLargerThanContainer_noNegativeOffset() { fun videoLargerThanContainer_noNegativeOffset() {
assertEquals(0, videoOffsetY(200, 268, 0f), "видео выше контейнера — хода нет") assertEquals(0, videoOffsetY(200, 268, 0f), "видео выше контейнера — хода нет")
} }
/*
* panelOffsetX — панель статуса сдвигается к носу, как контейнер:
* LEFT — вправо, RIGHT — влево, на (1 - scale) * W / 2.
*/
@Test
fun panelFullScale_noOffset() {
assertEquals(0, panelOffsetX(Side.LEFT, 640, 1f))
assertEquals(0, panelOffsetX(Side.RIGHT, 640, 1f))
}
@Test
fun panelHalfScale_movesTowardNose() {
// 640 * 0.5 / 2 = 160: LEFT вправо, RIGHT влево
assertEquals(160, panelOffsetX(Side.LEFT, 640, 0.5f))
assertEquals(-160, panelOffsetX(Side.RIGHT, 640, 0.5f))
}
@Test
fun panelScale07_offset() {
// 640 * 0.3 / 2 = 96
assertEquals(96, panelOffsetX(Side.LEFT, 640, 0.7f))
assertEquals(-96, panelOffsetX(Side.RIGHT, 640, 0.7f))
}
} }