这个项目以及代码中使用的未在下面代码给出源码的方法都在这里:https://github.com/NashLegend/LegendUtils


第二种对话框的源码在这里:https://github.com/NashLegend/LegendExplorer/,这是一个文件浏览器源码。




Android文件对话框,一般用的分两种。

一是我们自己程序内使用的,当我们需要让用户选择一个文件或文件夹进行上传、下载或者其他操作时有时会用到。

二是系统的全局文件对话框,当一个程序发起一个要选择的Intent,那么这个对话框就会弹出,用户进行操作后返回行距的文件或者文件夹,比如写一封邮件如果想同时发送一个附件的时候,就会发起一个Intent,然后我们的选择文件对话框会弹出,让用户来选择文件。


这个文件对话框大约长下面这个样子(图标是不是很熟悉,这是直接取的ES文件浏览器的图标),它可以实现文件、文件夹的单选、多选、混选,当用户点击确定时,返回一个ArrayList<File>:

wKioL1RQ5zrQlMBgAAHbXXa1Iqc992.jpg


下面是如何写这个文件对话框。


首先我们需要一个,一个Dialog需要一个view来显示,也就是我们看到的。我们给它起名FileDialogView。很显然它需要两个Button用于确定取消,一个ImageButton用于返回上级,多选的话还要再加一个【全部选择、全部取消】的CheckBox(上图为单选文件夹的示例,所以没有出现).一个EditText用于显示当前路径、以及最重要的——ListView以及它的adapter,我们叫这个adapter为FileListAdapter。

下面是这个FileDialogView的代码(这个项目不难,代码里面的注释应该足够清楚了……)。

/**
 * FileDialog的view
 * 
 * @author NashLegend
 */
public class FileDialogView extends FrameLayout implements OnClickListener,
		OnCheckedChangeListener {

	private FileListAdapter adapter;
	private ListView listView;//文件列表
	private EditText pathText;//当前路径
	private ImageButton backButton;//返回上级按钮
	private CheckBox selectAllButton;//全选按钮

	private int fileMode = FileDialog.FILE_MODE_OPEN_MULTI;//选择文件方式,默认为文件、文件夹混选
	private String initialPath = "/";//用来指定刚打开时的目录,默认为根目录

	private Button cancelButton;
	private Button okButton;

	public FileDialogView(Context context) {
		super(context);
		initView(context);
	}

	public FileDialogView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView(context);
	}

	public FileDialogView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView(context);
	}

	/**
         * 初始化view
         */
	private void initView(Context context) {
		LayoutInflater inflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		inflater.inflate(R.layout.dialog_file, this);

		listView = (ListView) findViewById(R.id.listview_dialog_file);
		pathText = (EditText) findViewById(R.id.edittext_dialog_file_path);
		backButton = (ImageButton) findViewById(R.id.imagebutton_dialog_file_back);
		selectAllButton = (CheckBox) findViewById(R.id.checkbox_dialog_file_all);
		cancelButton = (Button) findViewById(R.id.button_dialog_file_cancel);
		okButton = (Button) findViewById(R.id.button_dialog_file_ok);

		backButton.setOnClickListener(this);
		cancelButton.setOnClickListener(this);
		okButton.setOnClickListener(this);
		selectAllButton.setOnCheckedChangeListener(this);
		pathText.setKeyListener(null);//不需要弹起键盘

		adapter = new FileListAdapter(context);
		adapter.setDialogView(this);
		listView.setAdapter(adapter);
	}

	/**
	 * 打开目录
	 * 
	 * @param file 要打开的文件夹
	 *            
	 */
	public void openFolder(File file) {
		if (!file.exists() || !file.isDirectory()) {
			// 若不存在此目录,则打开SD卡根目录
			file = Environment.getExternalStorageDirectory();
		}
		//openFolder用来读取文件列表详见FileListAdapter的代码
		adapter.openFolder(file);
	}

	/**
	 * 打开目录
	 * 
	 * @param path
	 *            要打开的文件夹路径
	 */
	public void openFolder(String path) {
		openFolder(new File(path));
	}

	/**
	 * 打开初始目录
	 */
	public void openFolder() {
		openFolder(initialPath);
	}

	/**
	 * 返回上级目录
	 */
	private void back2ParentLevel() {
		File file = adapter.getCurrentDirectory();
		// 如果当前目录不为空且父目录不为空,则打开父目录
		if (file != null && file.getParentFile() != null) {
			openFolder(file.getParentFile());
		}
	}

	/**
	 * 选中当前目录所有文件
	 */
	private void selectAll() {
		adapter.selectAll();
	}

	/**
	 * 取消选中当前目录所有文件
	 */
	private void unselectAll() {
		adapter.unselectAll();
	}

	public void unselectCheckBox() {
		selectAllButton.setOnCheckedChangeListener(null);
		selectAllButton.setChecked(false);
		selectAllButton.setOnCheckedChangeListener(this);
	}

	/**
	 * @return 返回选中的文件列表
	 */
	public ArrayList<File> getSelectedFiles() {
		ArrayList<File> list = new ArrayList<File>();
		if (adapter.getSelectedFiles().size() > 0) {
			list = adapter.getSelectedFiles();
		} else {
		        //如果点击确定的时候没有选择文件并且模式是选择单个文件夹,那么就返回当前目录
			if (fileMode == FileDialog.FILE_MODE_OPEN_FOLDER_SINGLE) {
				list.add(adapter.getCurrentDirectory());
			}
		}
		return list;
	}

	@Override
	public void onClick(View v) {
		int id = v.getId();
		if (id == R.id.imagebutton_dialog_file_back) {
			back2ParentLevel();
		}
	}

	public EditText getPathText() {
		return pathText;
	}

	public int getFileMode() {
		return fileMode;
	}

	public void setFileMode(int fileMode) {
		this.fileMode = fileMode;
		if (fileMode > FileDialog.FILE_MODE_OPEN_FILE_MULTI) {
			// 单选模式应该看不到全选按钮才对
			selectAllButton.setVisibility(View.GONE);
		} else {
			selectAllButton.setVisibility(View.VISIBLE);
		}
	}

	public String getInitialPath() {
		return initialPath;
	}

	public void setInitialPath(String initialPath) {
		this.initialPath = initialPath;
	}

	@Override
	public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
		if (selectAllButton.isChecked()) {
			selectAll();
		} else {
			unselectAll();
		}
	}

	public CheckBox getSelectAllButton() {
		return selectAllButton;
	}
}

