android项目源码解析03——vudroid阅读器源码解析03:文件内容显示


本文要讲的是,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的那些代码才能搞明白了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值