Android應(yīng)用中實(shí)現(xiàn)選擇本地文件與目錄的實(shí)例分享
文件選擇器
今天給大家分享下文件選擇器的作用 , 具體就是獲取用戶在在SD卡選中的文件/文件夾路徑 ,類似于C#中OpenFileDialog控件(對C#的一站式開發(fā)還是念念不忘)。功能實(shí)現(xiàn)起來比較簡單,主要是幫助大家節(jié)省開發(fā)時間。
網(wǎng)上流傳較廣的一個成品如下 <[Android實(shí)例] 文件選擇器>, 本文也是根據(jù)上面的成品修改而成,使其更易理解,效率更高。 除此之外,主要特色有:
1、我們監(jiān)聽了用戶按下Back鍵的事件,使其返回上一層目錄;
2、針對不同的文件類型(文件vs文件夾 , 目標(biāo)文件vs其他文件)做了特殊處理。
知識點(diǎn)一、 File 類的使用
文件選擇器的主要功能是:瀏覽文件\文件夾、文件類型等;都是通過Java File類來實(shí)現(xiàn)的。
知識點(diǎn)二、調(diào)用方法說明
使用了startActivityForResult()發(fā)起調(diào)用以及onActivityResult()方法接受回調(diào)后的信息。
截圖如下:
其他的也沒什么好說了,大家看看代碼注釋吧~~ so easy - - 。
FileChooserActivity.java 實(shí)現(xiàn)文件選擇的類 。
public class CopyOfFileChooserActivity extends Activity { private String mSdcardRootPath ; //sdcard 根路徑 private String mLastFilePath ; //當(dāng)前顯示的路徑 private ArrayList<FileInfo> mFileLists ; private FileChooserAdapter mAdatper ; //配置適配器 private void setGridViewAdapter(String filePath) { updateFileItems(filePath); mAdatper = new FileChooserAdapter(this , mFileLists); mGridView.setAdapter(mAdatper); } //根據(jù)路徑更新數(shù)據(jù),并且通知Adatper數(shù)據(jù)改變 private void updateFileItems(String filePath) { mLastFilePath = filePath ; mTvPath.setText(mLastFilePath); if(mFileLists == null) mFileLists = new ArrayList<FileInfo>() ; if(!mFileLists.isEmpty()) mFileLists.clear() ; File[] files = folderScan(filePath); if(files == null) return ; for (int i = 0; i < files.length; i++) { if(files[i].isHidden()) // 不顯示隱藏文件 continue ; String fileAbsolutePath = files[i].getAbsolutePath() ; String fileName = files[i].getName(); boolean isDirectory = false ; if (files[i].isDirectory()){ isDirectory = true ; } FileInfo fileInfo = new FileInfo(fileAbsolutePath , fileName , isDirectory) ; //添加至列表 mFileLists.add(fileInfo); } //When first enter , the object of mAdatper don't initialized if(mAdatper != null) mAdatper.notifyDataSetChanged(); //重新刷新 } //獲得當(dāng)前路徑的所有文件 private File[] folderScan(String path) { File file = new File(path); File[] files = file.listFiles(); return files; } private AdapterView.OnItemClickListener mItemClickListener = new OnItemClickListener() { public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { FileInfo fileInfo = (FileInfo)(((FileChooserAdapter)adapterView.getAdapter()).getItem(position)); if(fileInfo.isDirectory()) //點(diǎn)擊項為文件夾, 顯示該文件夾下所有文件 updateFileItems(fileInfo.getFilePath()) ; else if(fileInfo.isPPTFile()){ //是ppt文件 , 則將該路徑通知給調(diào)用者 Intent intent = new Intent(); intent.putExtra(EXTRA_FILE_CHOOSER, fileInfo.getFilePath()); setResult(RESULT_OK , intent); finish(); } else { //其他文件..... toast(getText(R.string.open_file_error_format)); } } }; public boolean onKeyDown(int keyCode , KeyEvent event){ if(event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_BACK){ backProcess(); return true ; } return super.onKeyDown(keyCode, event); } //返回上一層目錄的操作 public void backProcess(){ //判斷當(dāng)前路徑是不是sdcard路徑 , 如果不是,則返回到上一層。 if (!mLastFilePath.equals(mSdcardRootPath)) { File thisFile = new File(mLastFilePath); String parentFilePath = thisFile.getParent(); updateFileItems(parentFilePath); } else { //是sdcard路徑 ,直接結(jié)束 setResult(RESULT_CANCELED); finish(); } } }
界面依舊很丑陋,囧 ,大家可以根據(jù)需要在此基礎(chǔ)上添加功能,下面選擇目錄也基本上同理。
目錄選擇器
chooserdialog.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="40dip"> <Button android:layout_width="40dip" android:layout_height="40dip" android:text="HOME" android:id="@+id/btn_home" android:layout_gravity="left" android:layout_weight="1" /> <LinearLayout android:layout_width="140dip" android:layout_height="35dip" android:id="@+id/dir_layout" android:gravity="center" android:layout_weight="1"> </LinearLayout> <!-- <TextView android:layout_width="140dip" android:layout_height="35dip" android:id="@+id/dir_str" android:gravity="center" android:layout_weight="1" /> --> <Button android:layout_width="40dip" android:layout_height="40dip" android:text="BACK" android:id="@+id/btn_back" android:layout_gravity="right" android:layout_weight="1" /> </LinearLayout> <ListView android:layout_width="fill_parent" android:layout_height="300dip" android:id="@+id/list_dir" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/btn_ok" android:text="OK"/> </LinearLayout>
package hkp.dirchooser; import java.io.File; import java.util.ArrayList; import java.util.List; import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.view.Gravity; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; public class DirChooserDialog extends Dialog implements android.view.View.OnClickListener{ private ListView list; ArrayAdapter<String> Adapter; ArrayList<String> arr=new ArrayList<String>(); Context context; private String path; private TextView title; private EditText et; private Button home,back,ok; private LinearLayout titleView; private int type = 1; private String[] fileType = null; public final static int TypeOpen = 1; public final static int TypeSave = 2; /** * @param context * @param type 值為1表示創(chuàng)建打開目錄類型的對話框,2為創(chuàng)建保存文件到目錄類型的對話框 * @param fileType 要過濾的文件類型,null表示只選擇目錄 * @param resultPath 點(diǎn)OK按鈕返回的結(jié)果,目錄或者目錄+文件名 */ public DirChooserDialog(Context context,int type,String[]fileType,String resultPath) { super(context); // TODO Auto-generated constructor stub this.context = context; this.type = type; this.fileType = fileType; this.path = resultPath; } /* (non-Javadoc) * @see android.app.Dialog#dismiss() */ @Override public void dismiss() { // TODO Auto-generated method stub super.dismiss(); } /* (non-Javadoc) * @see android.app.Dialog#onCreate(android.os.Bundle) */ @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.chooserdialog); path = getRootDir(); arr = (ArrayList<String>) getDirs(path); Adapter = new ArrayAdapter<String>(context,android.R.layout.simple_list_item_1, arr); list = (ListView)findViewById(R.id.list_dir); list.setAdapter(Adapter); list.setOnItemClickListener(lvLis); home = (Button) findViewById(R.id.btn_home); home.setOnClickListener(this); back = (Button) findViewById(R.id.btn_back); back.setOnClickListener(this); ok = (Button) findViewById(R.id.btn_ok); ok.setOnClickListener(this); titleView = (LinearLayout) findViewById(R.id.dir_layout); if(type == TypeOpen){ title = new TextView(context); titleView.addView(title); title.setText(path); }else if(type == TypeSave){ et = new EditText(context); et.setWidth(240); et.setHeight(70); et.setGravity(Gravity.CENTER); et.setPadding(0, 2, 0, 0); titleView.addView(et); et.setText("wfFileName"); } // title = (TextView) findViewById(R.id.dir_str); // title.setText(path); } //動態(tài)更新ListView Runnable add=new Runnable(){ @Override public void run() { // TODO Auto-generated method stub arr.clear(); //System.out.println("Runnable path:"+path); //必須得用這種方法為arr賦值才能更新 List<String> temp = getDirs(path); for(int i = 0;i < temp.size();i++) arr.add(temp.get(i)); Adapter.notifyDataSetChanged(); } }; private OnItemClickListener lvLis=new OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { String temp = (String) arg0.getItemAtPosition(arg2); //System.out.println("OnItemClick path1:"+path); if(temp.equals("..")) path = getSubDir(path); else if(path.equals("/")) path = path+temp; else path = path+"/"+temp; //System.out.println("OnItemClick path2"+path); if(type == TypeOpen) title.setText(path); Handler handler=new Handler(); handler.post(add); } }; private List<String> getDirs(String ipath){ List<String> file = new ArrayList<String>(); //System.out.println("GetDirs path:"+ipath); File[] myFile = new File(ipath).listFiles(); if(myFile == null){ file.add(".."); }else for(File f: myFile){ //過濾目錄 if(f.isDirectory()){ String tempf = f.toString(); int pos = tempf.lastIndexOf("/"); String subTemp = tempf.substring(pos+1, tempf.length()); // String subTemp = tempf.substring(path.length(),tempf.length()); file.add(subTemp); //System.out.println("files in dir:"+subTemp); } //過濾知道類型的文件 if(f.isFile() && fileType != null){ for(int i = 0;i< fileType.length;i++){ int typeStrLen = fileType[i].length(); String fileName = f.getPath().substring(f.getPath().length()- typeStrLen); if (fileName.toLowerCase().equals(fileType[i])) { file.add(f.toString().substring(path.length()+1,f.toString().length())); } } } } if(file.size()==0) file.add(".."); // System.out.println("file[0]:"+file.get(0)+" File size:"+file.size()); return file; } /* (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ @Override public void onClick(View v) { // TODO Auto-generated method stub if(v.getId() == home.getId()){ path = getRootDir(); if(type == TypeOpen) title.setText(path); Handler handler=new Handler(); handler.post(add); }else if(v.getId() == back.getId()){ path = getSubDir(path); if(type == TypeOpen) title.setText(path); Handler handler=new Handler(); handler.post(add); }else if(v.getId() == ok.getId()){ dismiss(); if(type == TypeSave) path = path+"/"+et.getEditableText().toString()+".wf"; Toast.makeText(context, path, Toast.LENGTH_SHORT).show(); } } private String getSDPath(){ File sdDir = null; boolean sdCardExist = Environment.getExternalStorageState() .equals(android.os.Environment.MEDIA_MOUNTED); //判斷sd卡是否存在 if(sdCardExist) { sdDir = Environment.getExternalStorageDirectory();//獲取根目錄 } if(sdDir == null){ //Toast.makeText(context, "No SDCard inside!",Toast.LENGTH_SHORT).show(); return null; } return sdDir.toString(); } private String getRootDir(){ String root = "/"; path = getSDPath(); if (path == null) path="/"; return root; } private String getSubDir(String path){ String subpath = null; int pos = path.lastIndexOf("/"); if(pos == path.length()){ path = path.substring(0,path.length()-1); pos = path.lastIndexOf("/"); } subpath = path.substring(0,pos); if(pos == 0) subpath = path; return subpath; } }
package hkp.dirchooser; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button btn = (Button) findViewById(R.id.btn_open); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub String path = null; String [] fileType = {"dst"};//要過濾的文件類型列表 DirChooserDialog dlg = new DirChooserDialog(MainActivity.this,2,fileType,path); dlg.setTitle("Choose dst file dir"); dlg.show(); } }); } }
相關(guān)文章
Android數(shù)據(jù)庫中事務(wù)操作方法之銀行轉(zhuǎn)賬示例
這篇文章主要介紹了Android數(shù)據(jù)庫中事務(wù)操作方法之銀行轉(zhuǎn)賬,以具體的銀行轉(zhuǎn)賬為例分析了Android數(shù)據(jù)庫操作中事務(wù)的使用與回滾相關(guān)操作技巧,需要的朋友可以參考下2017-08-08android項目手機(jī)衛(wèi)士來電顯示號碼歸屬地
由于詐騙電話越來越猖狂,號碼歸屬地顯示越來越重要,本篇文章主要介紹了android手機(jī)衛(wèi)士來電顯示號碼歸屬地,有要的朋友可以了解一下。2016-10-10Android判斷用戶的網(wǎng)絡(luò)類型實(shí)例講解(2/3/4G、wifi)
這篇文章主要介紹了Android判斷用戶的網(wǎng)絡(luò)類型實(shí)例,用戶的網(wǎng)絡(luò)類型分為2G、3G、4G、wifi,通過Android如何判斷用戶的網(wǎng)絡(luò)類型,本文為大家揭曉2015-12-12TextView實(shí)現(xiàn)圖文混合編排的方法
這篇文章主要為大家詳細(xì)介紹了TextView實(shí)現(xiàn)圖文混合編排的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08Android Listview點(diǎn)贊問題關(guān)于圖片重復(fù)問題
最近在開發(fā)android方面的項目時,遇到很多問題,下面小編以listview 與 baseadapter結(jié)合使用為例,給大家分享下關(guān)于點(diǎn)贊的的時候 圖片重復(fù)問題的解決方法,一起看看吧2016-11-11Android中判斷網(wǎng)絡(luò)連接是否可用及監(jiān)控網(wǎng)絡(luò)狀態(tài)
獲取網(wǎng)絡(luò)信息需要在AndroidManifest.xml文件中加入相應(yīng)的權(quán)限,接下來詳細(xì)介紹Android中判斷網(wǎng)絡(luò)連接是否可用及監(jiān)控網(wǎng)絡(luò)狀態(tài),感興趣的朋友可以參考下2012-12-12Android編程布局控件之AbsoluteLayout用法實(shí)例分析
這篇文章主要介紹了Android編程布局控件之AbsoluteLayout用法,結(jié)合實(shí)例形式簡單分析了Android絕對布局AbsoluteLayout的使用技巧,需要的朋友可以參考下2015-12-12android實(shí)現(xiàn)動態(tài)顯隱進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)動態(tài)顯隱進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07Android app開發(fā)中的Fragment入門學(xué)習(xí)教程
這篇文章主要介紹了Android app開發(fā)中的Fragment入門學(xué)習(xí)教程,包括Fragment的創(chuàng)建和XML布局文件中的Fragment定義等,需要的朋友可以參考下2016-02-02