FileDialogView代码并不多,只负责了构建界面的任务。


下面是FileListAdapter的代码,FileListAdapter负责读取文件夹、全选、反选、排序、返回选中文件,数据对象为FileItem:

package com.example.legendutils.BuildIn;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import com.example.legendutils.Dialogs.FileDialog;
import android.annotation.SuppressLint;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

public class FileListAdapter extends BaseAdapter {
    private ArrayList<FileItem> list = new ArrayList<FileItem>();
    private Context mContext;
    private File currentDirectory;
    private FileDialogView dialogView;

    public FileListAdapter(Context Context) {
        mContext = Context;
    }

    @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 holder = null;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = new FileItemView(mContext);
            holder.fileItemView = (FileItemView) convertView;
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.fileItemView.setFileItem(list.get(position), this,
                dialogView.getFileMode());
        return holder.fileItemView;
    }

    class ViewHolder {
        FileItemView fileItemView;
    }

    public ArrayList<FileItem> getList() {
        return list;
    }

    public void setList(ArrayList<FileItem> list) {
        this.list = list;
    }

    /**
     * 打开文件夹,更新文件列表
     * 
     * @param file
     */
    public void openFolder(File file) {
        if (file != null && file.exists() && file.isDirectory()) {
            if (!file.equals(currentDirectory)) {
                // 与当前目录不同
                currentDirectory = file;
                list.clear();
                File[] files = file.listFiles();
                if (files != null) {
                    for (int i = 0; i < files.length; i++) {
                        File tmpFile = files[i];
			if (tmpFile.isFile()
				&& (dialogView.getFileMode() == FileDialog.FILE_MODE_OPEN_FOLDER_MULTI || dialogView
				    .getFileMode() == FileDialog.FILE_MODE_OPEN_FOLDER_SINGLE)) {
				    //如果只能选择文件夹并且当前文件不是文件夹,那则跳过
				continue;
			}                   
                        list.add(new FileItem(files[i]));
                    }
                }
                files = null;
                sortList();
                notifyDataSetChanged();
            }
        }
        //改变FileDialogView的当前路径显示
        dialogView.getPathText().setText(file.getAbsolutePath());
    }

    /**
     * 选择当前目录下所有文件
     */
    public void selectAll() {
        int mode = dialogView.getFileMode();
        if (mode > FileDialog.FILE_MODE_OPEN_FILE_MULTI) {
            // 这个if不会发生,我为啥要写……
            return;
        }
        for (Iterator<FileItem> iterator = list.iterator(); iterator.hasNext();) {
            FileItem fileItem = (FileItem) iterator.next();

            if (mode == FileDialog.FILE_MODE_OPEN_FILE_MULTI
                    && fileItem.isDirectory()) {
                // fileItem是目录,但是只能选择文件,则跳过
                continue;
            }
            if (mode == FileDialog.FILE_MODE_OPEN_FOLDER_MULTI
                    && !fileItem.isDirectory()) {
                // fileItem是文件,但是只能选择目录,则跳过
                continue;
            }

            fileItem.setSelected(true);
        }
        notifyDataSetChanged();
    }

    /**
     * 取消所有文件的选中状态
     */
    public void unselectAll() {
        for (Iterator<FileItem> iterator = list.iterator(); iterator.hasNext();) {
            FileItem fileItem = (FileItem) iterator.next();
            fileItem.setSelected(false);
        }
        notifyDataSetChanged();
    }

    /**
     * 选中一个文件,只在选中时调用,取消选中不调用,且只由FileItemView调用
     * 
     * @param fileItem
     */
    public void selectOne(FileItem fileItem) {
        int mode = dialogView.getFileMode();
        if (mode > FileDialog.FILE_MODE_OPEN_FILE_MULTI) {
            // 如果是单选
            if (mode == FileDialog.FILE_MODE_OPEN_FILE_SINGLE
                    && fileItem.isDirectory()) {
                // fileItem是目录,但是只能选择文件,则返回
                return;
            }
            if (mode == FileDialog.FILE_MODE_OPEN_FOLDER_SINGLE
                    && !fileItem.isDirectory()) {
                // fileItem是文件,但是只能选择目录,则返回
                return;
            }
            for (Iterator<FileItem> iterator = list.iterator(); iterator
                    .hasNext();) {
                FileItem tmpItem = (FileItem) iterator.next();
                if (tmpItem.equals(fileItem)) {
                    tmpItem.setSelected(true);
                } else {
                    tmpItem.setSelected(false);
                }
            }
        } else {
            // 如果是多选
            if (mode == FileDialog.FILE_MODE_OPEN_FILE_MULTI
                    && fileItem.isDirectory()) {
                // fileItem是目录,但是只能选择文件,则返回
                return;
            }
            if (mode == FileDialog.FILE_MODE_OPEN_FOLDER_MULTI
                    && !fileItem.isDirectory()) {
                // fileItem是文件,但是只能选择目录,则返回
                return;
            }
            fileItem.setSelected(true);
        }

        notifyDataSetChanged();
    }

    public void sortList() {
        FileItemComparator comparator = new FileItemComparator();
        Collections.sort(list, comparator);
    }

    /**
     * 取消一个的选择,其他逻辑都在FileItemView里面
     */
    public void unselectOne() {
        dialogView.unselectCheckBox();
    }

    /**
     * @return 选中的文件列表
     */
    public ArrayList<File> getSelectedFiles() {
        ArrayList<File> selectedFiles = new ArrayList<File>();
        for (Iterator<FileItem> iterator = list.iterator(); iterator.hasNext();) {
            FileItem file = iterator.next();// 强制转换为File
            if (file.isSelected()) {
                selectedFiles.add(file);
            }
        }
        return selectedFiles;
    }

    public class FileItemComparator implements Comparator<FileItem> {

        @Override
        public int compare(FileItem lhs, FileItem rhs) {
            if (lhs.isDirectory() != rhs.isDirectory()) {
                // 如果一个是文件,一个是文件夹,优先按照类型排序
                if (lhs.isDirectory()) {
                    return -1;
                } else {
                    return 1;
                }
            } else {
                // 如果同是文件夹或者文件,则按名称排序
                return lhs.getName().toLowerCase().compareTo(rhs.getName().toLowerCase());
            }
        }
    }

    public File getCurrentDirectory() {
        return currentDirectory;
    }

    public FileDialogView getDialogView() {
        return dialogView;
    }

    public void setDialogView(FileDialogView dialogView) {
        this.dialogView = dialogView;
    }

}

