@june24/expo-pdf-reader 0.1.28 → 0.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -145,11 +145,17 @@ class ExpoPdfReaderView(
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
/**
|
|
148
|
-
* continuous / twoup / twoupcontinuous — pinch
|
|
149
|
-
*
|
|
148
|
+
* continuous / twoup / twoupcontinuous — pinch + zoom хийсэн үед pan (хөндлөн/босоо),
|
|
149
|
+
* scroll-ийг идэвхгүй болгоно. Zoom = 1 үед хэвийн босоо scroll.
|
|
150
150
|
*/
|
|
151
151
|
private inner class ZoomableScrollView(ctx: Context) : ScrollView(ctx) {
|
|
152
152
|
|
|
153
|
+
private var panX = 0f
|
|
154
|
+
private var panY = 0f
|
|
155
|
+
|
|
156
|
+
private fun isZoomedForPan(): Boolean =
|
|
157
|
+
activeTool == null && currentZoom > 1.02f
|
|
158
|
+
|
|
153
159
|
private val pinch = ScaleGestureDetector(
|
|
154
160
|
ctx,
|
|
155
161
|
object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
|
@@ -181,6 +187,9 @@ class ExpoPdfReaderView(
|
|
|
181
187
|
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
|
|
182
188
|
if (activeTool != null) return super.onInterceptTouchEvent(ev)
|
|
183
189
|
if (ev.pointerCount > 1 || pinch.isInProgress) return false
|
|
190
|
+
if (isZoomedForPan() && ev.actionMasked == MotionEvent.ACTION_DOWN) {
|
|
191
|
+
return true
|
|
192
|
+
}
|
|
184
193
|
return super.onInterceptTouchEvent(ev)
|
|
185
194
|
}
|
|
186
195
|
|
|
@@ -205,11 +214,42 @@ class ExpoPdfReaderView(
|
|
|
205
214
|
|
|
206
215
|
override fun onTouchEvent(ev: MotionEvent): Boolean {
|
|
207
216
|
if (activeTool != null) return super.onTouchEvent(ev)
|
|
217
|
+
|
|
208
218
|
if (pinch.isInProgress || ev.pointerCount > 1) {
|
|
209
219
|
return true
|
|
210
220
|
}
|
|
221
|
+
|
|
222
|
+
if (isZoomedForPan()) {
|
|
223
|
+
when (ev.actionMasked) {
|
|
224
|
+
MotionEvent.ACTION_DOWN -> {
|
|
225
|
+
stopNestedScroll()
|
|
226
|
+
panX = ev.x
|
|
227
|
+
panY = ev.y
|
|
228
|
+
}
|
|
229
|
+
MotionEvent.ACTION_MOVE -> {
|
|
230
|
+
container.translationX += ev.x - panX
|
|
231
|
+
container.translationY += ev.y - panY
|
|
232
|
+
panX = ev.x
|
|
233
|
+
panY = ev.y
|
|
234
|
+
clampContainerTranslationsInPlace()
|
|
235
|
+
}
|
|
236
|
+
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { }
|
|
237
|
+
}
|
|
238
|
+
return true
|
|
239
|
+
}
|
|
240
|
+
|
|
211
241
|
return super.onTouchEvent(ev)
|
|
212
242
|
}
|
|
243
|
+
|
|
244
|
+
override fun canScrollVertically(direction: Int): Boolean {
|
|
245
|
+
if (isZoomedForPan()) return false
|
|
246
|
+
return super.canScrollVertically(direction)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
override fun canScrollHorizontally(direction: Int): Boolean {
|
|
250
|
+
if (isZoomedForPan()) return false
|
|
251
|
+
return super.canScrollHorizontally(direction)
|
|
252
|
+
}
|
|
213
253
|
}
|
|
214
254
|
|
|
215
255
|
// ── UI ───────────────────────────────────────────────────────────────────
|
|
@@ -287,6 +327,7 @@ class ExpoPdfReaderView(
|
|
|
287
327
|
private fun reflowForHostWidthChange() {
|
|
288
328
|
val w = width.takeIf { it > 0 } ?: return
|
|
289
329
|
if (renderer == null) return
|
|
330
|
+
if (w <= 0) return
|
|
290
331
|
if (lastHostWidthForPdf > 0 && kotlin.math.abs(w - lastHostWidthForPdf) <= 4) return
|
|
291
332
|
lastHostWidthForPdf = w
|
|
292
333
|
currentViewWidth = w
|
|
@@ -923,7 +964,7 @@ class ExpoPdfReaderView(
|
|
|
923
964
|
private suspend fun renderTwoUpRange(
|
|
924
965
|
pdf: PdfRenderer, pageCount: Int, viewWidth: Int, startPage: Int, endPage: Int
|
|
925
966
|
) {
|
|
926
|
-
val halfWidth = viewWidth / 2
|
|
967
|
+
val halfWidth = (viewWidth / 2).coerceAtLeast(1)
|
|
927
968
|
var i = startPage
|
|
928
969
|
while (i < endPage) {
|
|
929
970
|
val leftBmp = renderPageBitmap(pdf, i, halfWidth)
|
|
@@ -987,12 +1028,21 @@ class ExpoPdfReaderView(
|
|
|
987
1028
|
}
|
|
988
1029
|
}
|
|
989
1030
|
|
|
1031
|
+
private fun resolveViewWidthForRender(): Int {
|
|
1032
|
+
val w = when {
|
|
1033
|
+
currentViewWidth > 0 -> currentViewWidth
|
|
1034
|
+
width > 0 -> width
|
|
1035
|
+
else -> resources.displayMetrics.widthPixels
|
|
1036
|
+
}
|
|
1037
|
+
return w.coerceAtLeast(1)
|
|
1038
|
+
}
|
|
1039
|
+
|
|
990
1040
|
private suspend fun loadNextChunk() {
|
|
991
1041
|
val pdf = renderer ?: return
|
|
992
1042
|
val start = renderedUpTo + 1
|
|
993
1043
|
if (start >= totalPages) return
|
|
994
1044
|
val end = minOf(start + PAGE_CHUNK, totalPages)
|
|
995
|
-
val viewWidth =
|
|
1045
|
+
val viewWidth = resolveViewWidthForRender()
|
|
996
1046
|
|
|
997
1047
|
withContext(Dispatchers.Main) { removeLoadingFooter() }
|
|
998
1048
|
|
|
@@ -1055,7 +1105,7 @@ class ExpoPdfReaderView(
|
|
|
1055
1105
|
val prevStart = maxOf(0, windowStart - PAGE_CHUNK)
|
|
1056
1106
|
val prevEnd = windowStart
|
|
1057
1107
|
if (prevStart >= prevEnd) return
|
|
1058
|
-
val viewWidth =
|
|
1108
|
+
val viewWidth = resolveViewWidthForRender()
|
|
1059
1109
|
|
|
1060
1110
|
data class PageBmp(val bmp: Bitmap, val idx: Int, val pdfW: Float, val pdfH: Float)
|
|
1061
1111
|
val pages = mutableListOf<PageBmp>()
|
|
@@ -1092,8 +1142,8 @@ class ExpoPdfReaderView(
|
|
|
1092
1142
|
val prevStart = maxOf(0, windowStart - PAGE_CHUNK)
|
|
1093
1143
|
val prevEnd = windowStart
|
|
1094
1144
|
if (prevStart >= prevEnd) return
|
|
1095
|
-
val viewWidth =
|
|
1096
|
-
val halfW = viewWidth / 2
|
|
1145
|
+
val viewWidth = resolveViewWidthForRender()
|
|
1146
|
+
val halfW = (viewWidth / 2).coerceAtLeast(1)
|
|
1097
1147
|
|
|
1098
1148
|
data class RowBmps(val leftIdx: Int, val leftBmp: Bitmap, val rightBmp: Bitmap?)
|
|
1099
1149
|
val rows = mutableListOf<RowBmps>()
|
|
@@ -1229,7 +1279,7 @@ class ExpoPdfReaderView(
|
|
|
1229
1279
|
*/
|
|
1230
1280
|
private fun jumpToPage(targetPage: Int) {
|
|
1231
1281
|
val pdf = renderer ?: return
|
|
1232
|
-
val viewWidth =
|
|
1282
|
+
val viewWidth = resolveViewWidthForRender()
|
|
1233
1283
|
renderJob?.cancel()
|
|
1234
1284
|
renderJob = scope.launch {
|
|
1235
1285
|
try {
|
|
@@ -1348,14 +1398,15 @@ class ExpoPdfReaderView(
|
|
|
1348
1398
|
|
|
1349
1399
|
private suspend fun renderPageBitmap(pdf: PdfRenderer, index: Int, targetWidth: Int): Bitmap =
|
|
1350
1400
|
withContext(pdfDispatcher) {
|
|
1401
|
+
val safeWidth = targetWidth.coerceAtLeast(1)
|
|
1351
1402
|
pdf.openPage(index).use { page ->
|
|
1352
1403
|
if (index < pagePdfW.size) {
|
|
1353
1404
|
pagePdfW[index] = page.width
|
|
1354
1405
|
pagePdfH[index] = page.height
|
|
1355
1406
|
}
|
|
1356
|
-
val s =
|
|
1407
|
+
val s = safeWidth.toFloat() / page.width.toFloat()
|
|
1357
1408
|
val h = (page.height * s).toInt().coerceAtLeast(1)
|
|
1358
|
-
val bmp = Bitmap.createBitmap(
|
|
1409
|
+
val bmp = Bitmap.createBitmap(safeWidth, h, Bitmap.Config.ARGB_8888)
|
|
1359
1410
|
bmp.eraseColor(Color.WHITE)
|
|
1360
1411
|
page.render(bmp, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
|
|
1361
1412
|
bmp
|
|
@@ -1446,7 +1497,18 @@ class ExpoPdfReaderView(
|
|
|
1446
1497
|
|
|
1447
1498
|
holder.loadJob = scope.launch {
|
|
1448
1499
|
val pdf = renderer ?: return@launch
|
|
1449
|
-
val
|
|
1500
|
+
val viewWidth = this@ExpoPdfReaderView.width
|
|
1501
|
+
if (viewWidth <= 0) {
|
|
1502
|
+
withContext(Dispatchers.Main) {
|
|
1503
|
+
post {
|
|
1504
|
+
if (holder.boundPage == position && this@ExpoPdfReaderView.width > 0) {
|
|
1505
|
+
notifyItemChanged(position)
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
return@launch
|
|
1510
|
+
}
|
|
1511
|
+
val bmp = renderPageBitmap(pdf, position, viewWidth)
|
|
1450
1512
|
val pdfW = pagePdfW.getOrElse(position) { 1 }.toFloat()
|
|
1451
1513
|
val pdfH = pagePdfH.getOrElse(position) { 1 }.toFloat()
|
|
1452
1514
|
withContext(Dispatchers.Main) {
|
package/package.json
CHANGED