@june24/expo-pdf-reader 0.1.19 → 0.1.21
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.
|
@@ -89,6 +89,7 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
89
89
|
private val onTextPress = ViewEvent<Map<String, Any>>("onTextPress", this, null)
|
|
90
90
|
|
|
91
91
|
private var pageHeights = mutableListOf<Int>()
|
|
92
|
+
private var rowHeights = mutableListOf<Int>()
|
|
92
93
|
private var pageWidthsPdf = mutableListOf<Float>()
|
|
93
94
|
private var pageHeightsPdf = mutableListOf<Float>()
|
|
94
95
|
private var pageViews = mutableListOf<ImageView?>()
|
|
@@ -96,8 +97,8 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
96
97
|
private var lastEmittedPageIndex = -1
|
|
97
98
|
private var totalPageCount = 0
|
|
98
99
|
|
|
99
|
-
private val renderWindowBefore =
|
|
100
|
-
private val renderWindowAfter =
|
|
100
|
+
private val renderWindowBefore = 20
|
|
101
|
+
private val renderWindowAfter = 25
|
|
101
102
|
|
|
102
103
|
// Annotation state
|
|
103
104
|
private val pageAnnotations = mutableListOf<MutableList<Annotation>>()
|
|
@@ -552,11 +553,38 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
552
553
|
notifyAnnotationChange()
|
|
553
554
|
}
|
|
554
555
|
|
|
556
|
+
private fun isTwoUpMode(): Boolean = displayMode == "twoUp" || displayMode == "twoUpContinuous"
|
|
557
|
+
|
|
558
|
+
private fun marginBetweenPages(): Int = if (displayMode == "single") 0 else 16
|
|
559
|
+
|
|
560
|
+
private fun getFrameForPage(pageIndex: Int): FrameLayout? {
|
|
561
|
+
if (pageIndex !in pageHeights.indices) return null
|
|
562
|
+
return if (isTwoUpMode()) {
|
|
563
|
+
val row = pageIndex / 2
|
|
564
|
+
val col = pageIndex % 2
|
|
565
|
+
if (row >= container.childCount) null
|
|
566
|
+
else (container.getChildAt(row) as? LinearLayout)?.getChildAt(col) as? FrameLayout
|
|
567
|
+
} else {
|
|
568
|
+
container.getChildAt(pageIndex) as? FrameLayout
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
555
572
|
private fun scrollToPage(pageIndex: Int) {
|
|
556
573
|
if (pageHeights.isEmpty()) return
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
574
|
+
val idx = pageIndex.coerceIn(0, pageHeights.size - 1)
|
|
575
|
+
val gap = marginBetweenPages()
|
|
576
|
+
val offset = if (isTwoUpMode() && rowHeights.isNotEmpty()) {
|
|
577
|
+
var sum = 0
|
|
578
|
+
for (r in 0 until idx / 2) {
|
|
579
|
+
sum += rowHeights[r] + gap
|
|
580
|
+
}
|
|
581
|
+
sum
|
|
582
|
+
} else {
|
|
583
|
+
var sum = 0
|
|
584
|
+
for (i in 0 until idx) {
|
|
585
|
+
sum += pageHeights[i] + gap
|
|
586
|
+
}
|
|
587
|
+
sum
|
|
560
588
|
}
|
|
561
589
|
scrollView.post { scrollView.smoothScrollTo(0, offset) }
|
|
562
590
|
}
|
|
@@ -596,6 +624,7 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
596
624
|
fileDescriptor?.close()
|
|
597
625
|
fileDescriptor = null
|
|
598
626
|
pageHeights.clear()
|
|
627
|
+
rowHeights.clear()
|
|
599
628
|
pageWidthsPdf.clear()
|
|
600
629
|
pageHeightsPdf.clear()
|
|
601
630
|
pageViews.clear()
|
|
@@ -630,15 +659,19 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
630
659
|
updateVisiblePages()
|
|
631
660
|
return
|
|
632
661
|
}
|
|
662
|
+
val viewWidth = width.coerceAtLeast(1)
|
|
663
|
+
val isTwoUp = displayMode == "twoUp" || displayMode == "twoUpContinuous"
|
|
664
|
+
val effectiveWidth = if (isTwoUp) viewWidth / 2 else viewWidth
|
|
633
665
|
scope.launch {
|
|
634
|
-
val w =
|
|
666
|
+
val w = effectiveWidth
|
|
635
667
|
val result = withContext(Dispatchers.Default) {
|
|
636
668
|
(0 until renderer.pageCount).map { i ->
|
|
637
669
|
val page = renderer.openPage(i)
|
|
638
670
|
try {
|
|
671
|
+
val pageH = (w.toFloat() * page.height / page.width).toInt()
|
|
639
672
|
Triple(
|
|
640
673
|
i,
|
|
641
|
-
|
|
674
|
+
pageH,
|
|
642
675
|
Pair(page.width.toFloat(), page.height.toFloat())
|
|
643
676
|
)
|
|
644
677
|
} finally {
|
|
@@ -649,6 +682,7 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
649
682
|
if (!isActive) return@launch
|
|
650
683
|
withContext(Dispatchers.Main) {
|
|
651
684
|
pageHeights.clear()
|
|
685
|
+
rowHeights.clear()
|
|
652
686
|
pageWidthsPdf.clear()
|
|
653
687
|
pageHeightsPdf.clear()
|
|
654
688
|
for ((_, h, pdfSize) in result) {
|
|
@@ -656,6 +690,14 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
656
690
|
pageWidthsPdf.add(pdfSize.first)
|
|
657
691
|
pageHeightsPdf.add(pdfSize.second)
|
|
658
692
|
}
|
|
693
|
+
if (isTwoUp) {
|
|
694
|
+
val rowCount = (renderer.pageCount + 1) / 2
|
|
695
|
+
for (r in 0 until rowCount) {
|
|
696
|
+
val h0 = pageHeights.getOrElse(2 * r) { 0 }
|
|
697
|
+
val h1 = pageHeights.getOrElse(2 * r + 1) { 0 }
|
|
698
|
+
rowHeights.add(maxOf(h0, h1))
|
|
699
|
+
}
|
|
700
|
+
}
|
|
659
701
|
ensurePlaceholders(renderer)
|
|
660
702
|
scrollToPage(initialPage.coerceIn(0, (renderer.pageCount - 1).coerceAtLeast(0)))
|
|
661
703
|
updateVisiblePages()
|
|
@@ -666,38 +708,85 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
666
708
|
private fun ensurePlaceholders(renderer: PdfRenderer) {
|
|
667
709
|
container.removeAllViews()
|
|
668
710
|
val pageCount = renderer.pageCount
|
|
711
|
+
val marginBetween = marginBetweenPages()
|
|
669
712
|
pageViews = MutableList(pageCount) { null }
|
|
670
713
|
overlayViews = MutableList(pageCount) { null }
|
|
671
714
|
while (pageAnnotations.size < pageCount) {
|
|
672
715
|
pageAnnotations.add(mutableListOf())
|
|
673
716
|
}
|
|
674
|
-
|
|
675
|
-
val
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
717
|
+
if (isTwoUpMode() && rowHeights.isNotEmpty()) {
|
|
718
|
+
val rowCount = rowHeights.size
|
|
719
|
+
for (r in 0 until rowCount) {
|
|
720
|
+
val rowLayout = LinearLayout(context).apply {
|
|
721
|
+
orientation = LinearLayout.HORIZONTAL
|
|
722
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
723
|
+
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
724
|
+
rowHeights[r]
|
|
725
|
+
).apply { setMargins(0, 0, 0, marginBetween) }
|
|
726
|
+
}
|
|
727
|
+
for (col in 0..1) {
|
|
728
|
+
val i = 2 * r + col
|
|
729
|
+
if (i >= pageCount) break
|
|
730
|
+
val frame = FrameLayout(context).apply {
|
|
731
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
732
|
+
0,
|
|
733
|
+
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
734
|
+
1f
|
|
735
|
+
).apply { setMargins(0, 0, if (col == 0) 8 else 0, 0) }
|
|
736
|
+
setBackgroundColor(Color.LTGRAY)
|
|
737
|
+
}
|
|
738
|
+
val overlay = AnnotationOverlayView(context, i).apply {
|
|
739
|
+
layoutParams = FrameLayout.LayoutParams(
|
|
740
|
+
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
741
|
+
FrameLayout.LayoutParams.MATCH_PARENT
|
|
742
|
+
)
|
|
743
|
+
}
|
|
744
|
+
frame.addView(overlay)
|
|
745
|
+
rowLayout.addView(frame)
|
|
746
|
+
overlayViews[i] = overlay
|
|
747
|
+
}
|
|
748
|
+
container.addView(rowLayout)
|
|
681
749
|
}
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
750
|
+
} else {
|
|
751
|
+
for (i in 0 until pageCount) {
|
|
752
|
+
val frame = FrameLayout(context).apply {
|
|
753
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
754
|
+
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
755
|
+
pageHeights[i]
|
|
756
|
+
).apply { setMargins(0, 0, 0, marginBetween) }
|
|
757
|
+
setBackgroundColor(Color.LTGRAY)
|
|
758
|
+
}
|
|
759
|
+
val overlay = AnnotationOverlayView(context, i).apply {
|
|
760
|
+
layoutParams = FrameLayout.LayoutParams(
|
|
761
|
+
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
762
|
+
FrameLayout.LayoutParams.MATCH_PARENT
|
|
763
|
+
)
|
|
764
|
+
}
|
|
765
|
+
frame.addView(overlay)
|
|
766
|
+
container.addView(frame)
|
|
767
|
+
overlayViews[i] = overlay
|
|
687
768
|
}
|
|
688
|
-
frame.addView(overlay)
|
|
689
|
-
container.addView(frame)
|
|
690
|
-
overlayViews[i] = overlay
|
|
691
769
|
}
|
|
692
770
|
}
|
|
693
771
|
|
|
694
772
|
private fun currentPageFromScroll(): Int {
|
|
695
773
|
if (pageHeights.isEmpty()) return 0
|
|
696
774
|
val scrollY = scrollView.scrollY
|
|
775
|
+
val gap = marginBetweenPages()
|
|
776
|
+
if (isTwoUpMode() && rowHeights.isNotEmpty()) {
|
|
777
|
+
var offset = 0
|
|
778
|
+
for (r in rowHeights.indices) {
|
|
779
|
+
val rowH = rowHeights[r]
|
|
780
|
+
if (scrollY < offset + rowH / 2) return (2 * r).coerceAtMost(pageHeights.size - 1)
|
|
781
|
+
if (scrollY < offset + rowH) return (2 * r + 1).coerceAtMost(pageHeights.size - 1)
|
|
782
|
+
offset += rowH + gap
|
|
783
|
+
}
|
|
784
|
+
return (pageHeights.size - 1).coerceAtLeast(0)
|
|
785
|
+
}
|
|
697
786
|
var offset = 0
|
|
698
787
|
for (i in pageHeights.indices) {
|
|
699
788
|
if (scrollY < offset + pageHeights[i] / 2) return i
|
|
700
|
-
offset += pageHeights[i] +
|
|
789
|
+
offset += pageHeights[i] + gap
|
|
701
790
|
}
|
|
702
791
|
return (pageHeights.size - 1).coerceAtLeast(0)
|
|
703
792
|
}
|
|
@@ -711,7 +800,7 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
711
800
|
for (i in pageViews.indices) {
|
|
712
801
|
if (i in from..to) continue
|
|
713
802
|
val iv = pageViews.getOrNull(i) ?: continue
|
|
714
|
-
val frame =
|
|
803
|
+
val frame = getFrameForPage(i) ?: continue
|
|
715
804
|
val bmp = (iv.drawable as? BitmapDrawable)?.bitmap
|
|
716
805
|
iv.setImageBitmap(null)
|
|
717
806
|
bmp?.recycle()
|
|
@@ -728,11 +817,10 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
728
817
|
|
|
729
818
|
private fun renderPageToView(pageIndex: Int) {
|
|
730
819
|
val renderer = pdfRenderer ?: return
|
|
731
|
-
val frame =
|
|
732
|
-
// Frame always has overlay; only skip if we already have an ImageView for this page
|
|
820
|
+
val frame = getFrameForPage(pageIndex) ?: return
|
|
733
821
|
if (pageViews.getOrNull(pageIndex) != null) return
|
|
734
822
|
val page = renderer.openPage(pageIndex)
|
|
735
|
-
val w = width.coerceAtLeast(1)
|
|
823
|
+
val w = if (isTwoUpMode()) (width / 2).coerceAtLeast(1) else width.coerceAtLeast(1)
|
|
736
824
|
val h = pageHeights[pageIndex]
|
|
737
825
|
val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
|
|
738
826
|
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
|
|
@@ -754,17 +842,7 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
754
842
|
|
|
755
843
|
private fun notifyPageChange() {
|
|
756
844
|
if (pageHeights.isEmpty()) return
|
|
757
|
-
val
|
|
758
|
-
var offset = 0
|
|
759
|
-
var detectedPage = 0
|
|
760
|
-
for (i in pageHeights.indices) {
|
|
761
|
-
if (scrollY < offset + pageHeights[i] / 2) {
|
|
762
|
-
detectedPage = i
|
|
763
|
-
break
|
|
764
|
-
}
|
|
765
|
-
offset += pageHeights[i] + 16
|
|
766
|
-
detectedPage = i
|
|
767
|
-
}
|
|
845
|
+
val detectedPage = currentPageFromScroll()
|
|
768
846
|
if (detectedPage != lastEmittedPageIndex) {
|
|
769
847
|
lastEmittedPageIndex = detectedPage
|
|
770
848
|
onPageChange(mapOf(
|
package/package.json
CHANGED