Create a PDF reader android App in Sketchware

To create a simple pdf reader in Sketchware follow the instructions given below.

1. Create a new project in Sketchware and create a VIEW as shown in image below:
linear2: A LinearH for the buttons/tools.
linear3: A LinearV for displaying images. Set it's padding to 0.
button1: A Button for picking PDF files.
edittext1: An EditText for displaying the page number. Set it's input type to numberSigned.
textview4: A TextView for displaying total number of pages.
textview3: A Button to move to page number entered in edittext1.
textview1: A Button to move to previous page.
textview2: A Button to move to next page.

2. Remove Toolbar and Status Bar of this View to make it full screen.

3. Add a File Picker component file_picker: application/pdf.

4. Add two number variables page and pageCount, and a String variable pdfFile. Also add a String list.

5. Add two more blocks: extra and display page(i).

6. In onCreate event use add source directly block and put following code.
touch = new ZoomableImageView(this);
linear3.addView(touch);
This code creates a new ZoomableImageView (defined as a new class later) and adds it to linear3.

7. In the event button1 onClick, Close renderer if it is open and use FilePicker pick files Block.
In the add source directly block use following code:
if (renderer != null){
renderer.close(); }

8. Define the More Block 'extra' using following codes:
i. Declare PdfRenderer and ZoomableImageView.
} private android.graphics.pdf.PdfRenderer renderer;
ZoomableImageView touch;

ii. Define a new View called ZoomableImageView.
public class ZoomableImageView extends ImageView {

Matrix matrix = new Matrix();
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
static final int CLICK = 3;
int mode = NONE;
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 4f;
float[] m;
float redundantXSpace, redundantYSpace;
float width, height;
float saveScale = 1f;
float right, bottom, origWidth, origHeight, bmWidth, bmHeight;
ScaleGestureDetector mScaleDetector;
Context context;

public ZoomableImageView(Context context) {
super(context);
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix.setTranslate(1f, 1f);
m = new float[9];
setImageMatrix(matrix); setScaleType(ScaleType.MATRIX);

setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: last.set(event.getX(), event.getY()); start.set(last); mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN: last.set(event.getX(), event.getY()); start.set(last);
mode = ZOOM;
break;
case MotionEvent.ACTION_MOVE:
if (mode == ZOOM || (mode == DRAG && saveScale > minScale)) {
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
float scaleWidth = Math.round(origWidth * saveScale);
float scaleHeight = Math.round(origHeight * saveScale);
if (scaleWidth < width) {
deltaX = 0;
if (y + deltaY > 0) deltaY = -y;
else if (y + deltaY < -bottom) deltaY = -(y + bottom);
} else if (scaleHeight < height) {
deltaY = 0;
if (x + deltaX > 0) deltaX = -x;
else if (x + deltaX < -right) deltaX = -(x + right);
} else {
if (x + deltaX > 0) deltaX = -x;
else if (x + deltaX < -right) deltaX = -(x + right);
if (y + deltaY > 0) deltaY = -y;
else if (y + deltaY < -bottom) deltaY = -(y + bottom);
}
matrix.postTranslate(deltaX, deltaY);
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK) performClick();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setImageMatrix(matrix);
invalidate();
return true;
}
});
}

@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
bmWidth = bm.getWidth();
bmHeight = bm.getHeight(); }

public void setMaxZoom(float x) {
maxScale = x; }

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mode = ZOOM;
return true;}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float mScaleFactor = detector.getScaleFactor();
float origScale = saveScale;
saveScale *= mScaleFactor;
if (saveScale > maxScale){
saveScale = maxScale;
mScaleFactor = maxScale / origScale;
} else if (saveScale < minScale) {
saveScale = minScale;
mScaleFactor = minScale / origScale;}
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
if (origWidth * saveScale <= width || origHeight * saveScale <= height) {
matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
if (mScaleFactor < 1) {
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (Math.round(origWidth * saveScale) < width) {
if (y < -bottom) matrix.postTranslate(0, -(y + bottom));
else if (y > 0) matrix.postTranslate(0, -y);
} else {
if (x < -right) matrix.postTranslate(-(x + right), 0);
else if (x > 0) matrix.postTranslate(-x, 0);}
}
}
} else {
matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY()); matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (x < -right) matrix.postTranslate(-(x + right), 0);
else if (x > 0) matrix.postTranslate(-x, 0);
if (y < -bottom) matrix.postTranslate(0, -(y + bottom));
else if (y > 0) matrix.postTranslate(0, -y);}
}
return true;
}
}

@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
float scale;
float scaleX = width / bmWidth;
float scaleY = height / bmHeight;
scale = Math.min(scaleX, scaleY); matrix.setScale(scale, scale); setImageMatrix(matrix);
saveScale = 1f;
redundantYSpace = height - (scale * bmHeight) ;
redundantXSpace = width - (scale * bmWidth);
redundantYSpace /= 2;
redundantXSpace /= 2; matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); setImageMatrix(matrix);}
}

