在 Android 中从 HTML 生成位图
Posted
技术标签:
【中文标题】在 Android 中从 HTML 生成位图【英文标题】:Generate bitmap from HTML in Android 【发布时间】:2011-06-05 18:15:47 【问题描述】:如何?
可以使用WebView
还是有更好的方法(比如直接使用WebView
渲染引擎)?怎么样?
我想实现以下方法...
public Bitmap toBitmap(Context context, String html, Rect rect);
...html
是要渲染的 html,rect
是所需位图的框架。
【问题讨论】:
您可以考虑再添加几百个词来解释“从 HTML 生成动态位图”的含义。 简而言之,我想从呈现的 HTML 生成位图。我删除了“动态”并重新措辞以防令人困惑。 FWIW,这是我的解决方案尝试:***.com/a/41354684/6684508 【参考方案1】:一种使用 WebView 从 HTML 字符串生成位图的同步方法,可以在 AsyncTask 中使用:
public Bitmap getBitmap(final WebView w, int containerWidth, int containerHeight, final String baseURL, final String content)
final CountDownLatch signal = new CountDownLatch(1);
final Bitmap b = Bitmap.createBitmap(containerWidth, containerHeight, Bitmap.Config.ARGB_8888);
final AtomicBoolean ready = new AtomicBoolean(false);
w.post(new Runnable()
@Override
public void run()
w.setWebViewClient(new WebViewClient()
@Override
public void onPageFinished(WebView view, String url)
ready.set(true);
);
w.setPictureListener(new PictureListener()
@Override
public void onNewPicture(WebView view, Picture picture)
if (ready.get())
final Canvas c = new Canvas(b);
view.draw(c);
w.setPictureListener(null);
signal.countDown();
);
w.layout(0, 0, rect.width(), rect.height());
w.loadDataWithBaseURL(baseURL, content, "text/html", "UTF-8", null);
);
try
signal.await();
catch (InterruptedException e)
e.printStackTrace();
return b;
它有一些限制,但这是一个开始。
【讨论】:
一个复杂的开始。【参考方案2】:您可以使用 draw 方法让它在您选择的位图中绘制。我举了一个例子,不要忘记清单的互联网和外部存储权限:
public class MainActivity extends Activity
private WebView mWebView;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
mWebView = new WebView(this);
setContentView(mWebView);
mWebView.loadUrl("http://tea.ch");
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
if (keyCode != KeyEvent.KEYCODE_BACK) return super.onKeyDown(keyCode, event);
Bitmap bm = Bitmap.createBitmap(200, 300, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
mWebView.draw(c);
OutputStream stream = null;
try
stream = new FileOutputStream(Environment.getExternalStorageDirectory() +"/teach.png");
bm.compress(CompressFormat.PNG, 80, stream);
if (stream != null) stream.close();
catch (IOException e)
finally
bm.recycle();
return super.onKeyDown(keyCode, event);
【讨论】:
那么有没有办法跳过WebView直接使用它的渲染引擎呢? 它是一个视图,你只能保留它的一个实例作为渲染引擎。您必须自己设置渲染为Layout参数的大小,例如:LayoutParams params = new LayoutParams(500,500); mWebView.setLayoutParams(params); mWebView.layout(0, 0, 500, 500); 我刚测试过,只需要设置mWebView.layout(0, 0, 500, 500); +1 用于测试。 :) 如果可行,将尝试接受答案。 不幸的是,此解决方案仅适用于活动内部。你知道如何在工作线程中实现它吗?【参考方案3】:为什么不使用 WebView 方法:capturePicture(),它返回一个图片并且从 API 级别 1 开始可用?
它返回整个文档的图片。
然后您可以使用矩形裁剪结果并从那里保存位图。
【讨论】:
请注意,capturePicture()
在 API 级别 19 中已弃用:developer.android.com/reference/android/webkit/…【参考方案4】:
这个例子展示了如何抓取webView内容的最后一张图片(等待webview完成渲染图片),它是一个使用Android将HTML转换为PNG的例子
活动代码
public class HtmlViewer extends Activity
private String HTML;
private Context ctx;
private Picture pic = null;
private int i=0; suppose this is the last pic
private int oldi = 0;
private Timer myTimer; // timer for waiting until last picture loaded
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_html_viewer);
Intent intent = getIntent();
HTML = intent.getStringExtra("HTML");
ctx = this;
WebView wv = (WebView)findViewById(R.id.webView1);
wv.setPictureListener(new PictureListener()
public void onNewPicture(WebView view, Picture picture)
Log.w("picture", "loading.." + String.valueOf(view.getProgress()));
pic = picture;
i++;
);
wv.loadData(HTML, "text/html; charset=utf-8", null);
wv.setWebViewClient(new WebViewClient()
public void onPageFinished(WebView wv, String url)
Picture p = wv.capturePicture();
myTimer = new Timer();
myTimer.schedule(new TimerTask()
@Override
public void run()
if (i > oldi)
oldi = i;
else
if (i != 0)
Log.w("picture", "finished");
cancel();
Picture picture = pic;
Log.w("picture", "onNewPicture- Height"+ picture.getHeight());
Log.w("picture", "onNewPicture- Width"+ picture.getWidth());
File sdCard = Environment.getExternalStorageDirectory();
if (picture != null)
Log.w("picture", " P OK");
Bitmap image = Bitmap.createBitmap(picture.getWidth(),picture.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(image);
picture.draw(canvas);
Log.w("picture", "C OK");
if (image != null)
Log.w("picture", "I OK");
ByteArrayOutputStream mByteArrayOS = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 90, mByteArrayOS);
try
File file = new File(sdCard, "AccountView.PNG");
FileOutputStream fos = new FileOutputStream(file);
fos.write(mByteArrayOS.toByteArray());
fos.flush();
fos.close();
Log.w("picture", "F OK " + String.valueOf(mByteArrayOS.size()) + " ? " + String.valueOf(file.length()));
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
Uri screenshotUri = Uri.fromFile(file);
sharingIntent.setType("image/png");
sharingIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.ACCOUNT_VIEW_TITLE)));
((Activity)ctx).finish();
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
, 0, 1000);
Log.w("picture", "done");
loadcompleted = true;
);
@Override
public boolean onCreateOptionsMenu(Menu menu)
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_html_viewer, menu);
return true;
布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:orientation="vertical"
tools:context=".HtmlViewer" >
<WebView
android:id="@+id/webView1"
android:layout_
android:layout_ />
【讨论】:
【参考方案5】:这是一个很好的库,可用于将任何 HTML 内容转换为位图。
同时支持 URL 和 HTML 字符串
https://github.com/iZettle/android-html2bitmap
【讨论】:
以上是关于在 Android 中从 HTML 生成位图的主要内容,如果未能解决你的问题,请参考以下文章
当我在我的 android 应用程序中从图库中加载图像时,为啥位图返回较小的图像?