android項目源碼解析03——vudroid閱讀器源碼解析03:檔案內容顯示

來源:互聯網
上載者:User

       本文要講的是,vudroid閱讀器選擇某個檔案後,如何展示該檔案的內容。

       這裡不涉及vudroid是如何讀取檔案內容的,只是涉及讀取到檔案內容後,如何展示這些內容。

       這裡涉及到三個類:DocumentView,Page,PageTreeNode。

       DocumentView我們可以認為是一個顯示容器,它裡面存放的內容是一個個的頁(Page),而每個頁是由若干個PageTreeNode組成的。

       因此,我們可以看到,DocumentView只是負責處理觸控螢幕時間、按鈕時間、滾動事件,當然這裡還涉及到放大縮小這個功能的處理;而Page是包括一頁的內容,包括頁邊界、常值內容等;PageTreeNode中存放的才是真正的常值內容。

1、DocumentView

        這裡要做的內容包括按鍵處理、觸控螢幕事件處理(支援多點觸摸)、放大縮小功能處理、scroll事件處理:

1)按鍵事件處理,這裡你按上下左右鍵,頁面內容是可以上下左右移動的。

@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)觸控螢幕事件處理(這裡由於引入了多點觸摸的庫,因此是支援多點觸摸的)

第一段代碼時倒入多點觸摸的庫

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);        }    }

第二段代碼是處理觸控螢幕事件

 @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;    }

        這段代碼中,首先是讓多點觸摸的處理類處理事件,如果該事件在這裡不被處理,則按普通觸控螢幕事件(區別於多點觸摸)處理。

3)、縮放功能處理

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();    }

這個應該是由ZoomListener觸發的事件,具體可以研究下ZoomListener的代碼。

4)scroll事件處理

        只要調用了scrollTo和scrollBy都會觸發onScrollChanged函數。該函數的代碼是所有DocumentView事件的基礎,因為其他事件最終都會調用這一個代碼。

@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();            }        });    }

        這裡我們看到,DocumentView中要改變顯示內容的話,最終都是通過更改每個Page的顯示來實現的。讀這一段代碼的時候要注意以下這段函數:

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;        }    }

        這一端代碼定義每一頁的大小。根據PageTreeNode中的代碼判斷,這一部分顯示是這樣的,pages中的內容,我們可以看作是一頁頁首尾連在一起的捲軸,DocumentView相當於一個放大鏡,這個放大鏡放到什麼地方,就顯示什麼內容。

2、page

        說實在的,我沒有搞清楚有了page以後,讓page來顯示內容就可以了,為什麼要加一個PageTreeNode類?

        page類的功能實際上很直白:顯示一頁內容的上下分界線,滑動到某頁時在其中間顯示當前頁數(這個黑體頁數值會被PageTreeNode的內容覆蓋,可以認為是檔案內容沒有顯示之前,先顯示一個頁數值)。

3、PageTreeNode

        PageTreeNode類是用來顯示檔案內容的,就是你在螢幕上看得到的實實在在的閱讀內容。

       從以下函數知道PageTreeNode中的內容在PageTreeNode的方框與documentView的方框有交集時可以顯示。

private boolean isVisible() {        return RectF.intersects(documentView.getViewRect(), getTargetRectF());    }

     但是我沒弄明白pageSliceBounds、children、thresholdHit()等等這些成員是拿來做什麼的。從DecodeServiceBase的代碼中可以看出pageSliceBounds與讀取具體某種格式的檔案(如pdf檔案)有關係,但其具體在什麼地方有用,也只有等閱讀以下讀取pdf的那些代碼才能搞明白了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.