iii. In the end put another add source directly block with following code.
 {

8. Next define the More Block display page (i).
i. In an add source directly block put following code (This code will open the pdf page using PdfRenderer and display it in the ZoomableImageView):
android.graphics.pdf.PdfRenderer.Page page = renderer.openPage((int)_i);
Bitmap mBitmap = Bitmap.createBitmap((int)getDip(page.getWidth()), (int)getDip(page.getHeight()), Bitmap.Config.ARGB_8888);
page.render(mBitmap, null, null, android.graphics.pdf.PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
touch.setImageBitmap(mBitmap);
page.close();

Here (int)_i represent the number variable i in the more Block.

ii. Use the blocks to display i+1 in EditText.

9. In the event file_picker onFilesPicked, use blocks as shown in image below:
i. Set the String pdfFile to path of the file picked.
ii. Set number variable page to 0.
iii. Use a try{ } catch (Exception){} code and  define the renderer and set pageCount to the pageCount obtained from the renderer. Use following code in add source directly block:
try {
renderer = new android.graphics.pdf.PdfRenderer(new ParcelFileDescriptor(ParcelFileDescriptor.open(new java.io.File(pdfFile), ParcelFileDescriptor.MODE_READ_ONLY)));
pageCount = renderer.getPageCount();

iv. Display the first page using the More Block display page (page).
v. Set the text of textview4 to pageCount.
vi. Catch Exception using following code:
} catch (Exception e){ }

10. In the event textview1 onClick, move to previous page. Use blocks as shown in image below:
11. In the event textview2 onClick, move to next page. Use blocks as shown in image below:
12. In the event textview3 onClick, move to the page number entered in edittext1. Use blocks as shown in image below:
13. Save and run the project. Now you can pick PDF files and view it in the ZoomableImageView added to linear3.

Watch this:




Convert PDF file to Android App in Android Studio or AIDE:

Comments

  1. ----------
    1. ERROR in /storage/emulated/0/.sketchware/mysc/606/app/src/main/java/com/my/newproject4/MainActivity.java (at line 138)
    touch = new ZoomableImageView(this);
    ^^^^^
    touch cannot be resolved to a variable
    ----------
    2. ERROR in /storage/emulated/0/.sketchware/mysc/606/app/src/main/java/com/my/newproject4/MainActivity.java (at line 139)
    linear3.addView(touch);
    ^^^^^
    touch cannot be resolved to a variable
    ----------
    3. ERROR in /storage/emulated/0/.sketchware/mysc/606/app/src/main/java/com/my/newproject4/MainActivity.java (at line 349)
    touch.setImageBitmap(mBitmap);
    ^^^^^
    touch cannot be resolved
    ----------
    3 problems (3 errors)

    ReplyDelete
    Replies
    1. ZoomableImageView touch;

      Put this in the more Block 'extra'.

      Delete
    2. To: Media Ahmed-
      If that happend then go to library menu and close compact design...

      Delete
  2. Plz how to make pdf book to apk with sketchware ?

    ReplyDelete
  3. We know that the scketchware is really important to get your own sketch/ You should try this to get some app which will assist you .

    ReplyDelete
  4. Replies
    1. display_page:
      more block
      create
      display_page
      variable= number
      then make sure add variable name then click add then create

      Delete
  5. Please how to zoom the page please reply me and the video for me.

    ReplyDelete
    Replies
    1. The ZoomableImageView class used in this tutorial can be used to pinch zoom the page.

      Delete
    2. Please bro i can't know how to do it please teach with video. How to zoom the page in sketchware tutorial.

      Delete
  6. How to make another block with display page []?

    ReplyDelete
  7. When I click on "open" button, it shows "Invalid Intent Operation: No activity found to handle intent"

    ReplyDelete
  8. how to make random numbers without duplicates?

    ReplyDelete
  9. Hello. Error message:" syntax error on token invalid character delete this token"
    Where's the problem?

    ReplyDelete
    Replies
    1. Remove the extra spaces from the locations where it is showing invalid character

      Delete
    2. This comment has been removed by the author.

      Delete
  10. I made a listview with my PDF files ..how do I just view them in an imageview

    ReplyDelete
  11. How to make book app please reply sir

    ReplyDelete
  12. Sanjeev, thanks so much for the great job. Inbox me please.

    ReplyDelete

Post a Comment

Popular posts from this blog

A Flash Light App in Sketchware

Create Music Player app in Sketchware

Simple car racing android game in Sketchware

In Sketchware: How to create a calculator for any simple formula?

Firebase auth in Sketchware for Login Activity