天天看点

[置顶] Android使用WebView加载图片防止OutOfMemoryError

分类:             Android总结              2013-06-09 16:01     571人阅读     评论(0)     收藏     举报     Android WebView加载图片 OutOfMemoryError Android大图片

在Android中, 大图片加载或者处理很容易出来OutOfMemory,也就是内存溢出

    所以在这里就使用WebView来加载大图片,但是WebView不好控制图片显示大小,也就是说

如果图片太大,webview将出一滚动条,图片过小则不可拉伸,极其影响美观。为此,作了些

修改,在一定区域内做一些图片尺寸的压缩。

    主要实现方式:由WebView的父控件居中布局来控制垂直方向的居中,WebView的元素居中

来控制图片的水平居中 ,最终达到图片在屏幕的中间显示。

核心Java代码如下:

[java] view plain copy print ?

  1. private void showImageByWebView(String path){  
  2.         webViewLayout = (LinearLayout) findViewById(R.id.img_webview);  
  3.         webView = new WebView(this);  
  4.         String url = "file://"+ path;  
  5.         int[] wh = new int[2];  
  6.         int disenty;//屏幕密度  
  7.         WindowManager wManager = this.getWindowManager();  
  8.         DisplayMetrics  disM = new DisplayMetrics();  
  9.         wManager.getDefaultDisplay().getMetrics(disM);    
  10.         disM = this.getResources().getDisplayMetrics();   
  11.         disenty = disM.disenty;  
  12.         wh[0] = dis.widthPixels;  
  13.         Rect outRect = new Rect();  
  14.         webViewLayout.getWindowVisibleDisplayFrame(outRect); //获取状态栏高度  
  15.         int contentHeight = (int) (wh[1] - this.getResources().getDimension(R.dimen.title_height) - outRect.top - 30); //获取webview应该显示的高度,屏幕高度减去标题栏高度和状态栏高度  
  16.         BitmapFactory.Options options = new BitmapFactory.Options();  
  17.         options.inJustDecodeBounds = true;   
  18.         BitmapFactory.decodeFile(path, options); // 因为设置了inJustDecodeBounds=true 所以此时返回的 bitmap 为 null,仅取出bitmap的信息,而不把它读到内存  
  19.         options.inJustDecodeBounds = false;    
  20.         int bitmapWidth = options.outWidth;   
  21.         int bitmapHeight = options.outHeight;   
  22.         String style = "";  
  23.         int[] imgDis = new int[2];  
  24.         int minHeight = getResources().getDimensionPixelSize(R.dimen.loadview_img_minheight);  
  25.         //注;由于webview将会设置settings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);表示单列所以宽度适应内容大小,所以宽度大于屏幕而高度小于屏幕时不需要再压缩  
  26.         if(bitmapHeight > (float)contentHeight/disenty){  
  27.             double scale = 0.00f;  
  28.             scale = (double)contentHeight / bitmapHeight;  
  29.             imgDis[0] = (int) (scale * bitmapWidth / (disenty + 0.1));//这里加上了0.1的原因与以上减30一样,webview宽高肯定大于图片内容所显示的宽度,里面还会有padding属性  
  30.             imgDis[1] = (int) (scale * bitmapHeight / (disenty + 0.1));  
  31.             style = "style=\"width: " + imgDis[0] + "px; height: " + imgDis[1] + "px;\"";  
  32.         }else if(bitmapHeight < minHeight){  
  33.             double scale = (double)minHeight/bitmapHeight ;  
  34.             int width = (int) (scale * bitmapWidth);  
  35.             style = "style=\"width: " + width / disenty + "px; height: " + minHeight / disenty + "px;\"";  
  36.         }  
  37.         StringBuffer data = new StringBuffer();  
  38.         data.append("<html><center><img src=\"")  
  39.                     .append(url)  
  40.                     .append("\" ")  
  41.                     .append(style)  
  42.                     .append("></center></html>");  
  43.         webView.loadDataWithBaseURL(url, data.toString(), "text/html","UTF-8","");  
  44.         webView.setScrollContainer(false);  
  45.         webView.setScrollbarFadingEnabled(false);  
  46.         WebSettings settings = webView.getSettings();  
  47.         settings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);  
  48.         settings.setBuiltInZoomControls(false); // 设置显示缩放按钮  
  49.         settings.setSupportZoom(true); //支持缩放  
  50.         //webView.setInitialScale(100);  
  51.         // settings.setUseWideViewPort(true); //双击放大,但是在这里如果放大将会有问题  
  52.         // settings.setLoadWithOverviewMode(true);//多窗口预览方式显示  
  53.         webView.setBackgroundColor(0x00000000);  
  54. //      View zoomControls = webView.getZoomControls();  
  55. //      LayoutParams paramszoom = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);  
  56. //      zoomControls.setLayoutParams(paramszoom);  
  57.         LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, Gravity.CENTER);  
  58.         params.width = LayoutParams.WRAP_CONTENT;  
  59.         params.height = LayoutParams.WRAP_CONTENT;  
  60.         webView.setMinimumHeight(500);  
  61.         webViewLayout.addView(webView, params);  
  62.     }  
