当前位置: 代码迷 >> Android >> 【Android】读取sdcard卡上的所有图片而且显示,读取的过程有进度条显示
  详细解决方案

【Android】读取sdcard卡上的所有图片而且显示,读取的过程有进度条显示

热度:5   发布时间:2016-04-28 00:11:41.0
【Android】读取sdcard卡上的所有图片并且显示,读取的过程有进度条显示

虽然下面的app还没有做到快图浏览、ES文件浏览器的水平,遇到大sdcard还是会存在读取过久、内存溢出等问题,但是基本思想是这样的。

如下图,在sdcard卡上有4张图片,


打开app,则会吧sd卡上的所有图片读取,并显示出来,读取的过程有进度条显示。


制作过程如下:

1、首先,res\values\strings.xml对字符设置如下,没有什么特别的。

<?xml version="1.0" encoding="utf-8"?><resources>    <string name="app_name">读取sdcard下的所有图片</string>    <string name="action_settings">Settings</string>    <string name="imageView_description">大图</string>  </resources>
2、之后,修改res\layout\activity_main.xml形成布局,这里采用布局与《【Android】画廊式的图片浏览器,使用HorizontalScrollView取代Gallery,OnClickListener的参数传递》(点击打开链接)是一模一样的,只是这里,HorizontalScrollView旗下的LinearLayout改为用Java代码生成,故对HorizontalScrollView赋予id。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <ImageView        android:id="@+id/imageView1"        android:layout_width="match_parent"        android:layout_height="200dp"        android:contentDescription="@string/imageView_description"        android:paddingTop="10dp" />    <HorizontalScrollView        android:id="@+id/horizontalScrollView1"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_gravity="center_vertical"        android:scrollbars="horizontal" >    </HorizontalScrollView></LinearLayout>

3、然后,与《【Android】读取sdcard上的图片》(点击打开链接)一样,在AndroidManifest.xml插入<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />与<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />要求对sdcard读取与写入的权限,这个文件修改之后如下:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.asyncread"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="18" />    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- 要求向SDCard读取数据权限 -->    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 要求向SDCard写入数据权限 -->    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name="com.example.asyncread.MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>
4、最后,才是整个程序的关键,对MainActivity.java的编写。这里首先插入了两个工具类,一个在《【Java】读取其下所有文件夹与文件的路径》(点击打开链接)中讲过,用于遍历sdcard上面的文件的,当然,遍历的时候剔除sdcard上Android这个系统文件夹,不剔除的话会把系统的图标等遍历出来。之后是一个图片缩放类,不对读取到的图片进行缩放,会在app运行时,出现内存溢出的错误。

程序一开始,在onCreate方法,在app头部生成一个进度条,之后调用异步类AsyncTask对sdcard卡文件的读取,与《【Android】画廊式的图片浏览器,使用HorizontalScrollView取代Gallery,OnClickListener的参数传递》(点击打开链接)中的方法一样,把图片资源一张张加载出来。只是作用对象从app的图片资源,变成从sdcard读取出来的图片。

