Improved PDF vertical reader zoom and orientation handling (#98)
- Implemented `fitZoom` calculation to properly center and scale pages, especially in landscape orientation. - Updated `clampValues` and animation bounds to ensure content is correctly centered when zoomed out. - Refined double-tap-to-zoom logic to toggle between `fitZoom`, 1x, and 2.5x scales. - Replaced manual frame-based zooming with `Animatable.animateTo` for smoother transitions. - Added `configChanges` to `MainActivity` in `AndroidManifest.xml` to handle orientation and screen size changes manually. - Reduced delays and improved reliability of initial page snapping in `PdfViewerScreen`.
This commit is contained in:
parent
c9dc3ce8c2
commit
a9c791120d
3 changed files with 136 additions and 107 deletions
|
|
@ -47,6 +47,7 @@
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:theme="@style/Theme.Reader"
|
android:theme="@style/Theme.Reader"
|
||||||
|
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
|
||||||
android:launchMode="singleTask">
|
android:launchMode="singleTask">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
|
||||||
|
|
@ -260,13 +260,10 @@ internal fun PdfVerticalReader(
|
||||||
val dividerHeightPx = with(density) { dividerHeightDp.toPx() }
|
val dividerHeightPx = with(density) { dividerHeightDp.toPx() }
|
||||||
|
|
||||||
val layoutState = remember(ratios, screenWidth, screenHeight, density) {
|
val layoutState = remember(ratios, screenWidth, screenHeight, density) {
|
||||||
// Return a wrapper object containing both list and total height to ensure
|
|
||||||
// atomicity
|
|
||||||
data class LayoutResult(val pages: List<PdfPageLayout>, val totalHeight: Float)
|
data class LayoutResult(val pages: List<PdfPageLayout>, val totalHeight: Float)
|
||||||
|
|
||||||
var currentY = 0.0
|
var currentY = 0.0
|
||||||
|
|
||||||
// Special case for single page centering
|
|
||||||
if (ratios.size == 1) {
|
if (ratios.size == 1) {
|
||||||
val ratio = ratios[0]
|
val ratio = ratios[0]
|
||||||
val safeRatio = if (ratio <= 0f) 1f else ratio
|
val safeRatio = if (ratio <= 0f) 1f else ratio
|
||||||
|
|
@ -278,7 +275,6 @@ internal fun PdfVerticalReader(
|
||||||
|
|
||||||
val pages = ratios.mapIndexed { index, ratio ->
|
val pages = ratios.mapIndexed { index, ratio ->
|
||||||
val safeRatio = if (ratio <= 0f) 1f else ratio
|
val safeRatio = if (ratio <= 0f) 1f else ratio
|
||||||
// Use double for calculation
|
|
||||||
val pageHeightDouble = screenWidth.toDouble() / safeRatio.toDouble()
|
val pageHeightDouble = screenWidth.toDouble() / safeRatio.toDouble()
|
||||||
val pageHeight = pageHeightDouble.toFloat()
|
val pageHeight = pageHeightDouble.toFloat()
|
||||||
|
|
||||||
|
|
@ -297,9 +293,7 @@ internal fun PdfVerticalReader(
|
||||||
info
|
info
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate exact total height based on the double accumulator
|
|
||||||
val totalH = if (pages.isNotEmpty()) {
|
val totalH = if (pages.isNotEmpty()) {
|
||||||
// Determine the bottom of the last element strictly
|
|
||||||
val last = pages.last()
|
val last = pages.last()
|
||||||
last.y + last.height
|
last.y + last.height
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -314,58 +308,85 @@ internal fun PdfVerticalReader(
|
||||||
Timber.tag(SCROLL_BOUNDS_TAG)
|
Timber.tag(SCROLL_BOUNDS_TAG)
|
||||||
.d("Layout Recalculated. Page Count: ${layoutInfo.size}, TotalDocHeight: $totalDocHeight")
|
.d("Layout Recalculated. Page Count: ${layoutInfo.size}, TotalDocHeight: $totalDocHeight")
|
||||||
|
|
||||||
val zoomAnimatable = remember { Animatable(1f) }
|
val fitZoom = remember(ratios, screenWidth, screenHeight) {
|
||||||
val panXAnimatable = remember { Animatable(0f) }
|
if (ratios.isEmpty() || screenWidth == 0f || screenHeight == 0f) 1f
|
||||||
|
else {
|
||||||
|
val firstRatio = ratios.firstOrNull { it > 0f } ?: 1f
|
||||||
|
val baseHeight = screenWidth / firstRatio
|
||||||
|
if (screenWidth > screenHeight) {
|
||||||
|
((screenHeight - 32f) / baseHeight).coerceAtMost(1f)
|
||||||
|
} else {
|
||||||
|
1f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val zoomAnimatable = remember { Animatable(fitZoom) }
|
||||||
|
val panXAnimatable = remember { Animatable(if ((screenWidth * fitZoom) < screenWidth) (screenWidth - (screenWidth * fitZoom)) / 2f else 0f) }
|
||||||
val panYAnimatable = remember { Animatable(0f) }
|
val panYAnimatable = remember { Animatable(0f) }
|
||||||
|
|
||||||
var previousLayoutPages by remember { mutableStateOf<List<PdfPageLayout>?>(null) }
|
var previousScreenWidth by remember { mutableFloatStateOf(0f) }
|
||||||
|
LaunchedEffect(screenWidth, screenHeight) {
|
||||||
|
if (previousScreenWidth > 0f && previousScreenWidth != screenWidth) {
|
||||||
|
if (zoomAnimatable.value <= 1.1f) {
|
||||||
|
val centeredX = if ((screenWidth * fitZoom) < screenWidth) {
|
||||||
|
(screenWidth - (screenWidth * fitZoom)) / 2f
|
||||||
|
} else 0f
|
||||||
|
|
||||||
|
zoomAnimatable.snapTo(fitZoom)
|
||||||
|
panXAnimatable.snapTo(centeredX)
|
||||||
|
onZoomChange(fitZoom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previousScreenWidth = screenWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
var isInitialLayout by remember { mutableStateOf(true) }
|
||||||
val currentScaleProvider = remember(zoomAnimatable) { { zoomAnimatable.value } }
|
val currentScaleProvider = remember(zoomAnimatable) { { zoomAnimatable.value } }
|
||||||
|
|
||||||
SideEffect {
|
LaunchedEffect(layoutState.pages) {
|
||||||
val prevPages = previousLayoutPages
|
if (!isInitialLayout) {
|
||||||
val currentPages = layoutState.pages
|
val targetPageIdx = state.currentPage
|
||||||
|
val newLayout = layoutState.pages
|
||||||
|
val pageLayout = newLayout.getOrNull(targetPageIdx)
|
||||||
|
|
||||||
if (prevPages != null && prevPages.size == currentPages.size) {
|
if (pageLayout != null) {
|
||||||
val anchorIndex = state.firstVisiblePage.coerceIn(currentPages.indices)
|
|
||||||
val oldY = prevPages[anchorIndex].y
|
|
||||||
val newY = currentPages[anchorIndex].y
|
|
||||||
val delta = newY - oldY
|
|
||||||
|
|
||||||
if (abs(delta) > 0.1f) {
|
|
||||||
val currentZoom = zoomAnimatable.value
|
val currentZoom = zoomAnimatable.value
|
||||||
val shiftInScreenPixels = delta * currentZoom
|
val targetPanY = headerHeightPx - (pageLayout.y * currentZoom)
|
||||||
val targetPanY = panYAnimatable.value - shiftInScreenPixels
|
val zoomedDocHeight = layoutState.totalHeight * currentZoom
|
||||||
|
val minPanY = (screenHeight - footerHeightPx - zoomedDocHeight).coerceAtMost(headerHeightPx)
|
||||||
|
val finalPanY = targetPanY.coerceIn(minPanY, headerHeightPx)
|
||||||
|
|
||||||
scope.launch { panYAnimatable.snapTo(targetPanY) }
|
Timber.tag("PdfZoomDiagnostics").i("Layout changed (Orientation/Size). Snapping to Page $targetPageIdx at PanY: $finalPanY")
|
||||||
|
panYAnimatable.snapTo(finalPanY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
previousLayoutPages = currentPages
|
isInitialLayout = false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clampValues(
|
fun clampValues(
|
||||||
targetZoom: Float, targetPanX: Float, targetPanY: Float
|
targetZoom: Float, targetPanX: Float, targetPanY: Float
|
||||||
): Triple<Float, Float, Float> {
|
): Triple<Float, Float, Float> {
|
||||||
val constrainedZoom = targetZoom.coerceIn(1f, 5f)
|
val constrainedZoom = targetZoom.coerceIn(fitZoom, 5f)
|
||||||
val zoomedDocWidth = screenWidth * constrainedZoom
|
val zoomedDocWidth = screenWidth * constrainedZoom
|
||||||
val zoomedDocHeight = totalDocHeight * constrainedZoom
|
val zoomedDocHeight = totalDocHeight * constrainedZoom
|
||||||
|
|
||||||
|
val constrainedX = if (zoomedDocWidth < screenWidth) {
|
||||||
|
(screenWidth - zoomedDocWidth) / 2f
|
||||||
|
} else {
|
||||||
val maxPanX = 0f
|
val maxPanX = 0f
|
||||||
val minPanX = -(zoomedDocWidth - screenWidth).coerceAtLeast(0f)
|
val minPanX = -(zoomedDocWidth - screenWidth)
|
||||||
|
targetPanX.coerceIn(minPanX, maxPanX)
|
||||||
val minPanY = (screenHeight - footerHeightPx - zoomedDocHeight).coerceAtMost(
|
|
||||||
headerHeightPx
|
|
||||||
)
|
|
||||||
|
|
||||||
val constrainedX = targetPanX.coerceIn(minPanX, maxPanX)
|
|
||||||
val constrainedY = targetPanY.coerceIn(minPanY, headerHeightPx)
|
|
||||||
|
|
||||||
if (constrainedZoom > 1.01f) {
|
|
||||||
Timber.tag("PdfZoomIssue").v(
|
|
||||||
"Clamp: Zoom=$constrainedZoom, targetY=$targetPanY, finalY=$constrainedY, " +
|
|
||||||
"boundsY=[$minPanY, $headerHeightPx], zoomedHeight=$zoomedDocHeight"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val minPanY = if (zoomedDocHeight < (screenHeight - headerHeightPx - footerHeightPx)) {
|
||||||
|
headerHeightPx
|
||||||
|
} else {
|
||||||
|
(screenHeight - footerHeightPx - zoomedDocHeight).coerceAtMost(headerHeightPx)
|
||||||
|
}
|
||||||
|
|
||||||
|
val constrainedY = targetPanY.coerceIn(minPanY, headerHeightPx)
|
||||||
|
|
||||||
return Triple(constrainedZoom, constrainedX, constrainedY)
|
return Triple(constrainedZoom, constrainedX, constrainedY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -629,6 +650,7 @@ internal fun PdfVerticalReader(
|
||||||
|
|
||||||
val currentZoom = zoomAnimatable.value
|
val currentZoom = zoomAnimatable.value
|
||||||
val zoomedDocHeight = totalDocHeight * currentZoom
|
val zoomedDocHeight = totalDocHeight * currentZoom
|
||||||
|
val zoomedDocWidth = screenWidth * currentZoom
|
||||||
|
|
||||||
val isAnimating = zoomAnimatable.isRunning || panYAnimatable.isRunning || panXAnimatable.isRunning
|
val isAnimating = zoomAnimatable.isRunning || panYAnimatable.isRunning || panXAnimatable.isRunning
|
||||||
|
|
||||||
|
|
@ -637,11 +659,21 @@ internal fun PdfVerticalReader(
|
||||||
val extraScrollForIme = if (isTextEditing) imeBottom.toFloat() else 0f
|
val extraScrollForIme = if (isTextEditing) imeBottom.toFloat() else 0f
|
||||||
|
|
||||||
val minPanY = (screenHeight - effectiveFooterPx - zoomedDocHeight - extraScrollForIme).coerceAtMost(headerHeightPx)
|
val minPanY = (screenHeight - effectiveFooterPx - zoomedDocHeight - extraScrollForIme).coerceAtMost(headerHeightPx)
|
||||||
val minPanX = -(screenWidth * currentZoom - screenWidth).coerceAtLeast(0f)
|
|
||||||
|
val minPanX: Float
|
||||||
|
val maxPanX: Float
|
||||||
|
if (zoomedDocWidth < screenWidth) {
|
||||||
|
val centeredX = (screenWidth - zoomedDocWidth) / 2f
|
||||||
|
minPanX = centeredX
|
||||||
|
maxPanX = centeredX
|
||||||
|
} else {
|
||||||
|
minPanX = -(zoomedDocWidth - screenWidth)
|
||||||
|
maxPanX = 0f
|
||||||
|
}
|
||||||
|
|
||||||
if (!isAnimating) {
|
if (!isAnimating) {
|
||||||
panYAnimatable.updateBounds(lowerBound = minPanY, upperBound = headerHeightPx)
|
panYAnimatable.updateBounds(lowerBound = minPanY, upperBound = headerHeightPx)
|
||||||
panXAnimatable.updateBounds(lowerBound = minPanX, upperBound = 0f)
|
panXAnimatable.updateBounds(lowerBound = minPanX, upperBound = maxPanX)
|
||||||
} else {
|
} else {
|
||||||
panYAnimatable.updateBounds(
|
panYAnimatable.updateBounds(
|
||||||
lowerBound = minOf(panYAnimatable.lowerBound ?: minPanY, minPanY),
|
lowerBound = minOf(panYAnimatable.lowerBound ?: minPanY, minPanY),
|
||||||
|
|
@ -649,7 +681,7 @@ internal fun PdfVerticalReader(
|
||||||
)
|
)
|
||||||
panXAnimatable.updateBounds(
|
panXAnimatable.updateBounds(
|
||||||
lowerBound = minOf(panXAnimatable.lowerBound ?: minPanX, minPanX),
|
lowerBound = minOf(panXAnimatable.lowerBound ?: minPanX, minPanX),
|
||||||
upperBound = 0f
|
upperBound = maxOf(panXAnimatable.upperBound ?: maxPanX, maxPanX)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -706,7 +738,12 @@ internal fun PdfVerticalReader(
|
||||||
|
|
||||||
val onDoubleTapToZoom: (Offset) -> Unit = { tapScreenOffset ->
|
val onDoubleTapToZoom: (Offset) -> Unit = { tapScreenOffset ->
|
||||||
val currentZoom = zoomAnimatable.value
|
val currentZoom = zoomAnimatable.value
|
||||||
val targetZoom = if (currentZoom < 1.1f) 2.5f else 1f
|
|
||||||
|
val targetZoom = when {
|
||||||
|
currentZoom < 0.95f -> 1f
|
||||||
|
currentZoom < 2.45f -> 2.5f
|
||||||
|
else -> fitZoom
|
||||||
|
}
|
||||||
|
|
||||||
val startPanX = panXAnimatable.value
|
val startPanX = panXAnimatable.value
|
||||||
val startPanY = panYAnimatable.value
|
val startPanY = panYAnimatable.value
|
||||||
|
|
@ -719,46 +756,41 @@ internal fun PdfVerticalReader(
|
||||||
val pivotContentX = (tapScreenOffset.x - startPanX) / currentZoom
|
val pivotContentX = (tapScreenOffset.x - startPanX) / currentZoom
|
||||||
val pivotContentY = (tapScreenOffset.y - startPanY) / currentZoom
|
val pivotContentY = (tapScreenOffset.y - startPanY) / currentZoom
|
||||||
|
|
||||||
val durationMillis = 400L
|
val rawNextPanX = tapScreenOffset.x - (pivotContentX * targetZoom)
|
||||||
val startTimeNanos = withFrameNanos { it }
|
val rawNextPanY = tapScreenOffset.y - (pivotContentY * targetZoom)
|
||||||
val durationNanos = durationMillis * 1_000_000L
|
|
||||||
|
|
||||||
while (true) {
|
val (finalZoom, finalX, finalY) = clampCamera(targetZoom, rawNextPanX, rawNextPanY)
|
||||||
val now = withFrameNanos { it }
|
|
||||||
val elapsedNanos = now - startTimeNanos
|
|
||||||
val progress = (elapsedNanos.toFloat() / durationNanos).coerceIn(0f, 1f)
|
|
||||||
val easedProgress = FastOutSlowInEasing.transform(progress)
|
|
||||||
|
|
||||||
val nextZoom = androidx.compose.ui.util.lerp(currentZoom, targetZoom, easedProgress)
|
|
||||||
|
|
||||||
val rawNextPanX = tapScreenOffset.x - (pivotContentX * nextZoom)
|
|
||||||
val rawNextPanY = tapScreenOffset.y - (pivotContentY * nextZoom)
|
|
||||||
|
|
||||||
val (clampedZoom, clampedX, clampedY) = clampCamera(nextZoom, rawNextPanX, rawNextPanY)
|
|
||||||
|
|
||||||
panXAnimatable.updateBounds(
|
panXAnimatable.updateBounds(
|
||||||
lowerBound = minOf(panXAnimatable.lowerBound ?: clampedX, clampedX),
|
lowerBound = minOf(panXAnimatable.lowerBound ?: finalX, finalX, startPanX),
|
||||||
upperBound = maxOf(panXAnimatable.upperBound ?: clampedX, clampedX)
|
upperBound = maxOf(panXAnimatable.upperBound ?: finalX, finalX, startPanX)
|
||||||
)
|
)
|
||||||
panYAnimatable.updateBounds(
|
panYAnimatable.updateBounds(
|
||||||
lowerBound = minOf(panYAnimatable.lowerBound ?: clampedY, clampedY),
|
lowerBound = minOf(panYAnimatable.lowerBound ?: finalY, finalY, startPanY),
|
||||||
upperBound = maxOf(panYAnimatable.upperBound ?: clampedY, clampedY)
|
upperBound = maxOf(panYAnimatable.upperBound ?: finalY, finalY, startPanY)
|
||||||
)
|
)
|
||||||
|
|
||||||
zoomAnimatable.snapTo(clampedZoom)
|
coroutineScope {
|
||||||
panXAnimatable.snapTo(clampedX)
|
launch { zoomAnimatable.animateTo(finalZoom, animationSpec = tween(400, easing = FastOutSlowInEasing)) }
|
||||||
panYAnimatable.snapTo(clampedY)
|
launch { panXAnimatable.animateTo(finalX, animationSpec = tween(400, easing = FastOutSlowInEasing)) }
|
||||||
|
launch { panYAnimatable.animateTo(finalY, animationSpec = tween(400, easing = FastOutSlowInEasing)) }
|
||||||
if (progress >= 1f) break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onZoomChange(zoomAnimatable.value)
|
onZoomChange(zoomAnimatable.value)
|
||||||
|
|
||||||
val finalZoom = zoomAnimatable.value
|
val zoomedDocWidth = screenWidth * finalZoom
|
||||||
panXAnimatable.updateBounds(
|
val finalMinX: Float
|
||||||
lowerBound = -(screenWidth * finalZoom - screenWidth).coerceAtLeast(0f),
|
val finalMaxX: Float
|
||||||
upperBound = 0f
|
if (zoomedDocWidth < screenWidth) {
|
||||||
)
|
val centeredX = (screenWidth - zoomedDocWidth) / 2f
|
||||||
|
finalMinX = centeredX
|
||||||
|
finalMaxX = centeredX
|
||||||
|
} else {
|
||||||
|
finalMinX = -(zoomedDocWidth - screenWidth)
|
||||||
|
finalMaxX = 0f
|
||||||
|
}
|
||||||
|
panXAnimatable.updateBounds(lowerBound = finalMinX, upperBound = finalMaxX)
|
||||||
|
|
||||||
val zDocH = totalDocHeight * finalZoom
|
val zDocH = totalDocHeight * finalZoom
|
||||||
val minScrollY = (screenHeight - footerHeightPx - zDocH).coerceAtMost(headerHeightPx)
|
val minScrollY = (screenHeight - footerHeightPx - zDocH).coerceAtMost(headerHeightPx)
|
||||||
panYAnimatable.updateBounds(lowerBound = minScrollY, upperBound = headerHeightPx)
|
panYAnimatable.updateBounds(lowerBound = minScrollY, upperBound = headerHeightPx)
|
||||||
|
|
@ -1032,7 +1064,7 @@ internal fun PdfVerticalReader(
|
||||||
|
|
||||||
val oldZoom = accumulatedZoom
|
val oldZoom = accumulatedZoom
|
||||||
val rawTargetZoom = oldZoom * effectiveZoomChange
|
val rawTargetZoom = oldZoom * effectiveZoomChange
|
||||||
val constrainedZoom = rawTargetZoom.coerceIn(1f, 5f)
|
val constrainedZoom = rawTargetZoom.coerceIn(fitZoom, 5f)
|
||||||
|
|
||||||
val prevCentroid = centroid - panChange
|
val prevCentroid = centroid - panChange
|
||||||
val contentPivotX = (prevCentroid.x - accumulatedPanX) / oldZoom
|
val contentPivotX = (prevCentroid.x - accumulatedPanX) / oldZoom
|
||||||
|
|
@ -1046,13 +1078,6 @@ internal fun PdfVerticalReader(
|
||||||
val rawNewPanX = centroid.x - (contentPivotX * constrainedZoom)
|
val rawNewPanX = centroid.x - (contentPivotX * constrainedZoom)
|
||||||
val rawNewPanY = centroid.y - (contentPivotY * constrainedZoom)
|
val rawNewPanY = centroid.y - (contentPivotY * constrainedZoom)
|
||||||
|
|
||||||
if (effectiveZoomChange > 1.0f) {
|
|
||||||
Timber.tag("PdfZoomIssue").d(
|
|
||||||
"PinchIn FIXED: ZoomFactor=$effectiveZoomChange, CentroidY=${centroid.y}, " +
|
|
||||||
"OldPanY=$accumulatedPanY, ResultRawPanY=$rawNewPanY"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val (finalZoom, finalX, finalY) = clampCamera(
|
val (finalZoom, finalX, finalY) = clampCamera(
|
||||||
constrainedZoom, rawNewPanX, rawNewPanY
|
constrainedZoom, rawNewPanX, rawNewPanY
|
||||||
)
|
)
|
||||||
|
|
@ -1103,7 +1128,7 @@ internal fun PdfVerticalReader(
|
||||||
scope.launch {
|
scope.launch {
|
||||||
isFlinging = true
|
isFlinging = true
|
||||||
try {
|
try {
|
||||||
if (accumulatedZoom !in 1f..5f) {
|
if (accumulatedZoom !in fitZoom..5f) {
|
||||||
zoomAnimatable.animateTo(
|
zoomAnimatable.animateTo(
|
||||||
finalZoom, animationSpec = tween(300)
|
finalZoom, animationSpec = tween(300)
|
||||||
)
|
)
|
||||||
|
|
@ -1111,8 +1136,18 @@ internal fun PdfVerticalReader(
|
||||||
onZoomChange(zoomAnimatable.targetValue)
|
onZoomChange(zoomAnimatable.targetValue)
|
||||||
val zoomedDocWidth = screenWidth * finalZoom
|
val zoomedDocWidth = screenWidth * finalZoom
|
||||||
val zoomedDocHeight = totalDocHeight * finalZoom
|
val zoomedDocHeight = totalDocHeight * finalZoom
|
||||||
val maxPanX = 0f
|
|
||||||
val minPanX = -(zoomedDocWidth - screenWidth).coerceAtLeast(0f)
|
val flingMinX: Float
|
||||||
|
val flingMaxX: Float
|
||||||
|
if (zoomedDocWidth < screenWidth) {
|
||||||
|
val centeredX = (screenWidth - zoomedDocWidth) / 2f
|
||||||
|
flingMinX = centeredX
|
||||||
|
flingMaxX = centeredX
|
||||||
|
} else {
|
||||||
|
flingMinX = -(zoomedDocWidth - screenWidth)
|
||||||
|
flingMaxX = 0f
|
||||||
|
}
|
||||||
|
|
||||||
val minPanY =
|
val minPanY =
|
||||||
(screenHeight - footerHeightPx - zoomedDocHeight).coerceAtMost(
|
(screenHeight - footerHeightPx - zoomedDocHeight).coerceAtMost(
|
||||||
headerHeightPx
|
headerHeightPx
|
||||||
|
|
@ -1121,11 +1156,9 @@ internal fun PdfVerticalReader(
|
||||||
Timber.tag(SCROLL_BOUNDS_TAG)
|
Timber.tag(SCROLL_BOUNDS_TAG)
|
||||||
.d("- totalDocHeight: $totalDocHeight, zoom: $finalZoom -> zoomedDocHeight: $zoomedDocHeight")
|
.d("- totalDocHeight: $totalDocHeight, zoom: $finalZoom -> zoomedDocHeight: $zoomedDocHeight")
|
||||||
Timber.tag(SCROLL_BOUNDS_TAG)
|
Timber.tag(SCROLL_BOUNDS_TAG)
|
||||||
.d("- Fling bounds set to Y: [$minPanY, $headerHeightPx]")
|
.d("- Fling bounds set to Y:[$minPanY, $headerHeightPx]")
|
||||||
panXAnimatable.updateBounds(minPanX, maxPanX)
|
panXAnimatable.updateBounds(flingMinX, flingMaxX)
|
||||||
panYAnimatable.updateBounds(
|
panYAnimatable.updateBounds(minPanY, headerHeightPx)
|
||||||
minPanY, headerHeightPx
|
|
||||||
)
|
|
||||||
|
|
||||||
coroutineScope {
|
coroutineScope {
|
||||||
launch {
|
launch {
|
||||||
|
|
|
||||||
|
|
@ -2147,8 +2147,6 @@ fun PdfViewerScreen(
|
||||||
Timber.tag("PdfPositionDebug").i("UI: Restoration Start | Target: $targetPage | Mode: $displayMode | Total: $pageCount")
|
Timber.tag("PdfPositionDebug").i("UI: Restoration Start | Target: $targetPage | Mode: $displayMode | Total: $pageCount")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
delay(200)
|
|
||||||
|
|
||||||
when (displayMode) {
|
when (displayMode) {
|
||||||
DisplayMode.PAGINATION -> {
|
DisplayMode.PAGINATION -> {
|
||||||
if (pagerState.currentPage != targetPage) {
|
if (pagerState.currentPage != targetPage) {
|
||||||
|
|
@ -2157,14 +2155,11 @@ fun PdfViewerScreen(
|
||||||
initialScrollDone = true
|
initialScrollDone = true
|
||||||
}
|
}
|
||||||
DisplayMode.VERTICAL_SCROLL -> {
|
DisplayMode.VERTICAL_SCROLL -> {
|
||||||
var retries = 0
|
while (verticalReaderState.snapToPageHandler == null) {
|
||||||
while (verticalReaderState.snapToPageHandler == null && retries < 20) {
|
delay(16)
|
||||||
delay(50)
|
|
||||||
retries++
|
|
||||||
}
|
}
|
||||||
Timber.tag("PdfPositionDebug").d("UI: Executing Vertical snapToPage($targetPage) after $retries retries")
|
Timber.tag("PdfPositionDebug").d("UI: Executing Vertical snapToPage($targetPage)")
|
||||||
verticalReaderState.snapToPage(targetPage)
|
verticalReaderState.snapToPage(targetPage)
|
||||||
delay(100)
|
|
||||||
initialScrollDone = true
|
initialScrollDone = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue