ListView应用--文件管理器

来源:互联网 发布:c语言最小公倍数怎么求 编辑:程序博客网 时间:2024/04/30 12:25
1、文件管理器应该由一个ListView和一个TextView组成。

  先完成布局设置

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TextView        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        android:text="当前位置: /mnt/sdcard" />    <ListView        android:id="@+id/list"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="8"        android:cacheColorHint="#00000000" >    </ListView></LinearLayout>

由于显示的ListView中有图标的存在,因此需要声明一个自定义的Adapter来处理,也就是需要建立一个行的布局文件。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="horizontal" >    <TextView        android:id="@+id/file_img"        android:layout_width="0dp"        android:layout_height="wrap_content"        android:layout_weight="1" />    <TextView        android:id="@+id/file_name"        android:layout_width="0dp"        android:layout_height="wrap_content"        android:layout_weight="5" >    </TextView></LinearLayout>

需要根据屏幕高度动态设置每一行的高度,因此需要计算高度,直接使用之前的Globals类即可。

编写自定义Adapter

public class FileAdapter extends BaseAdapter {private Context ctx;private List<Map<String, Object>> allValues;public FileAdapter(Context ctx, List<Map<String, Object>> allValues) {this.ctx = ctx;this.allValues = allValues;}@Overridepublic int getCount() {return allValues.size();}@Overridepublic Object getItem(int position) {return allValues.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = LayoutInflater.from(ctx).inflate(R.layout.file_line,null);// 需要动态设置高度convertView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, Globals.SCREEN_HEIGHT / 9));}// 处理内容的设置TextView fileImg = (TextView) convertView.findViewById(R.id.file_img);fileImg.getLayoutParams().height = Globals.SCREEN_HEIGHT / 9;TextView fileName = (TextView) convertView.findViewById(R.id.file_name);// 取得数据Map<String, Object> map = allValues.get(position);fileName.setText(map.get("fileName").toString());// 设置图片,根据传入的扩展名, 在Globals中的Map集合里查找该扩展名对应的文件图片id,并设置为这张图.fileImg.setBackgroundResource(Globals.allImgsMap.get(map.get("extName").toString()));return convertView;}}

下面需要编写程序来读取SD卡下的文件目录,并列表显示出来,这需要用到IO操作,以及Android读取SD卡的操作。

1.1、SD卡读取操作
可以通过Environment类来动态取得扩展设备的所在目录,再通过listFiles方法列出目录下的所有文件

public class MainActivity extends Activity {private TextView titleText;private ListView list;private List<Map<String, Object>> allValues = new ArrayList<Map<String, Object>>();private FileAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Globals.init(this);setContentView(R.layout.activity_main);// 取得组件titleText = (TextView) findViewById(R.id.title_text);list = (ListView) findViewById(R.id.list);// 读取SD卡,取得扩展设备的根目录File root = Environment.getExternalStorageDirectory();// 列出该目录下的所有文件File[] allFiles = root.listFiles();for (int i = 0; i < allFiles.length; i++) {File f = allFiles[i];Map<String, Object> map = new HashMap<String, Object>();// 保存文件或文件夹的名称map.put("fileName", f.getName());// 判断是文件还是文件夹if (f.isDirectory()) {// 文件夹String extName = "dir_close";map.put("extName", extName);} else {// 文件// 直接将文件的扩展名加入到map中即可.String extName = f.getName().substring(f.getName().lastIndexOf(".") + 1).toLowerCase();map.put("extName", extName);}// 将map集合加入到list中allValues.add(map);}// 建立Adapteradapter = new FileAdapter(this, allValues);list.setAdapter(adapter);}}

下面实现点击查看功能,当点某一个文件夹时,可以展开这个文件夹,来查看该文件夹里面的数据。

也就是要将List集合中的数据重新加载。

最好将读取文件夹中文件的功能封装成一个方法。

为了更方数据的调用,需要将操作方法封装,方便从目录下读取所有文件列表

private void loadFileData(File parentDir) {// 列出该目录下的所有文件File[] allFiles = parentDir.listFiles();for (int i = 0; i < allFiles.length; i++) {File f = allFiles[i];Map<String, Object> map = new HashMap<String, Object>();// 保存文件或文件夹的名称map.put("fileName", f.getName());// 保存文件的整体路径map.put("fullPath", f.getAbsolutePath());// 判断是文件还是文件夹if (f.isDirectory()) {// 文件夹String extName = "dir_close";map.put("extName", extName);map.put("dirFlag", true);} else {// 文件// 直接将文件的扩展名加入到map中即可.String extName = f.getName().substring(f.getName().lastIndexOf(".") + 1).toLowerCase();map.put("extName", extName);map.put("dirFlag", false);}// 将map集合加入到list中allValues.add(map);}}

加入事件监听,完成读取某一个目录下所有文件的功能

// 加入监听list.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {// 取得当前点击的项目对应的数据Map<String, Object> map = allValues.get(arg2);// 判断点的是否是文件夹boolean dirFlag = (Boolean) map.get("dirFlag");if (dirFlag) {// 是文件夹// 读取绝对路径String fullPath = (String) map.get("fullPath");// 建立该文件对象File dir = new File(fullPath);// 将 该文件夹 下的所有文件读取到List集合中,先将原有数据清空allValues.clear();// 添加数据loadFileData(dir);// 如果只修改数据,界面不会得到改变的通知,当用户再进行操作时,会出现错误.// 这里就需要通知界面进行修改.adapter.notifyDataSetChanged();}}});

还需要补充一个返回上一级目录的功能。

// 加入监听list.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {// 取得当前点击的项目对应的数据Map<String, Object> map = allValues.get(arg2);// 判断点的是否是文件夹boolean dirFlag = (Boolean) map.get("dirFlag");if (dirFlag) {// 是文件夹// 读取绝对路径String fullPath = (String) map.get("fullPath");// 建立该文件对象File dir = new File(fullPath);// 将 该文件夹 下的所有文件读取到List集合中,先将原有数据清空allValues.clear();// 判断当前是哪个目录,如果已经是SD卡的跟目录,就不应该再加入返回上一级的操作if (!Environment.getExternalStorageDirectory().getAbsolutePath().equals(fullPath)) {// 加入一个返回上一级的数据Map<String, Object> parentData = new HashMap<String, Object>();parentData.put("fileName", "返回上一级");parentData.put("extName", "dir_open");parentData.put("dirFlag", true);parentData.put("fullPath", dir.getParent());allValues.add(parentData);}// 添加数据loadFileData(dir);// 如果只修改数据,界面不会得到改变的通知,当用户再进行操作时,会出现错误.// 这里就需要通知界面进行修改.adapter.notifyDataSetChanged();}}});
1.2、加入普通对话框

在进行文件操作时,如果点击的不是文件夹,而是文件,想实现查看当前点击文件的详情的功能,这就要通过对话框来弹出提示了。

需要使用AlertDialog类来完成对话框。

但建立对话框需要使用Builder类来完成。

// 点的是文件, 想弹出一个对话框Builder builder = new Builder(MainActivity.this);// 对话框标题builder.setTitle("文件详情");// 内容builder.setMessage("文件大小: " + file.length() + "\r\n"+ "文件名: " + file.getName());// 按钮builder.setNegativeButton("关闭", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// 该事件自带一个功能, 可以自动关闭对话框 }});// 显示这个对话框builder.create().show();

按钮如果有多个,使用Builder可以最多加入三个按钮,其中中间的按钮位置固定的,但确定和取消的位置不确定。

加入长按删除功能,当要删除文件时,先弹出提示,确定还是取消,然后再删除。

list.setOnItemLongClickListener(new OnItemLongClickListener() {@Overridepublic boolean onItemLongClick(AdapterView<?> arg0, View arg1,final int arg2, long arg3) {// 取得要删除的数据Map<String, Object> map = allValues.get(arg2);// 取得文件路径final String path = (String) map.get("fullPath");boolean dirFlag = (Boolean) map.get("dirFlag");if (!dirFlag) {// 文件时可以提示删除Builder builder = new Builder(MainActivity.this);builder.setTitle("提示");builder.setMessage("确定要删除该文件(" + map.get("fileName")+ ")吗?");builder.setPositiveButton("确定", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// 将文件夹中的文件真正删除File f = new File(path);if (f.exists()) {f.delete();}// 将列表中的这条数据也删除allValues.remove(arg2);// 通知界面进行改变adapter.notifyDataSetChanged();}});builder.setNegativeButton("取消", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {}});builder.create().show();}return false;}});
注:

测试时发现无法真正的删除文件,因为该应用没有声明操作SD卡写出的权限。

因此需要在AndroidManifest.xml中进行声明。

1.3、返回键监听

在编写应用程序时,一般点“返回”键并不会直接退出系统,而是根据用户当前的状态提示信息,来决定是否退出,为了让用户长时间留在应用程序中。

通过在Activity中覆写OnKeyDown的方法来监听用户按键的情况。

@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {// 根据keyCode判断用户按的是哪个键.if (keyCode == KeyEvent.KEYCODE_BACK) {// 判断当前List集合中的第一条数据是否是"返回上一级"if ("TRUE".equals(allValues.get(0).get("real"))) {// 直接返回上一级list.performItemClick(list.getChildAt(0), 0, list.getChildAt(0).getId());} else {// 要真的退出// 弹出对话框Builder builder = new Builder(this);builder.setTitle("提示");builder.setMessage("亲,真的要退出吗?");builder.setPositiveButton("真的", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// 结束当前Activity程序finish();}});builder.setNegativeButton("暂不", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {}});builder.create().show();}// 取消返回键原有的作用return false;}return super.onKeyDown(keyCode, event);}

































1 0
原创粉丝点击