package com.example.asyncread;import java.io.File;import java.util.ArrayList;import android.os.AsyncTask;import android.os.Bundle;import android.os.Environment;import android.view.Gravity;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.view.Window;import android.widget.HorizontalScrollView;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.LinearLayout.LayoutParams;import android.widget.TextView;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;public class MainActivity extends Activity {	// 安卓组件	private HorizontalScrollView horizontalScrollView1;	private ImageView imageView1;	// 用于存放sdcard卡上的所有图片路径	public static ArrayList<String> dirAllStrArr = new ArrayList<String>();	// 用于遍历sdcard卡上所有文件的类	public static void DirAll(File dirFile) throws Exception {		if (dirFile.exists()) {			File files[] = dirFile.listFiles();			for (File file : files) {				if (file.isDirectory()) {					String fileName = file.getName();					// 除sdcard上Android这个文件夹以外。					if (!fileName.endsWith("Android")) {						// 如果遇到文件夹则递归调用。						DirAll(file);					}				} else {					// 如果是图片文件压入数组					String fileName = file.getName();					if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")							|| fileName.endsWith(".bmp")							|| fileName.endsWith(".gif")							|| fileName.endsWith(".png")) {						// 如果遇到文件则放入数组						if (dirFile.getPath().endsWith(File.separator)) {							dirAllStrArr									.add(dirFile.getPath() + file.getName());						} else {							dirAllStrArr.add(dirFile.getPath() + File.separator									+ file.getName());						}					}				}			}		}	}	// 图片加载的类	public static BitmapFactory.Options getHeapOpts(File file) {		BitmapFactory.Options opts = new BitmapFactory.Options();		// 数字越大读出的图片占用的heap必须越小,不然总是溢出		if (file.length() < 20480) { // 0-20k			opts.inSampleSize = 1;// 这里意为缩放的大小		} else if (file.length() < 51200) { // 20-50k			opts.inSampleSize = 2;		} else if (file.length() < 307200) { // 50-300k			opts.inSampleSize = 4;		} else if (file.length() < 819200) { // 300-800k			opts.inSampleSize = 6;		} else if (file.length() < 1048576) { // 800-1024k			opts.inSampleSize = 8;		} else {			opts.inSampleSize = 10;		}		return opts;	}	class MyTask extends AsyncTask<Void, Integer, LinearLayout> {		@Override		// 任务开始前做什么		protected void onPreExecute() {			setProgressBarVisibility(true);// 显示进度条			super.onPreExecute();		}		@Override		protected LinearLayout doInBackground(Void... arg0) {			// 生成一个水平线性布局			LinearLayout linearLayout1 = new LinearLayout(MainActivity.this);			LayoutParams layoutParams = new LayoutParams(					ViewGroup.LayoutParams.WRAP_CONTENT,					ViewGroup.LayoutParams.WRAP_CONTENT);			linearLayout1.setOrientation(LinearLayout.HORIZONTAL);			linearLayout1.setLayoutParams(layoutParams);// 应用到新生成的线性布局			/* 遍历sdcard旗下的所有文件夹开始 */			String sdpath = Environment.getExternalStorageDirectory()					.getAbsolutePath();// 获取sdcard的根路径			File dirFile = new File(sdpath);			try {				DirAll(dirFile);			} catch (Exception e) {				e.printStackTrace();			}			/* 遍历sdcard旗下的所有文件夹结束 */			// 得到sdcard旗下的所有图片路径之后,再对这个数组进行遍历			for (int i = 0; i < dirAllStrArr.size(); i++) {				String filePath = dirAllStrArr.get(i);				File file = new File(filePath);				Bitmap bm = BitmapFactory.decodeFile(filePath,						getHeapOpts(file));				LinearLayout linearLayout2 = new LinearLayout(MainActivity.this);				// 设置新生成线性布局的参数,宽度为100,高度为匹配父组件,也就是水平滚动视图的高度				LayoutParams layoutParams1 = new LayoutParams(100,						ViewGroup.LayoutParams.MATCH_PARENT);				layoutParams1.gravity = Gravity.CENTER_HORIZONTAL;// 设置线性布局内的组件水平居中				linearLayout2.setOrientation(LinearLayout.VERTICAL);// 设置新生成的线性布局android:orientation="vertical"				linearLayout2.setLayoutParams(layoutParams1);// 应用到新生成的线性布局				ImageView imageView2 = new ImageView(MainActivity.this);				imageView2.setId(i + 20000);// 这里由于id不能为字符的缘故,所有对图片的id分别设为20000,20001,20002,...便于下面的图片点击监听器所控制				imageView2.setImageBitmap(bm);// 将数组中的第i张图片放到图片视图				imageView2.setAdjustViewBounds(true);// 自动缩放为宽高比				imageView2.setMaxHeight(80);// 图片的高度为80dp				imageView2.setPadding(10, 10, 10, 10);				imageView2.setOnClickListener(new OnClickListener() {					@Override					public void onClick(View view) {						String filePath = dirAllStrArr.get(view.getId() - 20000);						File file = new File(filePath);						Bitmap bm = BitmapFactory.decodeFile(filePath,								getHeapOpts(file));						imageView1.setImageBitmap(bm);						// 把点击的图片id取出之后,减20000就是要显示的图片在图片数组的位置了。					}				});				// 将图片视图加载到新生成的线性布局之中				linearLayout2.addView(imageView2);				// 新生成一个标签文本				TextView textView = new TextView(MainActivity.this);				textView.setText(filePath);				textView.setTextSize(15);				// 标签文本在水平位置居中				textView.setGravity(Gravity.CENTER);				// 添加到新生成的线性布局之后				linearLayout2.addView(textView);				linearLayout1.addView(linearLayout2);				publishProgress(i);// 调用onProgressUpdate方法			}			return linearLayout1;		}		@Override		protected void onProgressUpdate(Integer... values) {			setProgress(values[0] * 2500);// 更新进度条			super.onProgressUpdate(values);		}		// 任务放完之后		@Override		protected void onPostExecute(LinearLayout result) {			setProgressBarVisibility(false);			horizontalScrollView1.addView(result);// 把doInBackground()最终搞出来的水平线性布局放到横向滚动布局中			super.onPostExecute(result);		}	}	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		requestWindowFeature(Window.FEATURE_PROGRESS);// 在头部生成一个进度条,必须在setContentView(R.layout.activity_main);这条语句之前		setContentView(R.layout.activity_main);		// 获取各种组件		horizontalScrollView1 = (HorizontalScrollView) findViewById(R.id.horizontalScrollView1);		imageView1 = (ImageView) findViewById(R.id.imageView1);		new MyTask().execute();// 开始MyTask任务	}}


版权声明:本文为博主原创文章,未经博主允许不得转载。

  相关解决方案