import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.util.Log;
import android.view.View;
+import java.io.File;
+import java.sql.Time;
+
+import cz.cvut.fel.dce.qrscanner.mupdf.MuPDFCore;
+
/**
- * Created by michal on 16.2.15.
+ * Created by Michal Horn on 16.2.15.
*/
-public class PdfPageView extends SceneView {
- private Bitmap mPdfBitmap;
- private Paint mBitmapPaint;
+public class PdfPageView extends View {
+ /**
+ * Value with some allowed minimum and maximum.
+ * @author Michal Horn
+ *
+ * @param <T> some comparable numeric data type
+ */
+ class IntervalValue<T extends Number & Comparable<? super T>> {
+ /**
+ * Stored value
+ */
+ private T mValue;
+ /**
+ * The lowest allowed value. All values stored in the object are
+ * higher or equal this minimum.
+ */
+ private T mMinimum;
+ /**
+ * The highest allowed value. All values stored in the object are
+ * lower or equal this maximum.
+ */
+ private T mMaximum;
+
+ /**
+ * Class constructor.
+ * Creates object that represents a value in range <minimum; maximum>.
+ *
+ * @param defValue Value to be stored in the object. Must be in the allowed range specified by other two parameters.
+ * @param minimum The lowes allowed value to be stored in the object.
+ * @param maximum The highest allowed value to be stored in the object.
+ * @throws Exception Throwed when minimal, maximal or inserted value were rejected.
+ */
+ public IntervalValue(T defValue, T minimum, T maximum) throws Exception {
+ setMinimum(minimum);
+ setMaximum(maximum);
+ if (!setValue(defValue)) {
+ throw new Exception("Provided value is not in the range.");
+ }
+ }
+
+ /**
+ * Store value in the object. The value must lie between the minimum and maximum
+ * defined for the object.
+ * @param value value to be stored in the object
+ * @return true - vale was stored successfully,<br>false - value could not be inserted because it was out of range.
+ */
+ public boolean setValue(T value) {
+ if (value.compareTo(mMinimum) >= 0 && value.compareTo(mMaximum) <= 0) {
+ mValue = value;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Set minimum for values in the object.
+ * Last inserted value is not changed even if it is lower then the new minimum.
+ * @param min new allowed minimum for the values stored to the object.
+ * @throws Exception throwed when new minimum is higher than old maximum.
+ */
+ public void setMinimum(T min) throws Exception {
+ if (mMaximum != null && mMinimum != null && mMinimum.compareTo(mMaximum) > 0) {
+ throw new Exception("Minimum is higher then maximum.");
+ }
+ mMinimum = min;
+ }
+
+ /**
+ * Set maximum for values in the object.
+ * Last inserted value is not changed even if it is higher then the new maximum.
+ * @param max new allowed maximum for the values stored to the object.
+ * @throws Exception throwed when new maximum is lower than old minimum.
+ */
+ public void setMaximum(T max) throws Exception {
+ if (mMinimum != null && mMaximum != null && mMaximum.compareTo(mMinimum) < 0) {
+ throw new Exception("Maximum is lower then minimum.");
+ }
+ mMaximum = max;
+ }
+
+ /**
+ * Get value stored in the object
+ * @return value stored in the object.
+ */
+ public T getValue() {
+ return mValue;
+ }
+
+ /**
+ * Get the lowest allowed value that can be stored in the object.
+ * @return minimal value
+ */
+ public T getMinimum() {
+ return mMinimum;
+ }
+
+ /**
+ * Get the highest allowed value that can be stored in the object.
+ * @return maximal value
+ */
+ public T getMaximum() {
+ return mMaximum;
+ }
+ }
+
+ /**
+ * Interface for events generated by the view
+ * @author Michal Horn
+ *
+ */
+ public interface SceneChange {
+ /**
+ * Invoked every time when the scene should be redrawed.
+ * @param source
+ */
+ public void onViewChanged(PdfPageView source);
+
+ /**
+ * Invoked once the PDF page is loaded and prepared as a bitmap to be shown
+ * @param source
+ */
+ public void onPageLoaded(PdfPageView source);
+ }
+
+ public static final String TAG = "PdfPageView";
+ protected Paint mPaint;
+ protected IntervalValue<Float> mZoom;
+ protected IntervalValue<Float> mXPosition;
+ protected IntervalValue<Float> mYPosition;
+ protected SceneChange mListener;
+ protected float mSceneHeight;
+ protected float mSceneWidth;
+ protected Bitmap mPdfBitmap;
+ protected File mPdfFile;
+ protected Boolean mPageLoaded;
+ private MuPDFCore mPdfCore;
+ private IntervalValue<Integer> mPage;
+ private MuPDFCore.Cookie mPdfCookie;
+
+ public PdfPageView(Context context, String filePath) throws Exception {
+ super(context);
+ mPageLoaded = false;
+ mPdfFile = new File(filePath);
+ if (!mPdfFile.exists()) {
+ throw new PdfViewerException("File " + filePath + " does not exist.");
+ }
+ mPaint = new Paint();
+ mPdfCore = new MuPDFCore(context, mPdfFile.getAbsolutePath());
+ mPdfCookie = mPdfCore.new Cookie();
+ if (mPdfCore == null) {
+ throw new PdfViewerException("The PDF file could not be loaded.");
+ }
+ mPage = new IntervalValue<>(0, 0, mPdfCore.countPages()-1);
+ Log.i(TAG, "Pages: " + mPage.toString());
+ }
+
+ public int getActualPage() {
+ return mPage.getValue();
+ }
+
+ public int getLastPage() {
+ return mPage.getMaximum();
+ }
+
+ public boolean setPage(int page) {
+ return mPage.setValue(page);
+ }
+
+ public void loadPage() {
+ long startTime = System.currentTimeMillis();
+ try {
+ Log.i(TAG, "Loading PDF page " + getActualPage());
+ mSceneWidth = mPdfCore.getPageSize(getActualPage()).x;
+ mSceneHeight = mPdfCore.getPageSize(getActualPage()).y;
+ Log.i(TAG, "Page size: " + mSceneWidth + "x" + mSceneHeight);
+ Bitmap.Config mPdfBitmapConf = Bitmap.Config.ARGB_8888;
+ mPdfBitmap = Bitmap.createBitmap((int)mSceneWidth, (int)mSceneHeight, mPdfBitmapConf);
+ mPdfCore.drawPage(mPdfBitmap, 0, (int) mSceneWidth, (int) mSceneHeight, 0, 0, (int) mSceneWidth, (int) mSceneHeight, mPdfCookie);
+
+ mXPosition = new IntervalValue<>(0.0f, -mSceneWidth, mSceneWidth);
+ mYPosition = new IntervalValue<>(0.0f, -mSceneHeight, mSceneHeight);
+ mZoom = new IntervalValue<>(0.2f, 0.2f, 10.0f);
+ } catch (Exception e) {
+ Log.e(TAG, "Error in setting page dimensions.");
+ e.printStackTrace();
+ }
+ long endTime = System.currentTimeMillis();
+ mPageLoaded = true;
+ Log.i(TAG, "PDF page loaded in " + Long.toString(endTime - startTime) + "ms.");
+ if (mListener != null) {
+ mListener.onPageLoaded(this);
+ }
+ }
+
+ /**
+ * Set a listener of the events
+ * @param listener listener of the events
+ */
+ public void setListener(SceneChange listener) {
+ mListener = listener;
+ }
+
+ public void clearListener() {
+ mListener = null;
+ }
+
+ /**
+ * Zoom scene function. The scene can be zoomed in or out only in limits
+ * defined in constructor.
+ * @param deltaRatio when > 0 - zoom in,<br> when < 0 - zoom out
+ */
+ public void zoom(float deltaRatio) {
+ if (!mPageLoaded) return;
+ float ratio = mZoom.getValue();
+ ratio += deltaRatio;
+ if (mZoom.setValue(ratio) == true && mListener != null) {
+ mListener.onViewChanged(this);
+ }
+ }
+
+ /**
+ * Move scene function. The scene can be moved only in the rectangle specified
+ * by limits defined in constructor.
+ * @param x change of the x coordinate relatively to the actual position
+ * @param y change of the y coordinate relatively to the actual position
+ */
+ public void move(float x, float y) {
+ if (!mPageLoaded) return;
+ boolean xWasSet = mXPosition.setValue(mXPosition.getValue() + x/mZoom.getValue()*2.2f);
+ boolean yWasSet = mYPosition.setValue(mYPosition.getValue() + y/mZoom.getValue()*2.2f);
+
+ if ((xWasSet || yWasSet) && mListener != null) {
+ mListener.onViewChanged(this);
+ }
+ }
+ /**
+ * @return actual scene zoom ratio
+ */
+ public float getZoomRatio() {
+ return mZoom.getValue();
+ }
+
+ /**
+ * @return actual scene position on X axis
+ */
+ public float getXPosition() {
+ return mXPosition.getValue();
+ }
+
+ /**
+ * @return actual scene positoin on Y axis
+ */
+ public float getYPosition() {
+ return mYPosition.getValue();
+ }
+
+ /**
+ * @return how tall the scene is
+ */
+ public float getSceneHeight() {
+ return mSceneHeight;
+ }
- public PdfPageView(Context context, Bitmap pdfBitmap, float defZoom, float minZoom, float maxZoom, float defXCenter, float minX, float maxX, float defYCenter, float minY, float maxY) throws Exception {
- super(context, defZoom, minZoom, maxZoom, defXCenter, minX, maxX, defYCenter, minY, maxY);
- mPdfBitmap = Bitmap.createBitmap(pdfBitmap);
- mBitmapPaint = new Paint();
+ /**
+ * @return how wide the scene is
+ */
+ public float getSceneWidth() {
+ return mSceneWidth;
}
@Override
- protected void computeSceneDimmensions() {
- mSceneWidth = mPdfBitmap.getWidth();
- mSceneHeight = mPdfBitmap.getHeight();
+ protected void onDraw(Canvas c) {
+ if (!mPageLoaded) return;
+ draw(c);
+ super.onDraw(c);
}
@Override
public void draw(Canvas c) {
+ if (!mPageLoaded) return;
c.translate(c.getWidth()/2, c.getHeight()/2);
c.scale(mZoom.getValue(), mZoom.getValue());
c.translate(-mXPosition.getValue(), -mYPosition.getValue());
- c.drawBitmap(mPdfBitmap, 0, 0, mBitmapPaint);
+ c.drawBitmap(mPdfBitmap, 0, 0, mPaint);
}
}
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
-import android.graphics.Bitmap;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
+import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.FrameLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import cz.cvut.fel.dce.qrscanner.R;
-import cz.cvut.fel.dce.qrscanner.mupdf.MuPDFCore;
-public class PdfViewActivity extends Activity implements ViewTreeObserver.OnGlobalLayoutListener, SceneView.SceneChange, SensorEventListener {
+public class PdfViewActivity extends Activity implements ViewTreeObserver.OnGlobalLayoutListener, PdfPageView.SceneChange, SensorEventListener {
+
+ enum ViewStates {
+ SCROLLING,
+ VIEWING
+ };
+
public static final String TAG = "PdfViewActivity";
private FrameLayout mPdfImageContainer;
+ private TextView mCurrentPageNumber;
+ private TextView mLastPageNumber;
+ private TextView mViewerStateText;
private ViewTreeObserver mPreviewImgObserver;
private String mFilePath;
private PdfPageView mPdfView;
private Boolean mPdfLoaded = false;
private SensorManager mSensorManager;
+ private ViewStates mViewStates;
+ private RelativeLayout mProgressContainer;
/**
* Start position of the gesture on touchpad
*/
private float startX;
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
setContentView(R.layout.activity_pdf_view);
mPdfImageContainer = (FrameLayout) findViewById(R.id.pdf_view_container);
+ mCurrentPageNumber = (TextView) findViewById(R.id.page_number);
+ mLastPageNumber = (TextView) findViewById(R.id.total_pages_num);
+ mViewerStateText = (TextView) findViewById(R.id.pdf_viewer_state);
+ mViewStates = ViewStates.SCROLLING;
+ mProgressContainer = (RelativeLayout) findViewById(R.id.progress_container);
+
if (mPdfImageContainer != null) {
mPreviewImgObserver = mPdfImageContainer.getViewTreeObserver();
Log.i(TAG, "Registering mPreviewImgObserver OnGlobalLayoutListener.");
try {
String picturePath = mFilePath;
Log.i(TAG, "Path to component files: " + picturePath);
-
- MuPDFCore core = new MuPDFCore(getApplicationContext(), picturePath);
- Log.d(TAG, "numpages: "+ core.countPages());
- MuPDFCore.Cookie cookie = core.new Cookie();
- int pageW = (int)core.getPageSize(0).x;
- int pageH = (int)core.getPageSize(0).y;
- Log.d(TAG, "page size: " + pageW + ", " + pageH);
- Bitmap.Config mPdfBitmapConf = Bitmap.Config.ARGB_8888;
- Bitmap mPdfBitmap = Bitmap.createBitmap(pageW, pageH, mPdfBitmapConf);
- core.drawPage(mPdfBitmap, 0, pageW, pageH,0 , 0, pageW, pageH, cookie);
- mPdfView = new PdfPageView(getApplicationContext(), mPdfBitmap, 0, 0, 100, (float) mPdfBitmap.getWidth()/2, 0, (float) mPdfBitmap.getWidth(), (float) mPdfBitmap.getHeight()/2, 0, (float) mPdfBitmap.getHeight());
+ mPdfView = new PdfPageView(getApplicationContext(), picturePath);
+ mCurrentPageNumber.setText(Integer.toString(mPdfView.getActualPage()+1));
+ mLastPageNumber.setText(Integer.toString(mPdfView.getLastPage()+1));
mPdfView.setListener(this);
- mPdfView.setDefaultValues(0, 0, 0);
+ mPdfView.setPage(0);
+ new LoadPageTask().execute();
+
+
if (mPdfImageContainer != null) {
- mPdfImageContainer.addView(mPdfView);
- mPdfImageContainer.invalidate();
mPdfLoaded = true;
}
else {
return super.onGenericMotionEvent(event);
}
- @Override
- public void onSceneChanged(SceneView source) {
- if (mPdfView != null) {
- mPdfView.invalidate();
- }
- }
-
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
}
+
+ @Override
+ public void onViewChanged(PdfPageView source) {
+ if (mPdfView != null) {
+ mPdfView.invalidate();
+ }
+ }
+
+ @Override
+ public void onPageLoaded(PdfPageView source) {
+
+ }
+
+ private class LoadPageTask extends AsyncTask<Void, Void, Void> {
+
+ @Override
+ protected Void doInBackground(Void[] objects) {
+ mPdfView.loadPage();
+ return null;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ Log.d(TAG, "Starting loading of the PDF page asynchronously.");
+ mProgressContainer.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ super.onPostExecute(aVoid);
+ mProgressContainer.setVisibility(View.INVISIBLE);
+ mPdfImageContainer.addView(mPdfView);
+ Log.d(TAG, "PDF page loaded.");
+ }
+ }
}
--- /dev/null
+package cz.cvut.fel.dce.qrscanner.pdfviewer;
+
+/**
+ * Created by michal on 16.2.15.
+ */
+public class PdfViewerException extends Exception {
+ PdfViewerException(String s){
+ super(s);
+ }
+}
+++ /dev/null
-package cz.cvut.fel.dce.qrscanner.pdfviewer;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.view.View;
-
-/**
- * Parent class for all views for drawing some graphic on canvas.
- * The scenes can be zoomed and moved by an application.
- * @author Michal Horn
- *
- */
-public abstract class SceneView extends View {
- /**
- * Value with some allowed minimum and maximum.
- * @author Michal Horn
- *
- * @param <T> some comparable numeric data type
- */
- class IntervalValue<T extends Number & Comparable<? super T>> {
- /**
- * Stored value
- */
- private T mValue;
- /**
- * The lowest allowed value. All values stored in the object are
- * higher or equal this minimum.
- */
- private T mMinimum;
- /**
- * The highest allowed value. All values stored in the object are
- * lower or equal this maximum.
- */
- private T mMaximum;
-
- /**
- * Class constructor.
- * Creates object that represents a value in range <minimum; maximum>.
- *
- * @param defValue Value to be stored in the object. Must be in the allowed range specified by other two parameters.
- * @param minimum The lowes allowed value to be stored in the object.
- * @param maximum The highest allowed value to be stored in the object.
- * @throws Exception Throwed when minimal, maximal or inserted value were rejected.
- */
- public IntervalValue(T defValue, T minimum, T maximum) throws Exception {
- setMinimum(minimum);
- setMaximum(maximum);
- if (!setValue(defValue)) {
- throw new Exception("Provided value is not in the range.");
- }
- }
-
- /**
- * Store value in the object. The value must lie between the minimum and maximum
- * defined for the object.
- * @param value value to be stored in the object
- * @return true - vale was stored successfully,<br>false - value could not be inserted because it was out of range.
- */
- public boolean setValue(T value) {
- if (value.compareTo(mMinimum) >= 0 && value.compareTo(mMaximum) <= 0) {
- mValue = value;
- return true;
- }
- else {
- return false;
- }
- }
-
- /**
- * Set minimum for values in the object.
- * Last inserted value is not changed even if it is lower then the new minimum.
- * @param min new allowed minimum for the values stored to the object.
- * @throws Exception throwed when new minimum is higher than old maximum.
- */
- public void setMinimum(T min) throws Exception {
- if (mMaximum != null && mMinimum != null && mMinimum.compareTo(mMaximum) > 0) {
- throw new Exception("Minimum is higher then maximum.");
- }
- mMinimum = min;
- }
-
- /**
- * Set maximum for values in the object.
- * Last inserted value is not changed even if it is higher then the new maximum.
- * @param max new allowed maximum for the values stored to the object.
- * @throws Exception throwed when new maximum is lower than old minimum.
- */
- public void setMaximum(T max) throws Exception {
- if (mMinimum != null && mMaximum != null && mMaximum.compareTo(mMinimum) < 0) {
- throw new Exception("Maximum is lower then minimum.");
- }
- mMaximum = max;
- }
-
- /**
- * Get value stored in the object
- * @return value stored in the object.
- */
- public T getValue() {
- return mValue;
- }
-
- /**
- * Get the lowest allowed value that can be stored in the object.
- * @return minimal value
- */
- public T getMinimum() {
- return mMinimum;
- }
-
- /**
- * Get the highest allowed value that can be stored in the object.
- * @return maximal value
- */
- public T getMaximum() {
- return mMaximum;
- }
- }
-
- /**
- * Interface for events generated by the view
- * @author Michal Horn
- *
- */
- public interface SceneChange {
- /**
- * Invoked every time when the scene should be redrawed.
- * @param source
- */
- public void onSceneChanged(SceneView source);
- }
-
- protected Paint mPaint;
- protected IntervalValue<Float> mZoom;
- protected IntervalValue<Float> mXPosition;
- protected IntervalValue<Float> mYPosition;
- protected SceneChange mListener;
- protected float mSceneHeight;
- protected float mSceneWidth;
- protected float mDefaultZoomRatio;
- protected float mDefaultXPos;
- protected float mDefaultYPos;
-
- /**
- * Class constructor.
- * @param context the context of the application to provide the canvas
- * @param defZoom initial zoom ratio
- * @param minZoom maximal allowed zoom out
- * @param maxZoom maximal allowed zoom in
- * @param defXCenter initial position of the scene
- * @param minX minimal scene position on X axis
- * @param maxX maximal scene position on X axis
- * @param defYCenter initial position of the scene
- * @param minY minimal scene position on Y axis
- * @param maxY maximal scene position on Y axis
- * @throws Exception
- */
- public SceneView(Context context,
- float defZoom, float minZoom, float maxZoom,
- float defXCenter, float minX, float maxX,
- float defYCenter, float minY, float maxY) throws Exception {
- super(context);
- mDefaultZoomRatio = defZoom;
- mDefaultXPos = defXCenter;
- mDefaultYPos = defYCenter;
- mZoom = new IntervalValue<Float>(defZoom, minZoom, maxZoom);
- mXPosition = new IntervalValue<Float>(defXCenter, minX, maxX);
- mYPosition = new IntervalValue<Float>(defYCenter, minY, maxY);
- mListener = null;
- mPaint = new Paint();
- }
-
- /**
- * Default class constructor, all default values are set to zeros.
- * @param context the context of the application to provide the canvas
- * @throws Exception
- */
- public SceneView(Context context) throws Exception {
- this(context, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
- }
-
- /**
- * Set a listener of the events
- * @param listener listener of the events
- */
- public void setListener(SceneChange listener) {
- mListener = listener;
- }
-
- /**
- * Set new default values. Default values are loaded when reset function is called.
- * Values are stored only, not applied.
- * @param zoom default zoom ratio
- * @param x default x position
- * @param y default y position
- */
- public void setDefaultValues(float zoom, float x, float y) {
- mDefaultXPos = x;
- mDefaultYPos = y;
- mDefaultZoomRatio = zoom;
- }
-
- /**
- * Zoom scene function. The scene can be zoomed in or out only in limits
- * defined in constructor.
- * @param deltaRatio when > 0 - zoom in,<br> when < 0 - zoom out
- */
- public void zoom(float deltaRatio) {
- float ratio = mZoom.getValue();
- ratio += deltaRatio;
- if (mZoom.setValue(ratio) == true && mListener != null) {
- mListener.onSceneChanged(this);
- }
- }
-
- /**
- * Move scene function. The scene can be moved only in the rectangle specified
- * by limits defined in constructor.
- * @param x change of the x coordinate relatively to the actual position
- * @param y change of the y coordinate relatively to the actual position
- */
- public void move(float x, float y) {
- boolean xWasSet = mXPosition.setValue(mXPosition.getValue() + x/mZoom.getValue()*2.2f);
- boolean yWasSet = mYPosition.setValue(mYPosition.getValue() + y/mZoom.getValue()*2.2f);
-
- if ((xWasSet || yWasSet) && mListener != null) {
- mListener.onSceneChanged(this);
- }
- }
-
- /**
- * Reset the zoom ratio and scene position to default values.
- */
- public void reset() {
- boolean xWasSet = mXPosition.setValue(mDefaultXPos);
- boolean yWasSet = mYPosition.setValue(mDefaultYPos);
- boolean zoomWasSet = mZoom.setValue(mDefaultZoomRatio);
- if ((xWasSet || yWasSet || zoomWasSet) && mListener != null) {
- mListener.onSceneChanged(this);
- }
- }
-
- /**
- * Abstract function for scene dimensions calculation to be implemented.
- */
- protected abstract void computeSceneDimmensions();
-
- /**
- * Abstract function with the drawing process to be implemented
- */
- public abstract void draw(Canvas c);
-
- /**
- * @return actual scene zoom ratio
- */
- public float getZoomRatio() {
- return mZoom.getValue();
- }
-
- /**
- * @return actual scene position on X axis
- */
- public float getXPosition() {
- return mXPosition.getValue();
- }
-
- /**
- * @return actual scene positoin on Y axis
- */
- public float getYPosition() {
- return mYPosition.getValue();
- }
-
- /**
- * @return how tall the scene is
- */
- public float getSceneHeight() {
- return mSceneHeight;
- }
-
- /**
- * @return how wide the scene is
- */
- public float getSceneWidth() {
- return mSceneWidth;
- }
-
- @Override
- protected void onDraw(Canvas c) {
- draw(c);
- super.onDraw(c);
- }
-}
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/page_state_scrolling"
- android:id="@+id/textView2"
+ android:id="@+id/pdf_viewer_state"
android:layout_alignParentEnd="true"/>
<TextView
android:text="@string/pdf_viewer_state_label"
android:id="@+id/textView4"
android:layout_alignParentTop="true"
- android:layout_toStartOf="@+id/textView2"/>
+ android:layout_toStartOf="@+id/pdf_viewer_state"/>
<TextView
android:layout_width="wrap_content"
android:layout_below="@+id/textView"
android:layout_alignParentStart="true"
android:id="@+id/pdf_view_container">
+
+ <RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_gravity="center"
+ android:id="@+id/progress_container">
+
+ <ProgressBar
+ style="?android:attr/progressBarStyleLarge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/progressBar"
+ android:layout_centerVertical="true"
+ android:layout_centerHorizontal="true"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/loading_page"
+ android:id="@+id/textView2"
+ android:layout_below="@+id/progressBar"
+ android:layout_centerHorizontal="true"/>
+ </RelativeLayout>
</FrameLayout>
</RelativeLayout>
<string name="page_number_label">Page:</string>
<string name="pdf_viewer_state_label">State:</string>
<string name="page_state_scrolling">scrolling</string>
+ <string name="loading_page">Loading...</string>
</resources>