下面是FileItemView,它是ListView的元素,用来显示每一个文件。数据对象为FileItem

/**
 * 文件列表单个item的view
 * 
 * @author NashLegend
 */
public class FileItemView extends FrameLayout implements OnClickListener,
		OnCheckedChangeListener {

	private ImageView icon;//文件图标
	private TextView title;//文件名
	private CheckBox checkBox;//选择按钮
	private ViewGroup rootFileItemView;//FileItemView的xml文件的根view
	private FileListAdapter adapter;
	private int fileMode = FileDialog.FILE_MODE_OPEN_MULTI;
	private boolean selectable = true;

	private FileItem fileItem;

	public FileItemView(Context context) {
		super(context);
		LayoutInflater inflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		inflater.inflate(R.layout.view_file_item, this);
		icon = (ImageView) findViewById(R.id.image_file_icon);
		title = (TextView) findViewById(R.id.text_file_title);
		rootFileItemView = (ViewGroup) findViewById(R.id.rootFileItemView);
		checkBox = (CheckBox) findViewById(R.id.checkbox_file_item_select);
		setOnClickListener(this);
	}

	public FileItem getFileItem() {
		return fileItem;
	}

	public void setFileItem(FileItem fileItem, FileListAdapter adapter,
			int fileMode) {
		this.fileItem = fileItem;
		this.adapter = adapter;
		this.fileMode = fileMode;
		icon.setImageResource(fileItem.getIcon());
		title.setText(fileItem.getName());
		toggleSelectState();

		if (!fileItem.isDirectory()
				&& (fileMode == FileDialog.FILE_MODE_OPEN_FOLDER_MULTI || fileMode == FileDialog.FILE_MODE_OPEN_FOLDER_SINGLE)) {
			//如果选择模式与当前文件类型不符,则设计为不可选择,比如在只可选择文件平时,文件不可选
			checkBox.setEnabled(false);
			selectable = false;
			checkBox.setOnCheckedChangeListener(null);
			return;
		}

		if (fileItem.isDirectory()
				&& (fileMode == FileDialog.FILE_MODE_OPEN_FILE_MULTI || fileMode == FileDialog.FILE_MODE_OPEN_FILE_SINGLE)) {
			//如果选择模式与当前文件类型不符,则设计为不可选择,比如在只可选择文件时,文件夹不可选
			checkBox.setEnabled(false);
			selectable = false;
			checkBox.setOnCheckedChangeListener(null);
			return;
		}
		selectable = true;
		checkBox.setEnabled(true);
		checkBox.setOnCheckedChangeListener(this);
	}

	/**
	 * 切换选中、未选中状态,fileItem.setSelected(boolean)先发生;
	 */
	public void toggleSelectState() {
		if (fileItem.isSelected()) {
			rootFileItemView
					.setBackgroundResource(R.drawable.bg_file_item_select);
		} else {
			rootFileItemView
					.setBackgroundResource(R.drawable.bg_file_item_normal);
		}
		checkBox.setOnCheckedChangeListener(null);
		checkBox.setChecked(fileItem.isSelected());
		checkBox.setOnCheckedChangeListener(this);
	}

	@Override
	public void onClick(View v) {
		if (v.getId() != R.id.checkbox_file_item_select) {
		        //被点击时,如果是文件夹则打开文件夹,如果是文件则选中文件
			if (fileItem.isDirectory()) {
				openFolder();
			} else {
				// 选中一个
				selectOne();
			}
		}
	}

	public void selectOne() {//选中一个文件(夹)
		if (selectable) {
			if (fileItem.isSelected()) {
				// 取消选中状态,只在FileItemView就可以
				fileItem.setSelected(!fileItem.isSelected());
				toggleSelectState();
				adapter.unselectOne();
			} else {
				// 如果要选中某个FileItem,则必须要在adapter里面进行,因为如果是单选的话,还要取消其他的选中状态
				adapter.selectOne(fileItem);
			}
		}
	}

	/**
	 * 打开文件夹
	 */
	public void openFolder() {
		adapter.openFolder(fileItem);
	}

	public FileListAdapter getAdapter() {
		return adapter;
	}

	@Override
	public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
		if (isChecked) {
			adapter.selectOne(fileItem);
		} else {
			fileItem.setSelected(false);
			rootFileItemView
					.setBackgroundResource(R.drawable.bg_file_item_normal);
			adapter.unselectOne();
		}
	}

	public int getFileMode() {
		return fileMode;
	}
}

