zoukankan      html  css  js  c++  java
  • 【Android】读取sdcard卡上的全部图片而且显示,读取的过程有进度条显示

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

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


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


    制作步骤例如以下:

    1、首先,resvaluesstrings.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、之后,改动reslayoutactivity_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任务 } }



  • 相关阅读:
    Mybatis中#{}和${}传参的区别
    笔记摘抄 —— shiro学习篇
    使用Spring的Testcase的单元测试的写法
    【转】FreeMarker学习笔记
    破解Pycharm,IDEA,PhpStrom等系列产品的,有关JetbrainsCrack的使用方法
    Python的字符串
    python的变量
    python开头注释
    h5-动画小案例-滚动展示
    h5-钟表动画案例
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5161103.html
Copyright © 2011-2022 走看看