diff --git a/CHANGELOG.md b/CHANGELOG.md
index dbee53f8..7652d133 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+## 3.2.0-beta.1 (2019-08-18)
+* Merge PR #714 with optimized page load
+* Merge PR #776 with fix for max & min zoom level
+* Merge PR #722 with fix for showing right position when view size changed
+* Merge PR #703 with fix for too many threads
+* Merge PR #702 with fix for memory leak
+* Merge PR #689 with possibility to disable long click
+* Merge PR #628 with fix for hiding scroll handle
+* Merge PR #627 with `fitEachPage` option
+* Merge PR #638 and #406 with fixed NPE
+* Merge PR #780 with README fix
+* Update compile SDK and support library to 28
+* Update Gradle and Gradle Plugin
+
## 3.1.0-beta.1 (2018-06-29)
* Merge pull request #557 for snapping pages (scrolling page by page)
* merge pull request #618 for night mode
diff --git a/README.md b/README.md
index 3575eaea..812c6e9d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
+# Change of ownership and looking for contributors!
+
+The ownership of the project was recently changed and we are actively looking for contributors to bring the project back to track. Please [visit](https://github.com/DImuthuUpe/AndroidPdfViewer/issues/1186)
# Android PdfViewer
@@ -10,14 +13,19 @@ Library for displaying PDF documents on Android, with `animations`, `gestures`,
It is based on [PdfiumAndroid](https://github.com/barteksc/PdfiumAndroid) for decoding PDF files. Works on API 11 (Android 3.0) and higher.
Licensed under Apache License 2.0.
-## What's new in 3.1.0-beta.1?
-* Merge pull request #557 for snapping pages (scrolling page by page)
-* merge pull request #618 for night mode
-* Merge pull request #566 for `OnLongTapListener`
-* Update PdfiumAndroid to 1.9.0, which uses `c++_shared` instead of `gnustl_static`
-* Update Gradle Plugin
-* Update compile SDK and support library to 26
-* Change minimum SDK to 14
+## What's new in 3.2.0-beta.1?
+* Merge PR #714 with optimized page load
+* Merge PR #776 with fix for max & min zoom level
+* Merge PR #722 with fix for showing right position when view size changed
+* Merge PR #703 with fix for too many threads
+* Merge PR #702 with fix for memory leak
+* Merge PR #689 with possibility to disable long click
+* Merge PR #628 with fix for hiding scroll handle
+* Merge PR #627 with `fitEachPage` option
+* Merge PR #638 and #406 with fixed NPE
+* Merge PR #780 with README fix
+* Update compile SDK and support library to 28
+* Update Gradle and Gradle Plugin
## Changes in 3.0 API
* Replaced `Contants.PRELOAD_COUNT` with `PRELOAD_OFFSET`
@@ -30,11 +38,11 @@ Licensed under Apache License 2.0.
Add to _build.gradle_:
-`compile 'com.github.barteksc:android-pdf-viewer:3.1.0-beta.1'`
+`implementation 'com.github.barteksc:android-pdf-viewer:3.2.0-beta.1'`
or if you want to use more stable version:
-`compile 'com.github.barteksc:android-pdf-viewer:2.8.2'`
+`implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'`
Library is available in jcenter repository, probably it'll be in Maven Central soon.
@@ -95,8 +103,9 @@ pdfView.fromAsset(String)
.spacing(0)
.autoSpacing(false) // add dynamic spacing to fit each page on its own on the screen
.linkHandler(DefaultLinkHandler)
- .pageFitPolicy(FitPolicy.WIDTH)
- .pageSnap(true) // snap pages to screen boundaries
+ .pageFitPolicy(FitPolicy.WIDTH) // mode to fit pages in the view
+ .fitEachPage(false) // fit each page to the view, else smaller pages are scaled relative to largest page.
+ .pageSnap(false) // snap pages to screen boundaries
.pageFling(false) // make a fling change only a single page like ViewPager
.nightMode(false) // toggle night mode
.load();
diff --git a/android-pdf-viewer/bintray.gradle b/android-pdf-viewer/bintray.gradle
new file mode 100644
index 00000000..9a01f197
--- /dev/null
+++ b/android-pdf-viewer/bintray.gradle
@@ -0,0 +1,89 @@
+apply plugin: 'com.github.dcendents.android-maven'
+apply plugin: 'com.jfrog.bintray'
+
+group = publishedGroupId
+version = libraryVersion
+
+install {
+ repositories.mavenInstaller {
+ pom.project {
+ packaging 'aar'
+ groupId publishedGroupId
+ artifactId artifact
+
+ name libraryName
+ description libraryDescription
+ url siteUrl
+
+ licenses {
+ license {
+ name licenseName
+ url licenseUrl
+ }
+ }
+ developers {
+ developer {
+ id developerId
+ name developerName
+ email developerEmail
+ }
+ }
+ scm {
+ connection gitUrl
+ developerConnection gitUrl
+ url siteUrl
+ }
+ }
+ }
+}
+
+task sourcesJar(type: Jar) {
+ classifier = 'sources'
+ from android.sourceSets.main.java.srcDirs
+}
+
+task javadoc(type: Javadoc) {
+ source = android.sourceSets.main.java.srcDirs
+ classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
+}
+
+afterEvaluate {
+ javadoc.classpath += files(android.libraryVariants.collect { variant ->
+ variant.javaCompileProvider.get().classpath.files
+ })
+}
+
+task javadocJar(type: Jar, dependsOn: javadoc) {
+ classifier = 'javadoc'
+ from javadoc.destinationDir
+}
+
+artifacts {
+ archives javadocJar
+ archives sourcesJar
+}
+
+Properties properties = new Properties()
+properties.load(project.rootProject.file('local.properties').newDataInputStream())
+
+bintray {
+ user = properties.getProperty("bintray.user")
+ key = properties.getProperty("bintray.apikey")
+
+ configurations = ['archives']
+ pkg {
+ repo = bintrayRepo
+ name = bintrayName
+ desc = libraryDescription
+ websiteUrl = siteUrl
+ vcsUrl = gitUrl
+ licenses = allLicenses
+ dryRun = false
+ publish = true
+ override = false
+ publicDownloadNumbers = true
+ version {
+ desc = libraryDescription
+ }
+ }
+}
\ No newline at end of file
diff --git a/android-pdf-viewer/build.gradle b/android-pdf-viewer/build.gradle
index 784ac639..32d03665 100644
--- a/android-pdf-viewer/build.gradle
+++ b/android-pdf-viewer/build.gradle
@@ -13,7 +13,7 @@ ext {
siteUrl = 'https://github.com/barteksc/AndroidPdfViewer'
gitUrl = 'https://github.com/barteksc/AndroidPdfViewer.git'
- libraryVersion = '3.1.0-beta.1'
+ libraryVersion = '3.2.0-beta.1'
developerId = 'barteksc'
developerName = 'Bartosz Schiller'
@@ -25,21 +25,20 @@ ext {
}
android {
- compileSdkVersion 26
+ compileSdkVersion 28
defaultConfig {
minSdkVersion 14
- targetSdkVersion 26
+ targetSdkVersion 28
versionCode 1
- versionName "3.1.0-beta.1"
+ versionName "3.2.0-beta.1"
}
}
dependencies {
- implementation 'com.android.support:support-compat:26.1.0'
+ implementation 'com.android.support:support-compat:28.0.0'
api 'com.github.barteksc:pdfium-android:1.9.0'
}
-apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle'
-apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle'
\ No newline at end of file
+apply from: 'bintray.gradle'
\ No newline at end of file
diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/AnimationManager.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/AnimationManager.java
index 67ab7f3b..e7e9439f 100644
--- a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/AnimationManager.java
+++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/AnimationManager.java
@@ -138,12 +138,14 @@ public void onAnimationUpdate(ValueAnimator animation) {
public void onAnimationCancel(Animator animation) {
pdfView.loadPages();
pageFlinging = false;
+ hideHandle();
}
@Override
public void onAnimationEnd(Animator animation) {
pdfView.loadPages();
pageFlinging = false;
+ hideHandle();
}
}
@@ -160,12 +162,14 @@ public void onAnimationUpdate(ValueAnimator animation) {
public void onAnimationCancel(Animator animation) {
pdfView.loadPages();
pageFlinging = false;
+ hideHandle();
}
@Override
public void onAnimationEnd(Animator animation) {
pdfView.loadPages();
pageFlinging = false;
+ hideHandle();
}
}
@@ -187,13 +191,15 @@ public void onAnimationUpdate(ValueAnimator animation) {
@Override
public void onAnimationCancel(Animator animation) {
+ pdfView.loadPages();
+ hideHandle();
}
@Override
public void onAnimationEnd(Animator animation) {
pdfView.loadPages();
- hideHandle();
pdfView.performPageSnap();
+ hideHandle();
}
@Override
diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/DecodingAsyncTask.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/DecodingAsyncTask.java
index a28974ba..24292ac9 100644
--- a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/DecodingAsyncTask.java
+++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/DecodingAsyncTask.java
@@ -1,77 +1,89 @@
-/**
- * Copyright 2016 Bartosz Schiller
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.github.barteksc.pdfviewer;
-
-import android.os.AsyncTask;
-
-import com.github.barteksc.pdfviewer.source.DocumentSource;
-import com.shockwave.pdfium.PdfDocument;
-import com.shockwave.pdfium.PdfiumCore;
-import com.shockwave.pdfium.util.Size;
-
-class DecodingAsyncTask extends AsyncTask {
-
- private boolean cancelled;
-
- private PDFView pdfView;
-
- private PdfiumCore pdfiumCore;
- private String password;
- private DocumentSource docSource;
- private int[] userPages;
- private PdfFile pdfFile;
-
- DecodingAsyncTask(DocumentSource docSource, String password, int[] userPages, PDFView pdfView, PdfiumCore pdfiumCore) {
- this.docSource = docSource;
- this.userPages = userPages;
- this.cancelled = false;
- this.pdfView = pdfView;
- this.password = password;
- this.pdfiumCore = pdfiumCore;
- }
-
- @Override
- protected Throwable doInBackground(Void... params) {
- try {
- PdfDocument pdfDocument = docSource.createDocument(pdfView.getContext(), pdfiumCore, password);
- pdfFile = new PdfFile(pdfiumCore, pdfDocument, pdfView.getPageFitPolicy(), getViewSize(),
- userPages, pdfView.isSwipeVertical(), pdfView.getSpacingPx(), pdfView.doAutoSpacing());
- return null;
- } catch (Throwable t) {
- return t;
- }
- }
-
- private Size getViewSize() {
- return new Size(pdfView.getWidth(), pdfView.getHeight());
- }
-
- @Override
- protected void onPostExecute(Throwable t) {
- if (t != null) {
- pdfView.loadError(t);
- return;
- }
- if (!cancelled) {
- pdfView.loadComplete(pdfFile);
- }
- }
-
- @Override
- protected void onCancelled() {
- cancelled = true;
- }
-}
+/**
+ * Copyright 2016 Bartosz Schiller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.barteksc.pdfviewer;
+
+import android.os.AsyncTask;
+
+import com.github.barteksc.pdfviewer.source.DocumentSource;
+import com.shockwave.pdfium.PdfDocument;
+import com.shockwave.pdfium.PdfiumCore;
+import com.shockwave.pdfium.util.Size;
+
+import java.lang.ref.WeakReference;
+
+class DecodingAsyncTask extends AsyncTask {
+
+ private boolean cancelled;
+
+ private WeakReference pdfViewReference;
+
+ private PdfiumCore pdfiumCore;
+ private String password;
+ private DocumentSource docSource;
+ private int[] userPages;
+ private PdfFile pdfFile;
+
+ DecodingAsyncTask(DocumentSource docSource, String password, int[] userPages, PDFView pdfView, PdfiumCore pdfiumCore) {
+ this.docSource = docSource;
+ this.userPages = userPages;
+ this.cancelled = false;
+ this.pdfViewReference = new WeakReference<>(pdfView);
+ this.password = password;
+ this.pdfiumCore = pdfiumCore;
+ }
+
+ @Override
+ protected Throwable doInBackground(Void... params) {
+ try {
+ PDFView pdfView = pdfViewReference.get();
+ if (pdfView != null) {
+ PdfDocument pdfDocument = docSource.createDocument(pdfView.getContext(), pdfiumCore, password);
+ pdfFile = new PdfFile(pdfiumCore, pdfDocument, pdfView.getPageFitPolicy(), getViewSize(pdfView),
+ userPages, pdfView.isSwipeVertical(), pdfView.getSpacingPx(), pdfView.isAutoSpacingEnabled(),
+ pdfView.isFitEachPage());
+ return null;
+ } else {
+ return new NullPointerException("pdfView == null");
+ }
+
+ } catch (Throwable t) {
+ return t;
+ }
+ }
+
+ private Size getViewSize(PDFView pdfView) {
+ return new Size(pdfView.getWidth(), pdfView.getHeight());
+ }
+
+ @Override
+ protected void onPostExecute(Throwable t) {
+ PDFView pdfView = pdfViewReference.get();
+ if (pdfView != null) {
+ if (t != null) {
+ pdfView.loadError(t);
+ return;
+ }
+ if (!cancelled) {
+ pdfView.loadComplete(pdfFile);
+ }
+ }
+ }
+
+ @Override
+ protected void onCancelled() {
+ cancelled = true;
+ }
+}
diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/DragPinchManager.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/DragPinchManager.java
index fa7fc33a..3860bc73 100644
--- a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/DragPinchManager.java
+++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/DragPinchManager.java
@@ -63,6 +63,10 @@ void disable() {
enabled = false;
}
+ void disableLongpress(){
+ gestureDetector.setIsLongpressEnabled(false);
+ }
+
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
boolean onTapHandled = pdfView.callbacks.callOnTap(e);
@@ -83,6 +87,9 @@ public boolean onSingleTapConfirmed(MotionEvent e) {
private boolean checkLinkTapped(float x, float y) {
PdfFile pdfFile = pdfView.pdfFile;
+ if (pdfFile == null) {
+ return false;
+ }
float mappedX = -pdfView.getCurrentXOffset() + x;
float mappedY = -pdfView.getCurrentYOffset() + y;
int page = pdfFile.getPageAtOffset(pdfView.isSwipeVertical() ? mappedY : mappedX, pdfView.getZoom());
@@ -197,7 +204,7 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve
if (!pdfView.isSwipeEnabled()) {
return false;
}
- if (pdfView.doPageFling()) {
+ if (pdfView.isPageFlingEnabled()) {
if (pdfView.pageFillsScreen()) {
onBoundedFling(velocityX, velocityY);
} else {
@@ -253,10 +260,12 @@ private void onBoundedFling(float velocityX, float velocityY) {
public boolean onScale(ScaleGestureDetector detector) {
float dr = detector.getScaleFactor();
float wantedZoom = pdfView.getZoom() * dr;
- if (wantedZoom < MINIMUM_ZOOM) {
- dr = MINIMUM_ZOOM / pdfView.getZoom();
- } else if (wantedZoom > MAXIMUM_ZOOM) {
- dr = MAXIMUM_ZOOM / pdfView.getZoom();
+ float minZoom = Math.min(MINIMUM_ZOOM, pdfView.getMinZoom());
+ float maxZoom = Math.min(MAXIMUM_ZOOM, pdfView.getMaxZoom());
+ if (wantedZoom < minZoom) {
+ dr = minZoom / pdfView.getZoom();
+ } else if (wantedZoom > maxZoom) {
+ dr = maxZoom / pdfView.getZoom();
}
pdfView.zoomCenteredRelativeTo(dr, new PointF(detector.getFocusX(), detector.getFocusY()));
return true;
diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PDFView.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PDFView.java
index 5e9636e7..b8374721 100644
--- a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PDFView.java
+++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PDFView.java
@@ -30,6 +30,7 @@
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.HandlerThread;
import android.util.AttributeSet;
import android.util.Log;
@@ -154,7 +155,7 @@ enum ScrollDir {
private DecodingAsyncTask decodingAsyncTask;
/** The thread {@link #renderingHandler} will run on */
- private final HandlerThread renderingHandlerThread;
+ private HandlerThread renderingHandlerThread;
/** Handler always waiting in the background and rendering tasks */
RenderingHandler renderingHandler;
@@ -171,6 +172,8 @@ enum ScrollDir {
/** Policy for fitting pages to screen */
private FitPolicy pageFitPolicy = FitPolicy.WIDTH;
+ private boolean fitEachPage = false;
+
private int defaultPage = 0;
/** True if should scroll through pages vertically instead of horizontally */
@@ -462,6 +465,14 @@ public void computeScroll() {
@Override
protected void onDetachedFromWindow() {
recycle();
+ if (renderingHandlerThread != null) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ renderingHandlerThread.quitSafely();
+ } else {
+ renderingHandlerThread.quit();
+ }
+ renderingHandlerThread = null;
+ }
super.onDetachedFromWindow();
}
@@ -474,13 +485,33 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (isInEditMode() || state != State.SHOWN) {
return;
}
+
+ // calculates the position of the point which in the center of view relative to big strip
+ float centerPointInStripXOffset = -currentXOffset + oldw * 0.5f;
+ float centerPointInStripYOffset = -currentYOffset + oldh * 0.5f;
+
+ float relativeCenterPointInStripXOffset;
+ float relativeCenterPointInStripYOffset;
+
+ if (swipeVertical){
+ relativeCenterPointInStripXOffset = centerPointInStripXOffset / pdfFile.getMaxPageWidth();
+ relativeCenterPointInStripYOffset = centerPointInStripYOffset / pdfFile.getDocLen(zoom);
+ }else {
+ relativeCenterPointInStripXOffset = centerPointInStripXOffset / pdfFile.getDocLen(zoom);
+ relativeCenterPointInStripYOffset = centerPointInStripYOffset / pdfFile.getMaxPageHeight();
+ }
+
animationManager.stopAll();
pdfFile.recalculatePageSizes(new Size(w, h));
+
if (swipeVertical) {
- moveTo(currentXOffset, -pdfFile.getPageOffset(currentPage, zoom));
- } else {
- moveTo(-pdfFile.getPageOffset(currentPage, zoom), currentYOffset);
+ currentXOffset = -relativeCenterPointInStripXOffset * pdfFile.getMaxPageWidth() + w * 0.5f;
+ currentYOffset = -relativeCenterPointInStripYOffset * pdfFile.getDocLen(zoom) + h * 0.5f ;
+ }else {
+ currentXOffset = -relativeCenterPointInStripXOffset * pdfFile.getDocLen(zoom) + w * 0.5f;
+ currentYOffset = -relativeCenterPointInStripYOffset * pdfFile.getMaxPageHeight() + h * 0.5f;
}
+ moveTo(currentXOffset,currentYOffset);
loadPageByOffset();
}
@@ -1184,7 +1215,7 @@ public int getSpacingPx() {
return spacingPx;
}
- public boolean doAutoSpacing() {
+ public boolean isAutoSpacingEnabled() {
return autoSpacing;
}
@@ -1192,12 +1223,12 @@ public void setPageFling(boolean pageFling) {
this.pageFling = pageFling;
}
- public boolean doPageFling() {
+ public boolean isPageFlingEnabled() {
return pageFling;
}
- private void setSpacing(int spacing) {
- this.spacingPx = Util.getDP(getContext(), spacing);
+ private void setSpacing(int spacingDp) {
+ this.spacingPx = Util.getDP(getContext(), spacingDp);
}
private void setAutoSpacing(boolean autoSpacing) {
@@ -1212,7 +1243,15 @@ public FitPolicy getPageFitPolicy() {
return pageFitPolicy;
}
- public boolean doPageSnap() {
+ private void setFitEachPage(boolean fitEachPage) {
+ this.fitEachPage = fitEachPage;
+ }
+
+ public boolean isFitEachPage() {
+ return fitEachPage;
+ }
+
+ public boolean isPageSnap() {
return pageSnap;
}
@@ -1330,6 +1369,8 @@ public class Configurator {
private FitPolicy pageFitPolicy = FitPolicy.WIDTH;
+ private boolean fitEachPage = false;
+
private boolean pageFling = false;
private boolean pageSnap = false;
@@ -1455,6 +1496,11 @@ public Configurator pageFitPolicy(FitPolicy pageFitPolicy) {
return this;
}
+ public Configurator fitEachPage(boolean fitEachPage) {
+ this.fitEachPage = fitEachPage;
+ return this;
+ }
+
public Configurator pageSnap(boolean pageSnap) {
this.pageSnap = pageSnap;
return this;
@@ -1470,6 +1516,11 @@ public Configurator nightMode(boolean nightMode) {
return this;
}
+ public Configurator disableLongpress() {
+ PDFView.this.dragPinchManager.disableLongpress();
+ return this;
+ }
+
public void load() {
if (!hasSize) {
waitingDocumentConfigurator = this;
@@ -1498,6 +1549,7 @@ public void load() {
PDFView.this.setSpacing(spacing);
PDFView.this.setAutoSpacing(autoSpacing);
PDFView.this.setPageFitPolicy(pageFitPolicy);
+ PDFView.this.setFitEachPage(fitEachPage);
PDFView.this.setPageSnap(pageSnap);
PDFView.this.setPageFling(pageFling);
diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PagesLoader.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PagesLoader.java
index bd7cf098..26c30f4b 100644
--- a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PagesLoader.java
+++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PagesLoader.java
@@ -22,6 +22,9 @@
import com.github.barteksc.pdfviewer.util.Util;
import com.shockwave.pdfium.util.SizeF;
+import java.util.LinkedList;
+import java.util.List;
+
import static com.github.barteksc.pdfviewer.util.Constants.Cache.CACHE_SIZE;
import static com.github.barteksc.pdfviewer.util.Constants.PRELOAD_OFFSET;
@@ -37,21 +40,55 @@ class PagesLoader {
private float partRenderHeight;
private final RectF thumbnailRect = new RectF(0, 0, 1, 1);
private final int preloadOffset;
- private final Holder firstHolder = new Holder();
- private final Holder lastHolder = new Holder();
- private final GridSize firstGrid = new GridSize();
- private final GridSize lastGrid = new GridSize();
- private final GridSize middleGrid = new GridSize();
private class Holder {
- int page;
int row;
int col;
+
+ @Override
+ public String toString() {
+ return "Holder{" +
+ "row=" + row +
+ ", col=" + col +
+ '}';
+ }
+ }
+
+ private class RenderRange {
+ int page;
+ GridSize gridSize;
+ Holder leftTop;
+ Holder rightBottom;
+
+ RenderRange() {
+ this.page = 0;
+ this.gridSize = new GridSize();
+ this.leftTop = new Holder();
+ this.rightBottom = new Holder();
+ }
+
+ @Override
+ public String toString() {
+ return "RenderRange{" +
+ "page=" + page +
+ ", gridSize=" + gridSize +
+ ", leftTop=" + leftTop +
+ ", rightBottom=" + rightBottom +
+ '}';
+ }
}
private class GridSize {
int rows;
int cols;
+
+ @Override
+ public String toString() {
+ return "GridSize{" +
+ "rows=" + rows +
+ ", cols=" + cols +
+ '}';
+ }
}
PagesLoader(PDFView pdfView) {
@@ -69,36 +106,6 @@ private void getPageColsRows(GridSize grid, int pageIndex) {
grid.cols = MathUtils.ceil(1f / partWidth);
}
- private Holder getPageAndCoordsByOffset(Holder holder, GridSize grid, float localXOffset,
- float localYOffset, boolean endOffset) {
- float fixedXOffset = -MathUtils.max(localXOffset, 0);
- float fixedYOffset = -MathUtils.max(localYOffset, 0);
- float offset = pdfView.isSwipeVertical() ? fixedYOffset : fixedXOffset;
- holder.page = pdfView.pdfFile.getPageAtOffset(offset, pdfView.getZoom());
- getPageColsRows(grid, holder.page);
- SizeF scaledPageSize = pdfView.pdfFile.getScaledPageSize(holder.page, pdfView.getZoom());
- float rowHeight = scaledPageSize.getHeight() / grid.rows;
- float colWidth = scaledPageSize.getWidth() / grid.cols;
- float row, col;
- float secondaryOffset = pdfView.pdfFile.getSecondaryPageOffset(holder.page, pdfView.getZoom());
- if (pdfView.isSwipeVertical()) {
- row = Math.abs(fixedYOffset - pdfView.pdfFile.getPageOffset(holder.page, pdfView.getZoom())) / rowHeight;
- col = MathUtils.min(fixedXOffset - secondaryOffset, 0) / colWidth;
- } else {
- col = Math.abs(fixedXOffset - pdfView.pdfFile.getPageOffset(holder.page, pdfView.getZoom())) / colWidth;
- row = MathUtils.min(fixedYOffset - secondaryOffset, 0) / rowHeight;
- }
-
- if (endOffset) {
- holder.row = MathUtils.ceil(row);
- holder.col = MathUtils.ceil(col);
- } else {
- holder.row = MathUtils.floor(row);
- holder.col = MathUtils.floor(col);
- }
- return holder;
- }
-
private void calculatePartSize(GridSize grid) {
pageRelativePartWidth = 1f / (float) grid.cols;
pageRelativePartHeight = 1f / (float) grid.rows;
@@ -106,87 +113,137 @@ private void calculatePartSize(GridSize grid) {
partRenderHeight = Constants.PART_SIZE / pageRelativePartHeight;
}
- private void loadVisible() {
- int parts = 0;
- float scaledPreloadOffset = preloadOffset * pdfView.getZoom();
- float firstXOffset = -xOffset + scaledPreloadOffset;
- float lastXOffset = -xOffset - pdfView.getWidth() - scaledPreloadOffset;
- float firstYOffset = -yOffset + scaledPreloadOffset;
- float lastYOffset = -yOffset - pdfView.getHeight() - scaledPreloadOffset;
- getPageAndCoordsByOffset(firstHolder, firstGrid, firstXOffset, firstYOffset, false);
- getPageAndCoordsByOffset(lastHolder, lastGrid, lastXOffset, lastYOffset, true);
+ /**
+ * calculate the render range of each page
+ */
+ private List getRenderRangeList(float firstXOffset, float firstYOffset, float lastXOffset, float lastYOffset) {
+
+ float fixedFirstXOffset = -MathUtils.max(firstXOffset, 0);
+ float fixedFirstYOffset = -MathUtils.max(firstYOffset, 0);
+
+ float fixedLastXOffset = -MathUtils.max(lastXOffset, 0);
+ float fixedLastYOffset = -MathUtils.max(lastYOffset, 0);
+
+ float offsetFirst = pdfView.isSwipeVertical() ? fixedFirstYOffset : fixedFirstXOffset;
+ float offsetLast = pdfView.isSwipeVertical() ? fixedLastYOffset : fixedLastXOffset;
+
+ int firstPage = pdfView.pdfFile.getPageAtOffset(offsetFirst, pdfView.getZoom());
+ int lastPage = pdfView.pdfFile.getPageAtOffset(offsetLast, pdfView.getZoom());
+ int pageCount = lastPage - firstPage + 1;
+
+ List renderRanges = new LinkedList<>();
+
+ for (int page = firstPage; page <= lastPage; page++) {
+ RenderRange range = new RenderRange();
+ range.page = page;
+
+ float pageFirstXOffset, pageFirstYOffset, pageLastXOffset, pageLastYOffset;
+ if (page == firstPage) {
+ pageFirstXOffset = fixedFirstXOffset;
+ pageFirstYOffset = fixedFirstYOffset;
+ if (pageCount == 1) {
+ pageLastXOffset = fixedLastXOffset;
+ pageLastYOffset = fixedLastYOffset;
+ } else {
+ float pageOffset = pdfView.pdfFile.getPageOffset(page, pdfView.getZoom());
+ SizeF pageSize = pdfView.pdfFile.getScaledPageSize(page, pdfView.getZoom());
+ if (pdfView.isSwipeVertical()) {
+ pageLastXOffset = fixedLastXOffset;
+ pageLastYOffset = pageOffset + pageSize.getHeight();
+ } else {
+ pageLastYOffset = fixedLastYOffset;
+ pageLastXOffset = pageOffset + pageSize.getWidth();
+ }
+ }
+ } else if (page == lastPage) {
+ float pageOffset = pdfView.pdfFile.getPageOffset(page, pdfView.getZoom());
+
+ if (pdfView.isSwipeVertical()) {
+ pageFirstXOffset = fixedFirstXOffset;
+ pageFirstYOffset = pageOffset;
+ } else {
+ pageFirstYOffset = fixedFirstYOffset;
+ pageFirstXOffset = pageOffset;
+ }
- for (int i = firstHolder.page; i <= lastHolder.page; i++) {
- loadThumbnail(i);
- }
+ pageLastXOffset = fixedLastXOffset;
+ pageLastYOffset = fixedLastYOffset;
- int pagesCount = lastHolder.page - firstHolder.page + 1;
- for (int page = firstHolder.page; page <= lastHolder.page && parts < CACHE_SIZE; page++) {
+ } else {
+ float pageOffset = pdfView.pdfFile.getPageOffset(page, pdfView.getZoom());
+ SizeF pageSize = pdfView.pdfFile.getScaledPageSize(page, pdfView.getZoom());
+ if (pdfView.isSwipeVertical()) {
+ pageFirstXOffset = fixedFirstXOffset;
+ pageFirstYOffset = pageOffset;
+
+ pageLastXOffset = fixedLastXOffset;
+ pageLastYOffset = pageOffset + pageSize.getHeight();
+ } else {
+ pageFirstXOffset = pageOffset;
+ pageFirstYOffset = fixedFirstYOffset;
+
+ pageLastXOffset = pageOffset + pageSize.getWidth();
+ pageLastYOffset = fixedLastYOffset;
+ }
+ }
+
+ getPageColsRows(range.gridSize, range.page); // get the page's grid size that rows and cols
+ SizeF scaledPageSize = pdfView.pdfFile.getScaledPageSize(range.page, pdfView.getZoom());
+ float rowHeight = scaledPageSize.getHeight() / range.gridSize.rows;
+ float colWidth = scaledPageSize.getWidth() / range.gridSize.cols;
+
+
+ // get the page offset int the whole file
+ // ---------------------------------------
+ // | | | |
+ // |<--offset-->| (page) |<--offset-->|
+ // | | | |
+ // | | | |
+ // ---------------------------------------
+ float secondaryOffset = pdfView.pdfFile.getSecondaryPageOffset(page, pdfView.getZoom());
+
+ // calculate the row,col of the point in the leftTop and rightBottom
+ if (pdfView.isSwipeVertical()) {
+ range.leftTop.row = MathUtils.floor(Math.abs(pageFirstYOffset - pdfView.pdfFile.getPageOffset(range.page, pdfView.getZoom())) / rowHeight);
+ range.leftTop.col = MathUtils.floor(MathUtils.min(pageFirstXOffset - secondaryOffset, 0) / colWidth);
- if (page == firstHolder.page && pagesCount > 1) {
- parts += loadPageEnd(firstHolder, firstGrid, CACHE_SIZE - parts);
- } else if (page == lastHolder.page && pagesCount > 1) {
- parts += loadPageStart(lastHolder, lastGrid, CACHE_SIZE - parts);
- } else if(pagesCount == 1) {
- parts += loadPageCenter(firstHolder, lastHolder, firstGrid, CACHE_SIZE - parts);
+ range.rightBottom.row = MathUtils.ceil(Math.abs(pageLastYOffset - pdfView.pdfFile.getPageOffset(range.page, pdfView.getZoom())) / rowHeight);
+ range.rightBottom.col = MathUtils.floor(MathUtils.min(pageLastXOffset - secondaryOffset, 0) / colWidth);
} else {
- getPageColsRows(middleGrid, page);
- parts += loadWholePage(page, middleGrid, CACHE_SIZE - parts);
+ range.leftTop.col = MathUtils.floor(Math.abs(pageFirstXOffset - pdfView.pdfFile.getPageOffset(range.page, pdfView.getZoom())) / colWidth);
+ range.leftTop.row = MathUtils.floor(MathUtils.min(pageFirstYOffset - secondaryOffset, 0) / rowHeight);
+
+ range.rightBottom.col = MathUtils.floor(Math.abs(pageLastXOffset - pdfView.pdfFile.getPageOffset(range.page, pdfView.getZoom())) / colWidth);
+ range.rightBottom.row = MathUtils.floor(MathUtils.min(pageLastYOffset - secondaryOffset, 0) / rowHeight);
}
+
+ renderRanges.add(range);
}
+ return renderRanges;
}
- /**
- * When whole page is visible
- *
- * @return loaded parts count
- */
- private int loadWholePage(int page, GridSize grid, int nbOfPartsLoadable) {
- calculatePartSize(grid);
- return loadPage(page, 0, grid.rows - 1, 0, grid.cols - 1, nbOfPartsLoadable);
- }
+ private void loadVisible() {
+ int parts = 0;
+ float scaledPreloadOffset = preloadOffset;
+ float firstXOffset = -xOffset + scaledPreloadOffset;
+ float lastXOffset = -xOffset - pdfView.getWidth() - scaledPreloadOffset;
+ float firstYOffset = -yOffset + scaledPreloadOffset;
+ float lastYOffset = -yOffset - pdfView.getHeight() - scaledPreloadOffset;
- /**
- * When only part of one page is visible
- *
- * @return loaded parts count
- */
- private int loadPageCenter(Holder firstHolder, Holder lastHolder, GridSize grid, int nbOfPartsLoadable) {
- calculatePartSize(grid);
- return loadPage(firstHolder.page, firstHolder.row, lastHolder.row, firstHolder.col, lastHolder.col, nbOfPartsLoadable);
- }
+ List rangeList = getRenderRangeList(firstXOffset, firstYOffset, lastXOffset, lastYOffset);
- /**
- * When only end of page is visible
- *
- * @return loaded parts count
- */
- private int loadPageEnd(Holder holder, GridSize grid, int nbOfPartsLoadable) {
- calculatePartSize(grid);
- if (pdfView.isSwipeVertical()) {
- int firstRow = holder.row;
- return loadPage(holder.page, firstRow, grid.rows - 1, 0, grid.cols - 1, nbOfPartsLoadable);
- } else {
- int firstCol = holder.col;
- return loadPage(holder.page, 0, grid.rows - 1, firstCol, grid.cols - 1, nbOfPartsLoadable);
+ for (RenderRange range : rangeList) {
+ loadThumbnail(range.page);
}
- }
- /**
- * If only start of the page is visible
- *
- * @return loaded parts count
- */
- private int loadPageStart(Holder holder, GridSize grid, int nbOfPartsLoadable) {
- calculatePartSize(grid);
- if (pdfView.isSwipeVertical()) {
- int lastRow = holder.row;
- return loadPage(holder.page, 0, lastRow, 0, grid.cols - 1, nbOfPartsLoadable);
- } else {
- int lastCol = holder.col;
- return loadPage(holder.page, 0, grid.rows - 1, 0, lastCol, nbOfPartsLoadable);
+ for (RenderRange range : rangeList) {
+ calculatePartSize(range.gridSize);
+ parts += loadPage(range.page, range.leftTop.row, range.rightBottom.row, range.leftTop.col, range.rightBottom.col, CACHE_SIZE - parts);
+ if (parts >= CACHE_SIZE) {
+ break;
+ }
}
}
diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PdfFile.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PdfFile.java
index f40d29ed..fdc104f2 100644
--- a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PdfFile.java
+++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/PdfFile.java
@@ -52,9 +52,9 @@ class PdfFile {
/** Scaled page with maximum width */
private SizeF maxWidthPageSize = new SizeF(0, 0);
/** True if scrolling is vertical, else it's horizontal */
- private boolean isVertical = true;
+ private boolean isVertical;
/** Fixed spacing between pages in pixels */
- private int spacingPx = 0;
+ private int spacingPx;
/** Calculate spacing automatically so each page fits on it's own in the center of the view */
private boolean autoSpacing;
/** Calculated offsets for pages */
@@ -64,6 +64,11 @@ class PdfFile {
/** Calculated document length (width or height, depending on swipe mode) */
private float documentLength = 0;
private final FitPolicy pageFitPolicy;
+ /**
+ * True if every page should fit separately according to the FitPolicy,
+ * else the largest page fits and other pages scale relatively
+ */
+ private final boolean fitEachPage;
/**
* The pages the user want to display in order
* (ex: 0, 2, 2, 8, 8, 1, 1, 1)
@@ -71,7 +76,7 @@ class PdfFile {
private int[] originalUserPages;
PdfFile(PdfiumCore pdfiumCore, PdfDocument pdfDocument, FitPolicy pageFitPolicy, Size viewSize, int[] originalUserPages,
- boolean isVertical, int spacing, boolean autoSpacing) {
+ boolean isVertical, int spacing, boolean autoSpacing, boolean fitEachPage) {
this.pdfiumCore = pdfiumCore;
this.pdfDocument = pdfDocument;
this.pageFitPolicy = pageFitPolicy;
@@ -79,6 +84,7 @@ class PdfFile {
this.isVertical = isVertical;
this.spacingPx = spacing;
this.autoSpacing = autoSpacing;
+ this.fitEachPage = fitEachPage;
setup(viewSize);
}
@@ -111,7 +117,7 @@ private void setup(Size viewSize) {
public void recalculatePageSizes(Size viewSize) {
pageSizes.clear();
PageSizeCalculator calculator = new PageSizeCalculator(pageFitPolicy, originalMaxWidthPageSize,
- originalMaxHeightPageSize, viewSize);
+ originalMaxHeightPageSize, viewSize, fitEachPage);
maxWidthPageSize = calculator.getOptimalMaxWidthPageSize();
maxHeightPageSize = calculator.getOptimalMaxHeightPageSize();
diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/scroll/DefaultScrollHandle.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/scroll/DefaultScrollHandle.java
index 81b9956b..8195a540 100644
--- a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/scroll/DefaultScrollHandle.java
+++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/scroll/DefaultScrollHandle.java
@@ -110,7 +110,9 @@ public void setScroll(float position) {
} else {
handler.removeCallbacks(hidePageScrollerRunnable);
}
- setPosition((pdfView.isSwipeVertical() ? pdfView.getHeight() : pdfView.getWidth()) * position);
+ if (pdfView != null) {
+ setPosition((pdfView.isSwipeVertical() ? pdfView.getHeight() : pdfView.getWidth()) * position);
+ }
}
private void setPosition(float pos) {
diff --git a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/util/PageSizeCalculator.java b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/util/PageSizeCalculator.java
index 02992a21..4d678c98 100644
--- a/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/util/PageSizeCalculator.java
+++ b/android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/util/PageSizeCalculator.java
@@ -28,13 +28,15 @@ public class PageSizeCalculator {
private SizeF optimalMaxHeightPageSize;
private float widthRatio;
private float heightRatio;
+ private boolean fitEachPage;
public PageSizeCalculator(FitPolicy fitPolicy, Size originalMaxWidthPageSize, Size originalMaxHeightPageSize,
- Size viewSize) {
+ Size viewSize, boolean fitEachPage) {
this.fitPolicy = fitPolicy;
this.originalMaxWidthPageSize = originalMaxWidthPageSize;
this.originalMaxHeightPageSize = originalMaxHeightPageSize;
this.viewSize = viewSize;
+ this.fitEachPage = fitEachPage;
calculateMaxPages();
}
@@ -42,13 +44,15 @@ public SizeF calculate(Size pageSize) {
if (pageSize.getWidth() <= 0 || pageSize.getHeight() <= 0) {
return new SizeF(0, 0);
}
+ float maxWidth = fitEachPage ? viewSize.getWidth() : pageSize.getWidth() * widthRatio;
+ float maxHeight = fitEachPage ? viewSize.getHeight() : pageSize.getHeight() * heightRatio;
switch (fitPolicy) {
case HEIGHT:
- return fitHeight(pageSize, pageSize.getHeight() * heightRatio);
+ return fitHeight(pageSize, maxHeight);
case BOTH:
- return fitBoth(pageSize, pageSize.getWidth() * widthRatio, pageSize.getHeight() * heightRatio);
+ return fitBoth(pageSize, maxWidth, maxHeight);
default:
- return fitWidth(pageSize, pageSize.getWidth() * widthRatio);
+ return fitWidth(pageSize, maxWidth);
}
}
diff --git a/build.gradle b/build.gradle
index a40f1b28..0a9a0ba0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,8 +5,8 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.1.3'
- classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.1'
+ classpath 'com.android.tools.build:gradle:3.4.2'
+ classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
}
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 8fc5b9c1..1a59b22b 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Jun 27 20:37:56 CEST 2018
+#Sun Aug 18 01:14:14 CEST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
diff --git a/sample/build.gradle b/sample/build.gradle
index 5b0fb37e..133bcdde 100644
--- a/sample/build.gradle
+++ b/sample/build.gradle
@@ -13,11 +13,11 @@ repositories {
apply plugin: 'com.android.application'
android {
- compileSdkVersion 26
+ compileSdkVersion 28
defaultConfig {
minSdkVersion 14
- targetSdkVersion 26
+ targetSdkVersion 28
versionCode 3
versionName "3.0.0"
}
@@ -26,7 +26,7 @@ android {
dependencies {
implementation project(':android-pdf-viewer')
- implementation 'com.android.support:appcompat-v7:26.1.0'
- implementation 'org.androidannotations:androidannotations-api:4.4.0'
- annotationProcessor "org.androidannotations:androidannotations:4.4.0"
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+ implementation 'org.androidannotations:androidannotations-api:4.6.0'
+ annotationProcessor "org.androidannotations:androidannotations:4.6.0"
}