当使用Crosswalk来显示网页时,如何将整个视图捕获到位图中?

12

我使用CrossWalk来展示网页,它的表现很不错。我有一个功能想要将整个内容捕获为位图并保存到SD卡中,但我找不到解决方案。使用TextureView只能够捕获屏幕大小的位图,有人遇到了同样的问题吗?另外,我可以使用WebView.draw()来捕获整个内容。

3个回答

3

以下是一些伪代码,可以帮助解决问题。您可以从 webview 中获取内容的高度和宽度,然后使用 webview.draw() 方法...就像下面的示例一样:

Bitmap  bitmap = Bitmap.createBitmap( webView.getWidth(), webView.getContentHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
webView.draw(canvas);

接下来,您可以使用bitmap.compress将位图文件输出并将其输出到文件输出流中。

//fos是FileOutputStream,如果需要可以使用其他内容。 bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);

我预见到的唯一问题是,由于WebView没有获取内容宽度的方法,因此您的位图可能会水平剪裁内容。否则,我认为这应该可以工作。


我使用这种方法来捕获WebView内容,但在CrossWalk WebView上无法正常工作。 - handrenliang
我不熟悉Crosswalk,但看了他们的文档后,很明显这行不通。非常抱歉。XWalkView是FrameLayout的子类,而不是WebView。有什么阻止你将HTML加载到WebView并从那里保存它的方法吗? - Developer Paul
如您所知,4.4以下的WebView使用Webkit渲染页面,效果差。我创建了一个超文本编辑器,在4.4以下的版本中无法正常工作。 - handrenliang
能否将HTML内容适应用户屏幕大小,然后使用传统的方法保存位图,就像在视图中一样?如果您可以将内容适应屏幕,则理论上应该能够将所有内容适应图片中。 - Developer Paul
这并没有捕捉到需要滚动的Webview的不可见部分。 - Mneckoee

3

我以前从未使用过Crosswalk,但我猜测Crosswalk WebView也是从android.view.View继承而来。如果是这样的话,你可以使用android视图绘制缓存。它看起来像这样:

yourWebView.setDrawingCacheEnabled(true);
Bitmap bmp = yourWebView.getDrawingCache();

那么,就像Paul所说的那样,通过FileOutputStream将其保存。
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);

getDrawingCache() 只能获取 WebView 的一部分内容,而不是整个页面的内容。 - handrenliang

2

如上述答案所述,您无法通过标准方式捕获XWalkView图像,因为Crosswalk XWalkView使用硬件层(即SurfaceView或TextureView)。但是,您可以使用TextureView类的getBitmap()方法来获取它。

简而言之,在初始化XWalkView之前(例如在Application子类中),您应该启用在Crosswalk中使用TextureView:

XWalkPreferences.setValue(XWalkPreferences.ANIMATABLE_XWALK_VIEW, true);

在视图树中找到TextureView,然后调用它的getBitmap()方法。

类似这样:

/**
    * Returns TextureView which is used in XWalkView
    *
    * @param group
    * @return
    */
private TextureView findXWalkTextureView(ViewGroup group) {
    int childCount = group.getChildCount();
    for (int i = 0; i < childCount; i++) {
        View child = group.getChildAt(i);
        if (child instanceof TextureView) {
            String parentClassName = child.getParent().getClass().toString();
            boolean isRightKindOfParent = (parentClassName.contains("XWalk"));
            if (isRightKindOfParent) {
                return (TextureView) child;
            }
        } else if (child instanceof ViewGroup) {
            TextureView textureView = findXWalkTextureView((ViewGroup) child);
            if (textureView != null) {
                return textureView;
            }
        }
    }

    return null;
}

/**
    * Example of capturing image from XWalkView based on TextureView
    *
    * @return
    */
public Bitmap captureImage() {
    if (mXWalkView != null) {
        Bitmap bitmap = null;

        boolean isCrosswalk = false;
        try {
            Class.forName("org.xwalk.core.XWalkView");
            isCrosswalk = true;
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (isCrosswalk) {
            try {
                TextureView textureView = findXWalkTextureView(mXWalkView);
                bitmap = textureView.getBitmap();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            bitmap = Bitmap.createBitmap(mXWalkView.getWidth(), mXWalkView.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas c = new Canvas(bitmap);
            mXWalkView.draw(c);
        }

        return bitmap;
    } else {
        return null;
    }
}

请查看此代码:https://github.com/gitawego/cordova-screenshot/blob/master/src/android/Screenshot.java 以了解更多详情。


我想要捕捉整个视图而不是其中的一部分屏幕。 - handrenliang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接