两个Android选择文件对话框

这个项目以及代码中使用的未在下面代码给出源码的方法都在这里: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的代码(这个项目不难,代码里面的注释应该足够清楚了……)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/**
  * 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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
  * 文件列表单个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以方便使用。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
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);
         }
 
     }
 
}


如何使用它:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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。如下:

1
2
3
4
5
6
7
8
             < 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基本差不多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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();
                     }
                 }
             });
         }
 
     }
}


本文出自 “NashLegend” 博客,请务必保留此出处http://nashlegend.blog.51cto.com/5635342/1569433

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值