Layout EPUB to match screen size, and reflow when changing orientation.
Handle screen rotation without restarting activity!
Add text size popup menu for EPUB documents.
diff --git a/lib/src/main/AndroidManifest.xml b/lib/src/main/AndroidManifest.xml
index 7ca0faf..61a9707 100644
--- a/lib/src/main/AndroidManifest.xml
+++ b/lib/src/main/AndroidManifest.xml
@@ -5,6 +5,7 @@
<application>
<activity
android:name=".DocumentActivity"
+ android:configChanges="orientation|screenSize|keyboardHidden"
>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
diff --git a/lib/src/main/java/com/artifex/mupdf/viewer/DocumentActivity.java b/lib/src/main/java/com/artifex/mupdf/viewer/DocumentActivity.java
index c5470d2..382b6a9 100644
--- a/lib/src/main/java/com/artifex/mupdf/viewer/DocumentActivity.java
+++ b/lib/src/main/java/com/artifex/mupdf/viewer/DocumentActivity.java
@@ -77,6 +77,13 @@
private AlertDialog mAlertDialog;
private ArrayList<OutlineActivity.Item> mFlatOutline;
+ private int mLayoutEM = 10;
+ private int mLayoutW = 312;
+ private int mLayoutH = 504;
+
+ protected View mLayoutButton;
+ protected PopupMenu mLayoutPopupMenu;
+
private MuPDFCore openFile(String path)
{
int lastSlashPos = path.lastIndexOf('/');
@@ -234,6 +241,14 @@
alert.show();
}
+ public void relayoutDocument() {
+ int loc = core.layout(mDocView.mCurrent, mLayoutW, mLayoutH, mLayoutEM);
+ mFlatOutline = null;
+ mDocView.mHistory.clear();
+ mDocView.refresh();
+ mDocView.setDisplayedViewIndex(loc);
+ }
+
public void createUI(Bundle savedInstanceState) {
if (core == null)
return;
@@ -266,6 +281,17 @@
protected void onDocMotion() {
hideButtons();
}
+
+ @Override
+ public void onSizeChanged(int w, int h, int oldw, int oldh) {
+ if (core.isReflowable()) {
+ mLayoutW = w * 72 / 160;
+ mLayoutH = h * 72 / 160;
+ relayoutDocument();
+ } else {
+ refresh();
+ }
+ }
};
mDocView.setAdapter(new PageAdapter(this, core));
@@ -385,6 +411,37 @@
}
});
+ if (core.isReflowable()) {
+ mLayoutButton.setVisibility(View.VISIBLE);
+ mLayoutPopupMenu = new PopupMenu(this, mLayoutButton);
+ mLayoutPopupMenu.getMenuInflater().inflate(R.menu.layout_menu, mLayoutPopupMenu.getMenu());
+ mLayoutPopupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ float oldLayoutEM = mLayoutEM;
+ int id = item.getItemId();
+ if (id == R.id.action_layout_6pt) mLayoutEM = 6;
+ else if (id == R.id.action_layout_7pt) mLayoutEM = 7;
+ else if (id == R.id.action_layout_8pt) mLayoutEM = 8;
+ else if (id == R.id.action_layout_9pt) mLayoutEM = 9;
+ else if (id == R.id.action_layout_10pt) mLayoutEM = 10;
+ else if (id == R.id.action_layout_11pt) mLayoutEM = 11;
+ else if (id == R.id.action_layout_12pt) mLayoutEM = 12;
+ else if (id == R.id.action_layout_13pt) mLayoutEM = 13;
+ else if (id == R.id.action_layout_14pt) mLayoutEM = 14;
+ else if (id == R.id.action_layout_15pt) mLayoutEM = 15;
+ else if (id == R.id.action_layout_16pt) mLayoutEM = 16;
+ if (oldLayoutEM != mLayoutEM)
+ relayoutDocument();
+ return true;
+ }
+ });
+ mLayoutButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ mLayoutPopupMenu.show();
+ }
+ });
+ }
+
if (core.hasOutline()) {
mOutlineButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
@@ -615,6 +672,7 @@
mSearchClose = (ImageButton)mButtonsView.findViewById(R.id.searchClose);
mSearchText = (EditText)mButtonsView.findViewById(R.id.searchText);
mLinkButton = (ImageButton)mButtonsView.findViewById(R.id.linkButton);
+ mLayoutButton = mButtonsView.findViewById(R.id.layoutButton);
mTopBarSwitcher.setVisibility(View.INVISIBLE);
mPageNumberView.setVisibility(View.INVISIBLE);
diff --git a/lib/src/main/java/com/artifex/mupdf/viewer/MuPDFCore.java b/lib/src/main/java/com/artifex/mupdf/viewer/MuPDFCore.java
index 40c62be..ad08a73 100644
--- a/lib/src/main/java/com/artifex/mupdf/viewer/MuPDFCore.java
+++ b/lib/src/main/java/com/artifex/mupdf/viewer/MuPDFCore.java
@@ -30,8 +30,14 @@
private float pageHeight;
private DisplayList displayList;
+ /* Default to "A Format" pocket book size. */
+ private int layoutW = 312;
+ private int layoutH = 504;
+ private int layoutEM = 10;
+
public MuPDFCore(String filename) {
doc = Document.openDocument(filename);
+ doc.layout(layoutW, layoutH, layoutEM);
pageCount = doc.countPages();
resolution = 160;
currentPage = -1;
@@ -39,6 +45,7 @@
public MuPDFCore(byte buffer[], String magic) {
doc = Document.openDocument(buffer, magic);
+ doc.layout(layoutW, layoutH, layoutEM);
pageCount = doc.countPages();
resolution = 160;
currentPage = -1;
@@ -52,6 +59,31 @@
return pageCount;
}
+ public synchronized boolean isReflowable() {
+ return doc.isReflowable();
+ }
+
+ public synchronized int layout(int oldPage, int w, int h, int em) {
+ if (w != layoutW || h != layoutH || em != layoutEM) {
+ System.out.println("LAYOUT: " + w + "," + h);
+ layoutW = w;
+ layoutH = h;
+ layoutEM = em;
+ long mark = doc.makeBookmark(oldPage);
+ doc.layout(layoutW, layoutH, layoutEM);
+ currentPage = -1;
+ pageCount = doc.countPages();
+ outline = null;
+ try {
+ outline = doc.loadOutline();
+ } catch (Exception ex) {
+ /* ignore error */
+ }
+ return doc.findBookmark(mark);
+ }
+ return oldPage;
+ }
+
private synchronized void gotoPage(int pageNum) {
/* TODO: page cache */
if (pageNum > pageCount-1)
@@ -109,6 +141,7 @@
AndroidDrawDevice dev = new AndroidDrawDevice(bm, patchX, patchY);
displayList.run(dev, ctm, cookie);
+ dev.close();
dev.destroy();
}
diff --git a/lib/src/main/java/com/artifex/mupdf/viewer/PageAdapter.java b/lib/src/main/java/com/artifex/mupdf/viewer/PageAdapter.java
index 7b48722..35a561b 100644
--- a/lib/src/main/java/com/artifex/mupdf/viewer/PageAdapter.java
+++ b/lib/src/main/java/com/artifex/mupdf/viewer/PageAdapter.java
@@ -41,6 +41,10 @@
mSharedHqBm = null;
}
+ public void refresh() {
+ mPageSizes.clear();
+ }
+
public View getView(final int position, View convertView, ViewGroup parent) {
final PageView pageView;
if (convertView == null) {
diff --git a/lib/src/main/java/com/artifex/mupdf/viewer/ReaderView.java b/lib/src/main/java/com/artifex/mupdf/viewer/ReaderView.java
index 48b9fff..526769e 100644
--- a/lib/src/main/java/com/artifex/mupdf/viewer/ReaderView.java
+++ b/lib/src/main/java/com/artifex/mupdf/viewer/ReaderView.java
@@ -45,8 +45,8 @@
private static final boolean HORIZONTAL_SCROLLING = true;
- private Adapter mAdapter;
- private int mCurrent; // Adapter's index for the current view
+ private PageAdapter mAdapter;
+ protected int mCurrent; // Adapter's index for the current view
private boolean mResetLayout;
private final SparseArray<View>
mChildViews = new SparseArray<View>(3);
@@ -338,6 +338,18 @@
mScale = 1.0f;
mXScroll = mYScroll = 0;
+ /* All page views need recreating since both page and screen has changed size,
+ * invalidating both sizes and bitmaps. */
+ mAdapter.refresh();
+ int numChildren = mChildViews.size();
+ for (int i = 0; i < mChildViews.size(); i++) {
+ View v = mChildViews.valueAt(i);
+ onNotInUse(v);
+ removeViewInLayout(v);
+ }
+ mChildViews.clear();
+ mViewCache.clear();
+
requestLayout();
}
@@ -753,15 +765,9 @@
@Override
public void setAdapter(Adapter adapter) {
-
- // release previous adapter's bitmaps
- if (null!=mAdapter && adapter!=mAdapter) {
- if (adapter instanceof PageAdapter){
- ((PageAdapter) adapter).releaseBitmaps();
- }
- }
-
- mAdapter = adapter;
+ if (mAdapter != null && mAdapter != adapter)
+ mAdapter.releaseBitmaps();
+ mAdapter = (PageAdapter) adapter;
requestLayout();
}
diff --git a/lib/src/main/res/drawable/ic_format_size_white_24dp.xml b/lib/src/main/res/drawable/ic_format_size_white_24dp.xml
new file mode 100644
index 0000000..23f2f33
--- /dev/null
+++ b/lib/src/main/res/drawable/ic_format_size_white_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M9,4v3h5v12h3L17,7h5L22,4L9,4zM3,12h3v7h3v-7h3L12,9L3,9v3z"/>
+</vector>
diff --git a/lib/src/main/res/layout/document_activity.xml b/lib/src/main/res/layout/document_activity.xml
index dda2d08..06bdea3 100644
--- a/lib/src/main/res/layout/document_activity.xml
+++ b/lib/src/main/res/layout/document_activity.xml
@@ -52,6 +52,15 @@
/>
<ImageButton
+ android:id="@+id/layoutButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/button"
+ android:src="@drawable/ic_format_size_white_24dp"
+ android:visibility="gone"
+ />
+
+ <ImageButton
android:id="@+id/outlineButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/lib/src/main/res/menu/layout_menu.xml b/lib/src/main/res/menu/layout_menu.xml
new file mode 100644
index 0000000..4bc834a
--- /dev/null
+++ b/lib/src/main/res/menu/layout_menu.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/action_layout_6pt" android:title="6pt" />
+ <item android:id="@+id/action_layout_7pt" android:title="7pt" />
+ <item android:id="@+id/action_layout_8pt" android:title="8pt" />
+ <item android:id="@+id/action_layout_9pt" android:title="9pt" />
+ <item android:id="@+id/action_layout_10pt" android:title="10pt" />
+ <item android:id="@+id/action_layout_11pt" android:title="11pt" />
+ <item android:id="@+id/action_layout_12pt" android:title="12pt" />
+ <item android:id="@+id/action_layout_13pt" android:title="13pt" />
+ <item android:id="@+id/action_layout_14pt" android:title="14pt" />
+ <item android:id="@+id/action_layout_15pt" android:title="15pt" />
+ <item android:id="@+id/action_layout_16pt" android:title="16pt" />
+</menu>