2014-03-01 68 views
2

我有一些本地html文件,我想用无限的滚动方法向他们展示。android无限滚动webview

注意:我不能改变html的内容,所以请不要建议给他们添加javascript。我必须在运行时间做到这一点。

因此,我发现我可以在运行时通过执行javascript

我重写了onOverScrolled()方法webView找出用户何时到达webView的末端。 (它的行为谨慎,所以问题不在这里)

问题是有些时候新内容成功附加和其他时间没有附加。

在日志中我可以看到,页面方法结束得到触发,检索新的html body被调用,执行javascript代码被调用,但它并没有影响。

这里是我的代码,可能是出事了,我不能看到它:

@Override 
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) 
{ 
    super.onOverScrolled(scrollX, scrollY, clampedX, clampedY); 
    if(clampedY & reloadFlag) //for first time realodFlag is false, when the WebViewClient.onPageFinished() get called it turn to ture 
    { 
     if (!(isVerticalScrollPossible(SCROLL_DOWN))) 
     { 
      reloadFlag = false; 
      currUri = nextResource(currUri); //findout next page 
      appendNextPage(); 
     } 

    } 
} 

private final int SCROLL_DOWN = 1; 
private final int SCROLL_UP = -1; 

private boolean isVerticalScrollPossible(int direction) 
{ 
    final int offset = computeVerticalScrollOffset(); 
    final int range = computeVerticalScrollRange() - computeVerticalScrollExtent(); 
    if (range == 0) return false; 
    if (direction < 0) { 
     return offset > 0; 
    } else { 
     return offset < range - 1; 
    } 
} 

public String getNextPageJS(Uri currPage) 
{ 
    String body = getNextPageBody(currPage); 
    //Log.d("myTAG", body); 
    String jsResult = "javascript:(function() { document.body.innerHTML += '<div id=\"separator\" style=\"height:10px; margin-top:10px; margin-bottom:10px; background-color:#000000;\"></div>" + body + "';})()"; 
    return jsResult; 
} 

private void appendNextPage() 
{ 
    reloadFlag = false; 
    Thread appendThread = new Thread(null, doAppend, "backgroundAppend"); 
    appendThread.start(); 
    Log.i("appendNextPage", "get called"); 
} 

public String rs = ""; 
private Runnable doAppend = new Runnable() 
{ 
    @Override 
    public void run() 
    { 
     Log.i("doAppend", "get called + currUri: " + currUri); 
     rs = getNextPageJS(currUri); 
     //loadUrl(rs); 
     appendHandler.sendEmptyMessage(0); 
    }  
}; 

private Handler appendHandler = new Handler() 
{ 
    public void handleMessage(Message msg) 
    { 
     loadUrl(rs); 
     reloadFlag = true; 
     Log.i("appendHandler", "get called");  
    } 
}; 

注意:有时我得到这个在模拟器日志(而不是在真实设备):

I/chromium(1339): [INFO:CONSOLE(1)] "Uncaught SyntaxError: An invalid or illegal string was specified.", source: http://localhost:1025/OEBPS/Text/Section0042.xhtml (1) 

页面的数量有时会不一样,可能是因为糟糕的javasccript代码,我不知道。

提示:

1)我不是JavaScript的编码器,所以可能是JavaScript代码不好

2)或致电也许javascript代码几次导致此问题

3)我知道JavaScript代码必须在页面加载完成后执行,所以也许代码调用太快了,问题在于onPageFinished()刚刚调用第一页,并且在通过JavaScript代码附加新内容时不会调用它,我试图用线程来解决这个问题,我认为它的工作。

更新:我觉得这个代码工作正常,当html身材很小,但是当我尝试附加大身体它不起作用。是loadUrl()方法有字符限制?或任何其他想法?

回答

0

好的,我发现问题,如果有人想知道。

的问题是loadUri()(在我的情况下,至少)不能一次(在JavaScript代码中,我写的)加载太多的HTML标记

所以,解决的办法是容易的,负载标签一个接一个。

这里是我使用的代码:

public ArrayList<String> getNextPageBody(Uri currAddress) 
{ 
    String html = getHtml(currAddress); // this is the all html tags in the next file 

    //get body elements as arrayList, using jsoup 
    Document doc = Jsoup.parse(html); 
    Elements elements = doc.select("body").first().children(); 
    ArrayList<String> chuncks = new ArrayList<String>(); 
    for (org.jsoup.nodes.Element el : elements) 
    { 
     chuncks.add(el.toString()); 
    } 

    return chuncks; 
} 

public void loadBodyChunk(ArrayList<String> bodyChunks) 
{  
    //show a separator for each page 
    bodyChunks.add(0, "javascript:(function() { document.body.innerHTML += '<div id=\"separator\" style=\"height:10px; margin-top:10px; margin-bottom:10px; background-color:#000000;\"></div>';}())"); 
    loadUrl(bodyChunks.get(0)); 

    for(int i = 1; i < bodyChunks.size(); i++) 
    { 
     String jsResult = "javascript:(function() { document.body.innerHTML += '" + bodyChunks.get(i) + "';}())"; 
     loadUrl(jsResult); 
    } 

    reloadFlag = true; 
} 

编辑:

也: 第一' S IN字符串应该是用\'取代:

body = body.replace("'", "\\'"); 

那么所有的换行字符应该被消除:

body = body.replaceAll(System.getProperty("line.separator"), " "); 

所有问题都解决了。