在android中渲染epub书?

时间:2011-12-15 10:03:17

标签: android webview render epub

我试着在android pad中显示epub书。我可以解析html和css,以显示书的内容和格式,也许书中包含图片,似乎我有两个选项:

  1. 使用Webview。
  2. 编写客户视图,以便它可以呈现html / css ---这似乎是一项非常复杂的任务。
  3. 哪种方式好?如果我必须使用WebView,那么分页逻辑怎么样,因为webview在一个页面中解析一个html文件,我在webview中找不到分页符。

3 个答案:

答案 0 :(得分:6)

我为android和ios开发了一个原生的epub播放器

我在此处分享的代码是我的产品源代码的一部分,复制和粘贴它不适合您。将其视为参考。

我在android中使用webview,在ios中使用uiwebview进行自定义视图和解析html/css几乎就像开发一个新的渲染引擎(即浏览器)。这是一个繁琐而复杂的。

简单地说,我为你提供了我为android

所采取的步骤
  • 创建自定义网页视图
  • 加载url并编写回调客户端(WebViewClient,WebChromeClient)
  • 在webview加载后使用以下方法进行分页

代码:

private class MyWebClient extends WebViewClient
    {
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
        }
        @Override
        public void onPageFinished(WebView view, String url) 
        {
            super.onPageFinished(view, url);

            final MyWebView myWebView = (MyWebView) view;

            String varMySheet = "var mySheet = document.styleSheets[0];";

                String addCSSRule = "function addCSSRule(selector, newRule) {"
                        + "ruleIndex = mySheet.cssRules.length;"
                        + "mySheet.insertRule(selector + '{' + newRule + ';}', ruleIndex);"

                        + "}";

                String insertRule1 = "addCSSRule('html', 'padding: 0px; height: "
                        + (myWebView.getMeasuredHeight()/getContext().getResources().getDisplayMetrics().density )
                        + "px; -webkit-column-gap: 0px; -webkit-column-width: "
                        + myWebView.getMeasuredWidth() + "px;')";

                myWebView.loadUrl("javascript:" + varMySheet);
                myWebView.loadUrl("javascript:" + addCSSRule);
                myWebView.loadUrl("javascript:" + insertRule1);



        }
    }

private class MyWebChromeClient extends WebChromeClient
    {
        @Override
        public void onProgressChanged(WebView view, int newProgress) 
        {
            super.onProgressChanged(view, newProgress);
            //  GlobalConstants.ENABLE_WEB_VIEW_TOUCH = false;
            if(newProgress == 100)
            {
                postDelayed(new Runnable() 
                {
                    @Override
                    public void run() 
                    {
                        calculateNoOfPages();

                    }
                },300);
            }
        }
    }

private void calculateNoOfPages()
    {

        if(getMeasuredWidth() != 0)
        {
            int newPageCount = computeHorizontalScrollRange()/getMeasuredWidth();
        }
    }

将jquery.js注入webview:

private void addJQueryJS() 
    {
        String path = "file:///android_asset/JSLibraries/jquery.min.js";
        String data = "{\"MethodName\":\"onJQueryJSLoaded\",\"MethodArguments\":{}}";
        String callBackToNative  = " jsInterface.callNativeMethod('jstoobjc:"+data+"');";
        String script = "function includeJSFile()"
                               +"{"
                               +"function loadScript(url, callback)"
                               +"{"
                               +"var script = document.createElement('script');"
                               +"script.type = 'text/javascript';"
                               +"script.onload = function () {"
                               +"callback();"
                               +"};"
                               +"script.src = url;"
                               +"if(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0])"
                               +"{"
                               +"(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(script);"
                               +"}"
                               +"else { callback(); }"
                               +"}"
                               +"loadScript('"+path+"', function ()"
                               +"{"
                               +callBackToNative
                               +"});"
                               +"} ; includeJSFile();";
        loadUrl("javascript: "+script);
    }
  • 将所有单词包装成跨度 - 用于突出显示文本并导航到页面。
  • 将有3个网页浏览量 - 当前页面,下一页面和上一页面。您应该根据该章节的页数设置偏移到webview滚动。 假设一个.html文件的内容为3页 - 以前的webview是第一页,当前的webview是第二页,下一个webview是第三页,但是所有的webview加载了相同的url。但是它们的内容偏移是不同的。
  • 编写自己的页面滑动逻辑而不是使用viewpager。只需将当前页面传递给适配器,然后适配器将返回下一页和上一页。通过一些计算。

