使用ListView显示Android SD卡中的文件列表
父类布局activity_main.xml,子类布局item_filelayout(一个文件的单独存放)
运行截图:
程序结构
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.asus.gary_034"> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>
AndroidMainfest.xml
package com.example.asus.gary_034; import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast; import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; public class MainActivity extends AppCompatActivity implements OnItemClickListener, View.OnClickListener { LinearLayout ll_root;
TextView root;
ListView lv;
List<File> list = new ArrayList<File>(); //获取SD卡根目录,必须获取权限,权限在AndroidManifest.xml/Permissions中添加
public static final String SDCard = Environment
.getExternalStorageDirectory().getAbsolutePath(); // 当前文件目录
public static String currDir = SDCard;
MyAdapter adapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
adapter = new MyAdapter(MainActivity.this, list);
lv.setAdapter(adapter);
getAllFiles(); } private void initData() {
ll_root = (LinearLayout) findViewById(R.id.ll_root);
root = (TextView) findViewById(R.id.root);
lv = (ListView) findViewById(R.id.lv);
lv.setOnItemClickListener(this);
root.setOnClickListener(this);
} public void getAllFiles() {
list.clear();
File file = new File(currDir);
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
for (File file2 : files) {
list.add(file2);
}
}
}
// 文件排序
sort(); // 数据改变之后刷新
// notifyDataSetChanged方法通过一个外部的方法控制如果适配器的内容改变时需要强制调用getView来刷新每个Item的内容,
// 可以实现动态的刷新列表的功能
adapter.notifyDataSetChanged();
} private void sort() {
//使用Collection.sort排序,给定一个比较器,使用匿名内部类实现比较器接口
Collections.sort(list, new Comparator<File>() { @Override
public int compare(File o1, File o2) {
if (o1.isDirectory() && o2.isDirectory() || o1.isFile()
&& o2.isFile()) {
return o1.compareTo(o2);
}
//文件夹在前
return o1.isDirectory() ? -1 : 1;
}
});
} //ListView 监听
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
File file = list.get(position);
if (file.isDirectory()) {
// 下一层目录
currDir = file.getAbsolutePath();
//根目录名加上当前文件夹名
addDirText(file);
getAllFiles();
} else {
Toast.makeText(MainActivity.this, "打开" + file.getName(),
Toast.LENGTH_SHORT).show();
}
} private void addDirText(File file) {
String name = file.getName();
TextView tv = new TextView(this);
tv.setText(name+">");
ll_root.addView(tv);
//将当前的路径保存
tv.setTag(file.getAbsolutePath()); tv.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) {
String tag = v.getTag().toString();
currDir = tag;
getAllFiles(); //将后面的所有TextView的tag移除
//从后往前删,一个一个删
for (int i = ll_root.getChildCount(); i >1; i--) {
View view = ll_root.getChildAt(i-1);
String currTag = view.getTag().toString();
if(!currTag.equals(currDir)){
ll_root.removeViewAt(i-1);
}else{
return;
}
}
}
});
} // Back键返回上一级
@Override
public void onBackPressed() {
// 如果当前目录就是系统根目录,直接调用父类
if (currDir.equals(SDCard)) {
super.onBackPressed();
} else {
// 返回上一层,显示上一层所有文件
currDir = new File(currDir).getParent();
getAllFiles(); //将当前TextView的tag移除
//总是将最后一个TextView移除
View view = ll_root.getChildAt(ll_root.getChildCount()-1);
ll_root.removeView(view); }
} //SD卡根目录TextView监听
@Override
public void onClick(View v) {
currDir = SDCard;
getAllFiles(); //移除ll_root布局中的其他所有组件
for (int i = ll_root.getChildCount(); i >1; i--) {
ll_root.removeViewAt(i-1);
} } }
MainActivity
package com.example.asus.gary_034; import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView; import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List; /**
* Created by ASUS on 2018/5/18.
*/ public class MyAdapter extends BaseAdapter {
Context context;
List<File> list; public MyAdapter(Context context, List<File> list) {
this.context = context;
this.list = list;
} @Override
public int getCount() {
return list.size();
} @Override
public Object getItem(int position) {
return list.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
//布局实例化
convertView = View.inflate(context, R.layout.item_filelayout, null);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// 设置数据
File file = (File) getItem(position);
if (file.isDirectory()) {
viewHolder.img.setImageResource(R.drawable.folder);
} else {
if (file.getName().endsWith(".jpg")
|| file.getName().endsWith(".png")
|| file.getName().endsWith(".gif")) {
viewHolder.img.setImageResource(R.drawable.pic);
} else if (file.getName().endsWith(".txt") || file.getName().endsWith(".log")) {
viewHolder.img.setImageResource(R.drawable.text);
} else {
viewHolder.img.setImageResource(R.drawable.unknown);
}
}
viewHolder.name.setText(file.getName());
viewHolder.time.setText(new SimpleDateFormat("yy-M-d HH:mm:ss")
.format(new Date(file.lastModified()))); return convertView;
} class ViewHolder {
ImageView img;
TextView name;
TextView time; public ViewHolder(View convertView) {
img = (ImageView) convertView.findViewById(R.id.img);
name = (TextView) convertView.findViewById(R.id.name);
time = (TextView) convertView.findViewById(R.id.time);
} } }
MyAdapter
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <LinearLayout
android:id="@+id/ll_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" > <TextView
android:id="@+id/root"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/holo_green_light"
android:text="SD卡目录>" />
</LinearLayout> <ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent" /> </LinearLayout>
activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="horizontal" > <ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical" > <TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="文件名" /> <TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="时间" />
</LinearLayout> </LinearLayout>
item_filelayout
一、获取手机存储卡权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
二、界面布局
activity_main.xml布局中
TextView中显示当前路径的的文本框(SD卡目录),ListView列出当前路径下所有文件的ListView
item_filelayout布局中
ImageView和两个TextView,用于作为列表项的一部分,一个TextView显示文件名,一个TextView显示时间
三、实现程序功能
//获取SD卡根目录,必须获取权限,权限在AndroidManifest.xml/Permissions中添加
public static final String SDCard = Environment
.getExternalStorageDirectory().getAbsolutePath(); // 当前文件目录
public static String currDir = SDCard;
MyAdapter adapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
adapter = new MyAdapter(MainActivity.this, list);
lv.setAdapter(adapter);
getAllFiles(); } private void initData() {
ll_root = (LinearLayout) findViewById(R.id.ll_root);
root = (TextView) findViewById(R.id.root);
lv = (ListView) findViewById(R.id.lv);
lv.setOnItemClickListener(this);
root.setOnClickListener(this);
} public void getAllFiles() {
list.clear();
File file = new File(currDir);
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
for (File file2 : files) {
list.add(file2);
}
}
}
// 文件排序
sort(); // 数据改变之后刷新
// notifyDataSetChanged方法通过一个外部的方法控制如果适配器的内容改变时需要强制调用getView来刷新每个Item的内容,
// 可以实现动态的刷新列表的功能
adapter.notifyDataSetChanged();
} private void sort() {
//使用Collection.sort排序,给定一个比较器,使用匿名内部类实现比较器接口
Collections.sort(list, new Comparator<File>() { @Override
public int compare(File o1, File o2) {
if (o1.isDirectory() && o2.isDirectory() || o1.isFile()
&& o2.isFile()) {
return o1.compareTo(o2);
}
//文件夹在前
return o1.isDirectory() ? -1 : 1;
}
});
} //ListView 监听
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
File file = list.get(position);
if (file.isDirectory()) {
// 下一层目录
currDir = file.getAbsolutePath();
//根目录名加上当前文件夹名
addDirText(file);
getAllFiles();
} else {
Toast.makeText(MainActivity.this, "打开" + file.getName(),
Toast.LENGTH_SHORT).show();
}
} private void addDirText(File file) {
String name = file.getName();
TextView tv = new TextView(this);
tv.setText(name+">");
ll_root.addView(tv);
//将当前的路径保存
tv.setTag(file.getAbsolutePath()); tv.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) {
String tag = v.getTag().toString();
currDir = tag;
getAllFiles(); //将后面的所有TextView的tag移除
//从后往前删,一个一个删
for (int i = ll_root.getChildCount(); i >1; i--) {
View view = ll_root.getChildAt(i-1);
String currTag = view.getTag().toString();
if(!currTag.equals(currDir)){
ll_root.removeViewAt(i-1);
}else{
return;
}
}
}
});
} // Back键返回上一级
@Override
public void onBackPressed() {
// 如果当前目录就是系统根目录,直接调用父类
if (currDir.equals(SDCard)) {
super.onBackPressed();
} else {
// 返回上一层,显示上一层所有文件
currDir = new File(currDir).getParent();
getAllFiles(); //将当前TextView的tag移除
//总是将最后一个TextView移除
View view = ll_root.getChildAt(ll_root.getChildCount()-1);
ll_root.removeView(view); }
} //SD卡根目录TextView监听
@Override
public void onClick(View v) {
currDir = SDCard;
getAllFiles(); //移除ll_root布局中的其他所有组件
for (int i = ll_root.getChildCount(); i >1; i--) {
ll_root.removeViewAt(i-1);
} }
3、在MyAdapter中用List集合存放文件,并且创建一个适配器SimpleAdapter
构造方法:SimpleAdapter(Contextcontext,List>data,intresource,String[]from,int[]to)
context:要使用的上下文环境。
data:是一个List>类型的集合对象,该集合中每个Map对象生成一个列表项。
resource:界面布局文件的ID,对应的布局文件作为列表项的组件。
from:是一个String[]类型的参数,该参数决定提取Map对象中哪些key对应的value来生成列表项。
to:该参数是一个int[]类型的参数,该参数决定填充哪些组件。
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
//布局实例化
convertView = View.inflate(context, R.layout.item_filelayout, null);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// 设置数据
File file = (File) getItem(position);
if (file.isDirectory()) {
viewHolder.img.setImageResource(R.drawable.folder);
} else {
if (file.getName().endsWith(".jpg")
|| file.getName().endsWith(".png")
|| file.getName().endsWith(".gif")) {
viewHolder.img.setImageResource(R.drawable.pic);
} else if (file.getName().endsWith(".txt") || file.getName().endsWith(".log")) {
viewHolder.img.setImageResource(R.drawable.text);
} else {
viewHolder.img.setImageResource(R.drawable.unknown);
}
}
viewHolder.name.setText(file.getName());
viewHolder.time.setText(new SimpleDateFormat("yy-M-d HH:mm:ss")
.format(new Date(file.lastModified()))); return convertView;
}