Высота: видео в контейнере прижимается к верху/низу по vertical (Row-центрирование съедало вертикаль)

This commit is contained in:
2026-08-25 02:15:48 +03:00
parent 6d22f56bd8
commit 883fd8e5e4
2 changed files with 40 additions and 1 deletions
@@ -115,6 +115,9 @@ fun GlassesMovieScreen(
) { ) {
Row( Row(
modifier = Modifier.fillMaxWidth().background(Color.Black), modifier = Modifier.fillMaxWidth().background(Color.Black),
// Видео в контейнере прижимается к верху (vertical=1) или низу (vertical=0):
// Row-центрирование съедало вертикаль — картинка оставалась «по центру».
verticalAlignment = Alignment.Top,
horizontalArrangement = if (side == Side.LEFT) Arrangement.End else Arrangement.Start, horizontalArrangement = if (side == Side.LEFT) Arrangement.End else Arrangement.Start,
) { ) {
if (SCALE_DEBUG_SQUARE) { if (SCALE_DEBUG_SQUARE) {
@@ -125,7 +128,9 @@ fun GlassesMovieScreen(
BinocularVideoPlayer( BinocularVideoPlayer(
player = player, player = player,
renderer = renderer, renderer = renderer,
modifier = Modifier.size(playerWidth.px, playerHeight.px), modifier = Modifier
.size(playerWidth.px, playerHeight.px)
.offset(y = videoOffsetY(containerH, playerHeight, vertical).px),
) )
} }
} }
@@ -155,6 +160,14 @@ fun scaleOffsetX(side: Side, screenWidthPx: Int, scale: Float): Int =
fun verticalOffsetY(screenHeightPx: Int, scale: Float, vertical: Float): Int = fun verticalOffsetY(screenHeightPx: Int, scale: Float, vertical: Float): Int =
((1f - vertical) * screenHeightPx * (1f - scale)).toInt() ((1f - vertical) * screenHeightPx * (1f - scale)).toInt()
/**
* Смещение видео внутри контейнера глаза: vertical=1.0 — у верха контейнера,
* 0.0 — у низа (нижняя кромка видео прижата к низу контейнера, который сам
* у низа экрана при vertical=0). Row-центрирование иначе съедало вертикаль.
*/
fun videoOffsetY(containerHeightPx: Int, videoHeightPx: Int, vertical: Float): Int =
((1f - vertical) * (containerHeightPx - videoHeightPx).coerceAtLeast(0)).toInt()
/** Отладочный режим: красный квадрат вместо видео (проверка масштаба/позиций скрином). Перед финалом — false. */ /** Отладочный режим: красный квадрат вместо видео (проверка масштаба/позиций скрином). Перед финалом — false. */
private const val SCALE_DEBUG_SQUARE = false private const val SCALE_DEBUG_SQUARE = false
@@ -5,6 +5,7 @@ import kotlin.test.assertEquals
import pw.binom.viewmate.glasses.ui.Side 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
/** /**
* scaleOffsetX — смещение контейнера глаза к центру (к носу): * scaleOffsetX — смещение контейнера глаза к центру (к носу):
@@ -62,4 +63,29 @@ class ScaleOffsetTest {
assertEquals(72, verticalOffsetY(480, 0.7f, 0.5f)) assertEquals(72, verticalOffsetY(480, 0.7f, 0.5f))
assertEquals(0, verticalOffsetY(480, 1f, 0.5f)) assertEquals(0, verticalOffsetY(480, 1f, 0.5f))
} }
/*
* videoOffsetY — видео внутри контейнера: верх при vertical=1, низ при 0.
*/
@Test
fun videoTop_zero() {
assertEquals(0, videoOffsetY(432, 268, 1f))
}
@Test
fun videoBottom_pushedToContainerBottom() {
// 432 контейнер, 268 видео: ход = 164
assertEquals(164, videoOffsetY(432, 268, 0f))
}
@Test
fun videoMiddle_halfOfRun() {
assertEquals(82, videoOffsetY(432, 268, 0.5f))
}
@Test
fun videoLargerThanContainer_noNegativeOffset() {
assertEquals(0, videoOffsetY(200, 268, 0f), "видео выше контейнера — хода нет")
}
} }