上面所使用的数据对象FileItem其实很简单,只是一个继承了File,并仅仅多了icon字段和selected字段的类。这里不写出来了,详见上面的地址。


现在有了View,只要把它放到Dialog里就可以了,Dialog很简单了,我们仍然依照系统的Dialog写一个Builder以方便使用。代码如下:

public class FileDialog extends Dialog {

	/**
	 * 以打开文件模式打开文件对话框,有可能是文件夹也有可能是文件,可多选,最终返回值为一个File对象列表。
	 */
	public static final int FILE_MODE_OPEN_MULTI = 0;

	/**
	 * 以打开文件模式打开文件对话框,只能选择文件夹而不是文件,可多选,最终返回值为一个File对象列表。
	 */
	public static final int FILE_MODE_OPEN_FOLDER_MULTI = 1;

	/**
	 * 以打开文件模式打开文件对话框,只能选择文件而不是文件夹,可多选,最终返回值为一个File对象列表。
	 */
	public static final int FILE_MODE_OPEN_FILE_MULTI = 2;

	/**
	 * 以打开文件模式打开文件对话框,有可能是文件夹也有可能是文件,最终返回值为一个长度为1的File对象列表。
	 */
	public static final int FILE_MODE_OPEN_SINGLE = 3;

	/**
	 * 以打开文件模式打开文件对话框,只能选择文件夹而不是文件,最终返回值为一个长度为1的File对象列表。
	 */
	public static final int FILE_MODE_OPEN_FOLDER_SINGLE = 4;