private void showImageByWebView(String path){
		webViewLayout = (LinearLayout) findViewById(R.id.img_webview);
		webView = new WebView(this);
		
		String url = "file://"+ path;
		
		int[] wh = new int[2];
		int disenty;//屏幕密度
		WindowManager wManager = this.getWindowManager();
		DisplayMetrics  disM = new DisplayMetrics();
		wManager.getDefaultDisplay().getMetrics(disM);  
		disM = this.getResources().getDisplayMetrics();	
		disenty = disM.disenty;
		wh[0] = dis.widthPixels;
		Rect outRect = new Rect();
		webViewLayout.getWindowVisibleDisplayFrame(outRect); //获取状态栏高度
		int contentHeight = (int) (wh[1] - this.getResources().getDimension(R.dimen.title_height) - outRect.top - 30); //获取webview应该显示的高度,屏幕高度减去标题栏高度和状态栏高度
		
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true; 
		BitmapFactory.decodeFile(path, options); // 因为设置了inJustDecodeBounds=true 所以此时返回的 bitmap 为 null,仅取出bitmap的信息,而不把它读到内存
		options.inJustDecodeBounds = false;  
        
		int bitmapWidth = options.outWidth; 
		int bitmapHeight = options.outHeight; 
		
		String style = "";
		int[] imgDis = new int[2];
		int minHeight = getResources().getDimensionPixelSize(R.dimen.loadview_img_minheight);
		
		//注;由于webview将会设置settings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);表示单列所以宽度适应内容大小,所以宽度大于屏幕而高度小于屏幕时不需要再压缩
		if(bitmapHeight > (float)contentHeight/disenty){
			double scale = 0.00f;
			scale = (double)contentHeight / bitmapHeight;
			imgDis[0] = (int) (scale * bitmapWidth / (disenty + 0.1));//这里加上了0.1的原因与以上减30一样,webview宽高肯定大于图片内容所显示的宽度,里面还会有padding属性
			imgDis[1] = (int) (scale * bitmapHeight / (disenty + 0.1));
			style = "style=\"width: " + imgDis[0] + "px; height: " + imgDis[1] + "px;\"";
		}else if(bitmapHeight < minHeight){
			double scale = (double)minHeight/bitmapHeight ;
			int width = (int) (scale * bitmapWidth);
			style = "style=\"width: " + width / disenty + "px; height: " + minHeight / disenty + "px;\"";
		}

		StringBuffer data = new StringBuffer();
		data.append("<html><center><img src=\"")
					.append(url)
					.append("\" ")
					.append(style)
					.append("></center></html>");

		webView.loadDataWithBaseURL(url, data.toString(), "text/html","UTF-8","");
		webView.setScrollContainer(false);
		webView.setScrollbarFadingEnabled(false);
		
		WebSettings settings = webView.getSettings();
		settings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
		settings.setBuiltInZoomControls(false); // 设置显示缩放按钮
		settings.setSupportZoom(true); //支持缩放
		//webView.setInitialScale(100);
		
		// settings.setUseWideViewPort(true); //双击放大,但是在这里如果放大将会有问题
		// settings.setLoadWithOverviewMode(true);//多窗口预览方式显示
		
		webView.setBackgroundColor(0x00000000);
	
//		View zoomControls = webView.getZoomControls();
//		LayoutParams paramszoom = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
//		zoomControls.setLayoutParams(paramszoom);
		
		LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, Gravity.CENTER);
		params.width = LayoutParams.WRAP_CONTENT;
		params.height = LayoutParams.WRAP_CONTENT;
		webView.setMinimumHeight(500);
		webViewLayout.addView(webView, params);
	}
           

核心布局代码如下:

[html] view plain copy print ?

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.     <!-- .....-->  
  7.     <LinearLayout   
  8.         android:id="@+id/img_webview"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="fill_parent"  
  11.         android:layout_centerInParent="true"  
  12.         android:minHeight="200dip"  
  13.         android:minWidth="200dip"  
  14.         android:gravity="center"  
  15.         android:paddingTop="@dimen/title_normal_height"  
  16.         />  
  17. </RelativeLayout>  
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

	<!-- .....-->
    
        
    <LinearLayout 
        android:id="@+id/img_webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
		android:layout_centerInParent="true"
		android:minHeight="200dip"
        android:minWidth="200dip"
        android:gravity="center"
        android:paddingTop="@dimen/title_normal_height"
        />

</RelativeLayout>