2017-02-09 10 views
2

私はAndroidサービスのWebレンダリングメカニズムとして機能するWebViewが必要なアプリケーションを作成しています。 WebViewがウィンドウに添付されることはありません。 しかし、ビュー(ViewGroup)を手作業で測定してレイアウトし、それをビットマップに描画することで、ビュー階層に配置することなくページのスナップショットを生成することができます。私はscrollTo()へのコールを行う一度scrollTo()の後にAndroid WebViewが破損しています

問題があり、スクロール前に隠されて、それをトリミングしたページの一部を描画しませんビュー、この

scrolled a bit along x and y axis as well

のようなもの

ページのロードは、以下のコード

を用い

private void layout(
     @NonNull final WebView webView, final int targetWidth, final int targetHeight) { 
    webView.measure(
      View.MeasureSpec.makeMeasureSpec(targetWidth, View.MeasureSpec.AT_MOST), 
      View.MeasureSpec.makeMeasureSpec(targetHeight, View.MeasureSpec.AT_MOST)); 

    webView.layout(0, 0, targetWidth, targetHeight); 
} 

ビットマップがキャプチャされる次のような方法を使用して、要求されたのWebViewがレイアウトされるずっと前私は通常、私はそれをしたい場所のWebViewがスクロールされますアクティビティ内窓に取り付けたのWebView内のページをロードしたときにページがある:

private Bitmap capture(
     @NonNull final WebView webView) { 
    webView.setDrawingCacheEnabled(true); 
    webView.buildDrawingCache(); 

    final Bitmap bitmap = Bitmap.createBitmap(
      webView.getWidth(), webView.getHeight(), Bitmap.Config.ARGB_8888); 

    final Canvas canvas = new Canvas(bitmap); 
    webView.draw(canvas); 

    webView.setDrawingCacheEnabled(false); 

    return bitmap; 
} 

は、全体的な手順は、これが重要

layout(mWebView, maxWidth, maxHeight); 
// page is loaded 
mWebView.scrollTo(...); 
// here I've tried number of things like mWebView.invalidate(), mWebView.requestLayout() or mWebView.refreshDrawableState() 
final Bitmap bitmap = capture(mWebView); 

のようになりますうまく表示されます。

違いは何ですか?これは、WebViewがアクティビティのウィンドウにアタッチされているとき、アンドロイドとWebViewとはどのような違いがありますか?

+0

'WebView'は、ウィンドウにアタッチされていないことが検出された場合、それ自体を再描画しない最適化を採用していると確信しています。 WebViewで 'invalidate()'を呼び出そうとしましたか?多分それは完全な再描画を強制するかもしれません... –

+0

応答に感謝します。はい、あります。 私はrequestLayout()を試しただけでなく、ページが読み込まれた後の短い(〜1秒)タイムアウトの後にこれをやっています。 – foo

+0

WebView、WebViewChromiumなど、何が起こっているのかを正確に理解するのは難しいですが、図面やスクロール機能の中にはWebViewをUIスレッド上で実行する必要がある/表示階層にアタッチする必要があることがあります。さらに、 'View.invalidate()'のように見えます(表示されない場合はスキップします)(http://grepcode.com/file/repository)。grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/view/View.java#View.skipInvalidate%28%29) –

答えて

0

これを試してみてください。 ビットマップを作成した私の仕組みは、WebViewが描画キャッシュを有効にしてキャンバス上に描画するという事実に依存していました。

描画キャッシュは有効になっていますが、スクロール変更後に更新されませんでした。ビューの状態のみが変更されたためです。

ビューレンダリングでHWアクセラレーションを有効にしているので、描画キャッシュを有効にして、新しいビットマップが必要なときにだけ使用するだけです(ビューを無効にする必要はありません私はスクロール位置を設定した後、目的)。だから、それはすべての非常に簡単である

public void init() { 
    mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null); 
    mWebView.setDrawingCacheEnabled(true); 
    // (layout the view) 
} 

public void capture(...) { 
    mWebView.scrollTo(...); 
    final Bitmap capturedBitmap = mWebView.getDrawingCache(); 
    // do sth with the bitmap 
    // ... 
} 

だから、解決策は次のようになります。

+0

これはお返事ありがとうございますが、これは役に立たなかった。 – foo

1

:-) ...

mWebView.scrollTo(...); 

webView.setDrawingCacheEnabled(true); 
webView.buildDrawingCache();//write these lines before posting the capture event 

new Handler.post(){ 
    new Runnable(){ 
     public void run(){ 
      final Bitmap bitmap = capture(mWebView); 
     } 
    } 
} 

それはあなたの問題を解決する可能性があります、私は最終的に、このために根本的な原因を見つけた -

関連する問題