	/**
	 * 以打开文件模式打开文件对话框,只能选择文件而不是文件夹,最终返回值为一个长度为1的File对象列表。
	 */
	public static final int FILE_MODE_OPEN_FILE_SINGLE = 5;

	public FileDialog(Context context) {
		super(context);
	}

	public FileDialog(Context context, int theme) {
		super(context, theme);
	}

	public FileDialog(Context context, boolean cancelable,
			OnCancelListener cancelListener) {
		super(context, cancelable, cancelListener);
	}

	public interface FileDialogListener {
		public void onFileSelected(ArrayList<File> files);

		public void onFileCanceled();
	}

	public static class Builder {
		private int fileMode = FileDialog.FILE_MODE_OPEN_MULTI;
		private String initialPath = Environment.getExternalStorageDirectory()
				.getAbsolutePath();
		private FileDialogListener fileSelectListener;
		private FileDialogView dialogView;
		private Context context;
		private boolean canceledOnTouchOutside = true;
		private boolean cancelable = true;
		private String title = "选择文件";

		public Builder(Context context) {
			this.context = context;
		}

		public Builder setCanceledOnTouchOutside(boolean flag) {
			canceledOnTouchOutside = flag;
			return this;
		}

		public Builder setCancelable(boolean flag) {
			cancelable = flag;
			return this;
		}

		public Builder setFileMode(int fileMode) {
			this.fileMode = fileMode;
			return this;
		}

		public Builder setInitialPath(String initialPath) {
			this.initialPath = initialPath;
			return this;
		}

		public Builder setTitle(String title) {
			this.title = title;
			return this;
		}

		public Builder setFileSelectListener(
				FileDialogListener fileSelectListener) {
			this.fileSelectListener = fileSelectListener;
			return this;
		}

