This article describes how to display the content of a file after the vudroid reader selects a file.
This does not involve how the vudroid reads the file content, but how the content is displayed after the file content is read.
Three classes are involved: documentview, page, and pagetreenode.
Documentview can be considered as a display container, which stores pages, and each page is composed of several pagetreenode.
Therefore, we can see that documentview is only responsible for processing touch screen time, button time, and rolling events. Of course, this function also involves enlarging and downgrading the content, and page contains a page of content, including page boundaries and text content. pagetreenode stores real text content.
1. documentview
The content here includes button processing, touch screen event processing (multi-touch supported), zoom-in and zoom-out processing, and scroll event processing:
1) Click Event processing. Here you press the upper and lower keys, and the page content can be moved up, down, and left.
@Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_DPAD_RIGHT: lineByLineMoveTo(1); return true; case KeyEvent.KEYCODE_DPAD_LEFT: lineByLineMoveTo(-1); return true; case KeyEvent.KEYCODE_DPAD_DOWN: verticalDpadScroll(1); return true; case KeyEvent.KEYCODE_DPAD_UP: verticalDpadScroll(-1); return true; } } return super.dispatchKeyEvent(event); }
2) touch screen event processing (because a multi-touch library is introduced here, multi-touch is supported)
Add a multi-touch Library to the first code.
private void initMultiTouchZoomIfAvailable(ZoomModel zoomModel) { try { multiTouchZoom = (MultiTouchZoom) Class.forName("org.vudroid.core.multitouch.MultiTouchZoomImpl").getConstructor(ZoomModel.class).newInstance(zoomModel); } catch (Exception e) { System.out.println("Multi touch zoom is not available: " + e); } }
The second code is to handle touch screen events.
@Override public boolean onTouchEvent(MotionEvent ev) { super.onTouchEvent(ev); if (multiTouchZoom != null) { if (multiTouchZoom.onTouchEvent(ev)) { return true; } if (multiTouchZoom.isResetLastPointAfterZoom()) { setLastPosition(ev); multiTouchZoom.setResetLastPointAfterZoom(false); } } if (velocityTracker == null) { velocityTracker = VelocityTracker.obtain(); } velocityTracker.addMovement(ev); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: stopScroller(); setLastPosition(ev); if (ev.getEventTime() - lastDownEventTime < DOUBLE_TAP_TIME) { zoomModel.toggleZoomControls(); } else { lastDownEventTime = ev.getEventTime(); } break; case MotionEvent.ACTION_MOVE: scrollBy((int) (lastX - ev.getX()), (int) (lastY - ev.getY())); setLastPosition(ev); break; case MotionEvent.ACTION_UP: velocityTracker.computeCurrentVelocity(1000); scroller.fling(getScrollX(), getScrollY(), (int) -velocityTracker.getXVelocity(), (int) -velocityTracker.getYVelocity(), getLeftLimit(), getRightLimit(), getTopLimit(), getBottomLimit()); velocityTracker.recycle(); velocityTracker = null; break; } return true; }
In this Code, the first step is to let the multi-touch processing class handle the event. If the event is not processed here, it will be handled by the ordinary touch screen event (different from the multi-touch.
3) Scaling
public void zoomChanged(float newZoom, float oldZoom) { inZoom = true; stopScroller(); final float ratio = newZoom / oldZoom; invalidatePageSizes(); scrollTo((int) ((getScrollX() + getWidth() / 2) * ratio - getWidth() / 2), (int) ((getScrollY() + getHeight() / 2) * ratio - getHeight() / 2)); postInvalidate(); }
This should be an event triggered by zoomlistener. You can study the zoomlistener code.
4) scroll event handling
The onscrollchanged function is triggered when scrollto and scrollby are called. The code of this function is the basis of all documentview events, because other events will eventually call this code.
@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); // bounds could be not updated post(new Runnable() { public void run() { currentPageModel.setCurrentPageIndex(getCurrentPage()); } }); if (inZoom) { return; } // on scrollChanged can be called from scrollTo just after new layout applied so we should wait for relayout post(new Runnable() { public void run() { updatePageVisibility(); } }); }
Here, we can see that if you want to change the display content in documentview, it is implemented by changing the display of each page. Pay attention to the following functions when reading this Code:
void invalidatePageSizes() { if (!isInitialized) { return; } float heightAccum = 0; int width = getWidth(); float zoom = zoomModel.getZoom(); for (int i = 0; i < pages.size(); i++) { Page page = pages.get(i); float pageHeight = page.getPageHeight(width, zoom); page.setBounds(new RectF(0, heightAccum, width * zoom, heightAccum + pageHeight)); heightAccum += pageHeight; } }
The code at this end defines the size of each page. According to the Code in pagetreenode, this part of display is like this. The content in pages can be seen as a scroll that is connected together at the beginning and end of a page. documentview is equivalent to a magnifier where the magnifier is placed, display the content.
2. Page
To be honest, I have not figured out why to add a pagetreenode class after the page is displayed?
The page function is actually straightforward: displays the upper and lower boundaries of a page. When sliding to a page, the current page number is displayed in the middle of the page. (The pagetreenode value will overwrite the content of pagetreenode, A page number is displayed before the file content is displayed ).
3. pagetreenode
The pagetreenode class is used to display the file content, which is the actual content you can read on the screen.
The following functions show that the content in pagetreenode is displayed when the pagetreenode box is in line with the documentview box.
private boolean isVisible() { return RectF.intersects(documentView.getViewRect(), getTargetRectF()); }
But I didn't understand what those members, such as pageslicebounds, children, thresholdhit (), are doing. From the code of decodeservicebase, we can see that pageslicebounds has something to do with reading a file in a specific format (such as a PDF file), but where it is useful, only those codes that read the following pdf can be understood.