在android中渲染epub书?

Posted

技术标签:

【中文标题】在android中渲染epub书?【英文标题】:render the epub book in android? 【发布时间】:2012-01-21 00:58:39 【问题描述】:

我正在尝试在 android pad 中显示 epub 书。我可以解析html和css,为了显示书的内容和格式,也许书里有图片,看来我有两个选择:

    使用 Webview。 编写一个客户视图,以便它可以呈现 html/css --- 这似乎是一项非常复杂的任务。

什么是好方法?如果我必须使用WebView,那么分页逻辑怎么样,因为webview在一页中解析一个html文件,我在webview中找不到分页符。

【问题讨论】:

【参考方案1】:

我为安卓和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 addCs-s-rule = "function addCs-s-rule(selector, newRule) "
                        + "ruleIndex = mySheet.cssRules.length;"
                        + "mySheet.insertRule(selector + '' + newRule + ';', ruleIndex);"

                        + "";

                String insertRule1 = "addCs-s-rule('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:" + addCs-s-rule);
                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);
    
将所有单词包装成 span - 用于突出显示文本和导航到页面。 将有 3 个 webviews - 当前页、下一页和上一页。您应该根据该章节的页数设置 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;
        
    

无需使用任何第三方库。只需花费大量时间编写自己的所有内容。

【讨论】:

#Uday Sravan,我是 android 上的 epub 开发新手,在过去的 3 周里,我一直在尝试 Android ePub 分页和页面转换的几种选项。只有您的答案似乎可以正常工作。我可以让一些示例代码工作吗? 你能告诉我,我应该什么时候调用 addJQueryJS() ?是在将 HTML 页面加载到 webview 之后还是之前?【参考方案2】:

不错,但有问题... :-)

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

一些简单的..如果你想试试这个...(这是我的个人意见,可能我错了)

【讨论】:

是的,webview 提供了这么多功能。 你能举个例子说明在 epub 文件中使用 webview 的搜索和书签功能吗 文字在底部和顶部被截断如何处理?【参考方案3】:

有一个处理分页问题的 javascript 库

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

本项目在android中使用

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

获取源代码并查看。

【讨论】:

以上是关于在android中渲染epub书?的主要内容,如果未能解决你的问题,请参考以下文章

android - 从 webview 中获取文本

Epub 固定布局在纵向中不是全屏

我用的是iphone4我有电子书都是TXT格式的怎么转化成epub格式的?

关于计算机学习的书(doc,mobi,epub,pdf四种格式)

如何根据屏幕大小将Epub Html拆分为多个页面

是否有任何EPUB库动作脚本(adobe air)?