		/**
		 * 必须强制设置dialog的大小,因为ListView大小必须确定,否则ListView的Adapter的getView会执行很多遍,
		 * 次数取决于listview最终能显示多少项。
		 * 
		 * @return
		 */
		public FileDialog create(int width, int height) {
			final FileDialog dialog = new FileDialog(context);
			dialogView = new FileDialogView(context);
			dialogView.setFileMode(fileMode);
			dialogView.setInitialPath(initialPath);
			dialogView.openFolder();
			dialog.setTitle(title);
			dialog.setCancelable(cancelable);
			dialog.setCanceledOnTouchOutside(canceledOnTouchOutside);
			dialog.setContentView(dialogView, new LayoutParams(
					LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
			if (width > 0 && height > 0) {
				dialog.getWindow().setLayout(width, height);
			}
			Button okButton = (Button) dialogView
					.findViewById(R.id.button_dialog_file_ok);
			Button cancelButton = (Button) dialogView
					.findViewById(R.id.button_dialog_file_cancel);
			okButton.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					// 点击确定按钮,返回文件列表
					if (fileSelectListener != null) {
						if (dialogView.getSelectedFiles().size() > 0) {
							fileSelectListener.onFileSelected(dialogView
									.getSelectedFiles());
						} else {
							fileSelectListener.onFileCanceled();
						}
					}
					dialog.dismiss();
				}
			});
			cancelButton.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
				        //点击取消按钮,直接dismiss
					if (fileSelectListener != null) {
						fileSelectListener.onFileCanceled();
					}
					dialog.dismiss();
				}
			});
			return dialog;
		}

		/**
		 * 使得FileDialog大小和activity一样,在Activity创建完成之前,返回的数字可能不对
		 * 
		 * @param activity
		 * @return
		 */
		public FileDialog create(Activity activity) {
		        //下面这两个方法是获得窗口的宽高,方法不在这里贴出了,详情见上面给出的项目地址
			int width = DisplayUtil.getWindowWidth(activity);
			int height = DisplayUtil.getWindowHeight(activity);
			return create(width, height);
		}

	}

}


如何使用它:


FileDialog dialog = new FileDialog.Builder(getActivity())
				.setFileMode(FileDialog.FILE_MODE_OPEN_FOLDER_SINGLE)
				.setCancelable(true).setCanceledOnTouchOutside(false)
				.setTitle("selectFolder")
				.setFileSelectListener(new FileDialogListener() {

					@Override
					public void onFileSelected(ArrayList<File> files) {
						if (files.size() > 0) {
							copy2Folder(getSelectedFiles(), files.get(0));
						}
					}

					@Override
					public void onFileCanceled() {
						ToastUtil.showToast(getActivity(), "Copy Cancelled!");
					}
				}).create(getActivity());
		dialog.show();





至于第二种接收系统通知其实在同小异,核心代码都跟上面一样,唯一的区别是,它其实是一个Activity,我们叫它PickerActivity,使用了FileDialogView的Activity,而上面的是Dialog……

要接收打开文件的Intent,要在AndroidMenifest.xml的这个Activity节点***册IntentFilter。如下:

            <intent-filter>
                <action android:name="android.intent.action.GET_CONTENT" />

                <category android:name="android.intent.category.OPENABLE" />
                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="*/*" />
            </intent-filter>

PickerActivity代码,跟FileDialog基本差不多。

public class PickerActivity extends Activity {

	private FileDialogView pickerView;
	private Button cancelButton;
	private Button okButton;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_picker);
		setTitle("Pick A File");
		Intent intent = getIntent();
		if (intent != null
				&& Intent.ACTION_GET_CONTENT.equals(intent.getAction())) {
			pickerView = (FileDialogView) findViewById(R.id.picker);
			pickerView.setFileMode(FileDialog.FILE_MODE_OPEN_FILE_SINGLE);
			pickerView.setInitialPath(Environment.getExternalStorageDirectory()
					.getAbsolutePath());
			pickerView.openFolder();
			cancelButton = (Button) pickerView
					.findViewById(com.example.legendutils.R.id.button_dialog_file_cancel);
			okButton = (Button) pickerView
					.findViewById(com.example.legendutils.R.id.button_dialog_file_ok);
			cancelButton.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					setResult(RESULT_CANCELED);
					finish();
				}
			});
			okButton.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					ArrayList<File> files = pickerView.getSelectedFiles();
					if (files != null && files.size() > 0) {
						File file = files.get(0);
						Intent intent = new Intent();
						Uri uri = Uri.fromFile(file);
						intent.setData(uri);
						setResult(RESULT_OK, intent);
						finish();
					}
				}
			});
		}

	}
}