我想在加载WebView后对WebView进行快照。但是,返回的位图始终为null,因为即使我使用onPageFinished
,渲染也未完成加载。
我在互联网上搜索,人们建议使用WebView.PictureListener
,但此功能在API 12中已弃用。
一些代码
public class MainActivity extends Activity {
private WebView mButterflyWebView;
/**
* Gets html content from the assets folder.
*/
private String getHtmlFromAsset() {
InputStream is;
StringBuilder builder = new StringBuilder();
String htmlString = null;
try {
is = getAssets().open(getString(R.string.butterfly_html));
if (is != null) {
BufferedReader reader = new BufferedReader(
new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
htmlString = builder.toString();
}
} catch (IOException e) {
e.printStackTrace();
}
return htmlString;
}
/**
* Initializes views, controls...
*/
private void init() {
mButterflyWebView = (WebView) findViewById(R.id.butterfly_webview);
mButterflyWebView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress == 100){
if (capturePictureWebView() != null){
saveBitmapToFile(capturePictureWebView());
}
}
}
});
}
/**
* Loads html page with the content.
*/
private void loadHtmlPage() {
String htmlString = getHtmlFromAsset();
if (htmlString != null)
mButterflyWebView.loadDataWithBaseURL(
"file:///android_asset/images/", htmlString, "text/html",
"UTF-8", null);
else
Toast.makeText(this, R.string.no_such_page, Toast.LENGTH_LONG)
.show();
}
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
loadHtmlPage();
}
private Bitmap capturePictureWebView() {
mButterflyWebView.measure(MeasureSpec.makeMeasureSpec(
MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
mButterflyWebView.layout(0, 0, mButterflyWebView.getMeasuredWidth(),
mButterflyWebView.getMeasuredHeight());
mButterflyWebView.setDrawingCacheEnabled(true);
mButterflyWebView.buildDrawingCache();
if (mButterflyWebView.getMeasuredWidth() == 0 || mButterflyWebView.getMeasuredHeight() == 0){
return null;
}
Bitmap bm = Bitmap.createBitmap(720, 1280, Bitmap.Config.ARGB_8888);
System.out.println("width=" + mButterflyWebView.getMeasuredWidth());
System.out.println("height=" + mButterflyWebView.getMeasuredHeight());
Canvas bigcanvas = new Canvas(bm);
// bigcanvas.scale(720/mButterflyWebView.getMeasuredWidth(), 1280/mButterflyWebView.getMeasuredHeight());
Paint paint = new Paint();
int iHeight = bm.getHeight();
bigcanvas.drawBitmap(bm, 0, iHeight, paint);
mButterflyWebView.draw(bigcanvas);
return bm;
}
private void saveBitmapToFile(Bitmap bitmap) {
try {
FileOutputStream out = new FileOutputStream("/storage/sdcard0/a.png");
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:12)
您应该尝试使用WebChromeClient
并实施onProgressChanged
:
mButterflyWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int progress) {
if (progress == 100) {
// do screenshot
}
}
});
编辑:检查是否多次加载onPageStarted:
mButterflyWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.d("WebView", "onPageStarted " + url);
}
@Override
public void onPageFinished(WebView view, String url) {
Log.d("WebView", "onPageFinished " + url);
}
});
答案 1 :(得分:4)
您可以在WebView中执行此操作:
@Override
public void invalidate() {
super.invalidate();
if (getContentHeight() > 0) {
// WebView has displayed some content and is scrollable.
}
}
答案 2 :(得分:4)
检测页面是否已呈现的最佳方法是使用API 23中提供的onPageCommitVisible回调。onPageLoadFinished
不适合,因为它过早交付(处理HTML时,但尚未呈现)。
webview.setWebViewClient(new WebViewClient(){
@Override
public void onPageCommitVisible (WebView view,
String url)
}
}
答案 3 :(得分:2)
最后我得到了非常详细的问题。这解释了为什么它总是返回null位图。
我的应用中的每次更改都是由用户操作触发的,因此我想出了一个修改后的版本,只能在touchEvent 之后触发invalidate()
感谢您的帮助。
答案 4 :(得分:0)
调用OnPageFinshed方法或进度达到100%时,渲染器将无法完成渲染,因此这两种方法都不能保证您已完全渲染视图。
但是您可以从OnLoadResource方法中找出已经渲染的内容和仍在渲染的内容。而且此方法被调用了几次。
@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
// Log and see all the urls and know exactly what is being rendered and visible. If you wanna know when the entire page is completely rendered, find the last url from log and check it with if clause and implement your logic there.
if (url.contains("assets/loginpage/img/ui/forms/")) {
// loginpage is rendered and visible now.
// your logic here.
}
}
答案 5 :(得分:-2)
private class CfdWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.v(TAG, "shouldOverrideUrlLoading: " + url);;
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Log.v(TAG, "onPageFinished: " + url);
// do something
}
}
答案 6 :(得分:-2)
Kotlin 解决方案
第一个解决方案
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val webView : WebView = findViewById(R.id.webView)
webView.webViewClient = MyWebViewClient()
}
private class MyWebViewClient : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
println("Load Started")
}
override fun onPageFinished(view: WebView, url: String) {
println("Load Finished")
}
}
}
第二种解决方案
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val webView : WebView = findViewById(R.id.webView)
webView.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
println("Load Started")
}
override fun onPageFinished(view: WebView, url: String) {
println("Load Finished")
}
}
}