代码:

@Override
    public PageView getPreviousView(PageView oldPage) 
    {
        MyWebView oldWebView = ((PageView)oldPage).getWebView();

        int chapterIndex = oldWebView.getData().getIndexOfChapter();
        int pageIndex = oldWebView.getData().getIndexOfPage();
        int pageCount = oldWebView.getData().getChapterVO().getPageCount();
        pageIndex--;
        if(pageIndex < 0)
        {
            pageIndex = 0;
            chapterIndex--;
            if(chapterIndex<0)
            {
                //return the same page
                chapterIndex = 0;
                return null;
            }
            else
            {
                //previous chapter last page
                PageView pageView = new PageView(oldPage.getContext(),_mViewPager);
                MyWebView webView= pageView.getWebView();

                PageVO data = new PageVO();
                data.setChapterVO(_chaptersColl.get(chapterIndex));
                data.setIndexOfChapter(chapterIndex);
                data.setIndexOfPage(-2);

                webView.setData(data);
                return pageView;
            }
        }
        else if(pageIndex <= pageCount-1)
        {
            //same chapter previous page
            PageView pageView = new PageView(oldPage.getContext(),_mViewPager);
            MyWebView webView= pageView.getWebView();

            PageVO data = new PageVO();
            data.setChapterVO(_chaptersColl.get(chapterIndex));
            data.setIndexOfChapter(chapterIndex);
            data.setIndexOfPage(pageIndex);

            webView.setData(data);
            return pageView;
        }
        return oldPage;
    }

    @Override
    public PageView getNextView(PageView oldPage) 
    {
        MyWebView oldWebView = ((PageView)oldPage).getWebView();
        int chapterIndex = oldWebView.getData().getIndexOfChapter();
        int pageIndex = oldWebView.getData().getIndexOfPage();
        int pageCount = oldWebView.getData().getChapterVO().getPageCount();
        pageIndex++;
        if(pageIndex>=pageCount)
        {
            pageIndex=0;
            chapterIndex++;
            if(chapterIndex>=_chaptersColl.size())
            {
                //end of the chapters and pages so return the same page
                chapterIndex--;
                return null;
            }
            else
            {
                //next chapter first page
                PageView pageView = new PageView(oldPage.getContext(),_mViewPager);
                MyWebView webView= pageView.getWebView();

                PageVO data = new PageVO();
                data.setChapterVO(_chaptersColl.get(chapterIndex));
                data.setIndexOfChapter(chapterIndex);
                data.setIndexOfPage(pageIndex);

                webView.setData(data);

                return pageView;
            }
        }
        else
        {
            //next page in same chapter
            PageView pageView = new PageView(oldPage.getContext(),_mViewPager);
            MyWebView webView= pageView.getWebView();

            PageVO data = new PageVO();
            data.setChapterVO(_chaptersColl.get(chapterIndex));
            data.setIndexOfChapter(chapterIndex);
            data.setIndexOfPage(pageIndex);
            //data.setPageCount(pageCount);

            webView.setData(data);

            return pageView;
        }
    }

无需使用任何第三方库。需要花费大量时间来编写自己的所有东西。

答案 1 :(得分:4)

好一个,但问题是...... :-)

我不认为Android webview的任何分页符逻辑是可用的,根据您的关注,WebView是显示.epub文件的好选择(您可以添加许多功能,如突出显示,搜索,书签等)。如果你发现那个,那么如果设备大小改变了。我正在做的是,我只是在webview中显示WebPage并禁用滚动,然后我可以找到webview的最大高度,以及设备屏幕大小(高度和宽度),现在我为下一页和上一页放了两个按钮,这只是根据设备大小的高度滚动页面..

容易的东西..如果你想要试试这个......(这是我个人的意见,可能是我错了)

答案 2 :(得分:4)

这个javascript库可以解决分页问题

http://monocle.inventivelabs.com.au/

这个项目在android中使用它

https://github.com/sharathpuranik/chaek-android

获取源代码并查看。