Pilih File Dialog [ditutup]

146

Adakah yang tahu tentang dialog pilih file yang lengkap? Mungkin satu tempat Anda bisa memfilter semua file kecuali file dengan ekstensi spesifik?

Saya belum menemukan sesuatu yang cukup ringan untuk diimplementasikan dengan mudah ke salah satu proyek saya. Satu-satunya pilihan lain tampaknya menggunakan maksud terbuka OI FileManager, tetapi itu mengharuskan pengguna sudah menginstal file manager.

Saya akan berterima kasih jika seseorang dapat menunjukkan Dialog yang akan memungkinkan pengguna untuk menelusuri folder dan memilih file, dan mengembalikan path.

Aymon Fournier
sumber
5
Jika, seperti yang Anda katakan, "Internet membutuhkan contoh seperti itu," maka ini adalah kesempatan ANDA untuk menciptakannya untuk tujuan yang begitu mulia. SO bukan situs "rent a coder". Di sisi lain, jika Anda mencoba membangun / menggunakan dialog pemilihan file dan mengalami masalah, maka ini adalah tempat untuk datang dengan pertanyaan spesifik Anda.
Cal Jacobson
33
Pertanyaannya adalah apakah sesuatu seperti ALLREADY-nya ada, yang bagus, karena Anda tidak ingin menemukan kembali weel.
Velrok
9
Pertanyaan ini seharusnya tidak ditutup. Saya akan mengirim jawaban dengan aFileChooser ( github.com/iPaulPro/aFileChooser ) tetapi tidak bisa, jadi mari kita berharap mereka yang perlu melihat komentar ini.
Tiago
2
Saya setuju, ini pertanyaan yang bermanfaat. Saya berharap untuk berkontribusi implementasi kelas tunggal sederhana ini untuk jawaban: ninthavenue.com.au/simple-android-file-chooser
Roger Keays

Jawaban:

184

Anda hanya perlu mengganti onCreateDialogdalam suatu Kegiatan.

//In an Activity
private String[] mFileList;
private File mPath = new File(Environment.getExternalStorageDirectory() + "//yourdir//");
private String mChosenFile;
private static final String FTYPE = ".txt";    
private static final int DIALOG_LOAD_FILE = 1000;

private void loadFileList() {
    try {
        mPath.mkdirs();
    }
    catch(SecurityException e) {
        Log.e(TAG, "unable to write on the sd card " + e.toString());
    }
    if(mPath.exists()) {
        FilenameFilter filter = new FilenameFilter() {

            @Override
            public boolean accept(File dir, String filename) {
                File sel = new File(dir, filename);
                return filename.contains(FTYPE) || sel.isDirectory();
            }

        };
        mFileList = mPath.list(filter);
    }
    else {
        mFileList= new String[0];
    }
}

protected Dialog onCreateDialog(int id) {
    Dialog dialog = null;
    AlertDialog.Builder builder = new Builder(this);

    switch(id) {
        case DIALOG_LOAD_FILE:
            builder.setTitle("Choose your file");
            if(mFileList == null) {
                Log.e(TAG, "Showing file picker before loading the file list");
                dialog = builder.create();
                return dialog;
            }
            builder.setItems(mFileList, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    mChosenFile = mFileList[which];
                    //you can do stuff with the file here too
                }
            });
            break;
    }
    dialog = builder.show();
    return dialog;
}
Nathan Schwermann
sumber
4
Tambahkan kemampuan untuk menavigasi folder dan pergi ke folder induk, dan Anda mendapatkannya
Aymon Fournier
48
Jika Anda tidak dapat memodifikasi di atas untuk menavigasi sistem file, saya tidak tahu bagaimana Anda akan mencangkokkannya ke dalam aplikasi Anda. Ketika dia sudah membengkokkan "aturan" dan menulis kode untuk Anda, saya harap Anda tidak benar-benar akan menahan tebusan untuk itu.
Blumer
6
Saya mengedit kode di atas untuk menunjukkan cara memasukkan folder. Anda harus bisa mengetahui sisanya. Jika Anda mendeteksi bahwa file yang ditekan adalah direktori di onClick, tetapkan jalur baru dan panggil onCreateDialog lagi.
Nathan Schwermann
1
Hey whats "Environmet", adalah variabel, sebenarnya saya menggunakan kode Anda dan tidak dapat mendeteksi whats "Environment".
TRONZ
6
Jangan lupa untuk menambahkan <menggunakan-izin android: name = "android.permission.READ_EXTERNAL_STORAGE" /> izin untuk Manifest
Zar E Ahmer
73

Schwiz Thanx untuk ide! Inilah solusi yang dimodifikasi:

public class FileDialog {
    private static final String PARENT_DIR = "..";
    private final String TAG = getClass().getName();
    private String[] fileList;
    private File currentPath;
    public interface FileSelectedListener {
        void fileSelected(File file);
    }
    public interface DirectorySelectedListener {
        void directorySelected(File directory);
    }
    private ListenerList<FileSelectedListener> fileListenerList = new ListenerList<FileDialog.FileSelectedListener>();
    private ListenerList<DirectorySelectedListener> dirListenerList = new ListenerList<FileDialog.DirectorySelectedListener>();
    private final Activity activity;
    private boolean selectDirectoryOption;
    private String fileEndsWith;    

    /**
    * @param activity 
    * @param initialPath
    */
    public FileDialog(Activity activity, File initialPath) {
        this(activity, initialPath, null);
    }

    public FileDialog(Activity activity, File initialPath, String fileEndsWith) {
        this.activity = activity;
        setFileEndsWith(fileEndsWith);
        if (!initialPath.exists()) initialPath = Environment.getExternalStorageDirectory();
            loadFileList(initialPath);
    }

    /**
    * @return file dialog
    */
    public Dialog createFileDialog() {
        Dialog dialog = null;
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);

        builder.setTitle(currentPath.getPath());
        if (selectDirectoryOption) {
            builder.setPositiveButton("Select directory", new OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    Log.d(TAG, currentPath.getPath());
                    fireDirectorySelectedEvent(currentPath);
                }
            });
        }

        builder.setItems(fileList, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                String fileChosen = fileList[which];
                File chosenFile = getChosenFile(fileChosen);
                if (chosenFile.isDirectory()) {
                    loadFileList(chosenFile);
                    dialog.cancel();
                    dialog.dismiss();
                    showDialog();
                } else fireFileSelectedEvent(chosenFile);
            }
        });

        dialog = builder.show();
        return dialog;
    }


    public void addFileListener(FileSelectedListener listener) {
        fileListenerList.add(listener);
    }

    public void removeFileListener(FileSelectedListener listener) {
        fileListenerList.remove(listener);
    }

    public void setSelectDirectoryOption(boolean selectDirectoryOption) {
        this.selectDirectoryOption = selectDirectoryOption;
    }

    public void addDirectoryListener(DirectorySelectedListener listener) {
        dirListenerList.add(listener);
    }

    public void removeDirectoryListener(DirectorySelectedListener listener) {
        dirListenerList.remove(listener);
    }

    /**
    * Show file dialog
    */
    public void showDialog() {
        createFileDialog().show();
    }

    private void fireFileSelectedEvent(final File file) {
        fileListenerList.fireEvent(new FireHandler<FileDialog.FileSelectedListener>() {
            public void fireEvent(FileSelectedListener listener) {
                listener.fileSelected(file);
            }
        });
    }

    private void fireDirectorySelectedEvent(final File directory) {
        dirListenerList.fireEvent(new FireHandler<FileDialog.DirectorySelectedListener>() {
            public void fireEvent(DirectorySelectedListener listener) {
                listener.directorySelected(directory);
            }
        });
    }

    private void loadFileList(File path) {
        this.currentPath = path;
        List<String> r = new ArrayList<String>();
        if (path.exists()) {
            if (path.getParentFile() != null) r.add(PARENT_DIR);
            FilenameFilter filter = new FilenameFilter() {
                public boolean accept(File dir, String filename) {
                    File sel = new File(dir, filename);
                    if (!sel.canRead()) return false;
                    if (selectDirectoryOption) return sel.isDirectory();
                    else {
                        boolean endsWith = fileEndsWith != null ? filename.toLowerCase().endsWith(fileEndsWith) : true;
                        return endsWith || sel.isDirectory();
                    }
                }
            };
            String[] fileList1 = path.list(filter);
            for (String file : fileList1) {
                r.add(file);
            }
        }
        fileList = (String[]) r.toArray(new String[]{});
    }

    private File getChosenFile(String fileChosen) {
        if (fileChosen.equals(PARENT_DIR)) return currentPath.getParentFile();
        else return new File(currentPath, fileChosen);
    }

    private void setFileEndsWith(String fileEndsWith) {
        this.fileEndsWith = fileEndsWith != null ? fileEndsWith.toLowerCase() : fileEndsWith;
    }
}

class ListenerList<L> {
    private List<L> listenerList = new ArrayList<L>();

    public interface FireHandler<L> {
        void fireEvent(L listener);
    }

    public void add(L listener) {
        listenerList.add(listener);
    }

    public void fireEvent(FireHandler<L> fireHandler) {
        List<L> copy = new ArrayList<L>(listenerList);
        for (L l : copy) {
            fireHandler.fireEvent(l);
        }
    }

    public void remove(L listener) {
        listenerList.remove(listener);
    }

    public List<L> getListenerList() {
        return listenerList;
    }
}

Gunakan pada aktivitas onCreate (opsi pemilihan direktori dikomentari):

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    File mPath = new File(Environment.getExternalStorageDirectory() + "//DIR//");
    fileDialog = new FileDialog(this, mPath, ".txt");
    fileDialog.addFileListener(new FileDialog.FileSelectedListener() {
        public void fileSelected(File file) {
            Log.d(getClass().getName(), "selected file " + file.toString());
        }
    });
    //fileDialog.addDirectoryListener(new FileDialog.DirectorySelectedListener() {
    //  public void directorySelected(File directory) {
    //      Log.d(getClass().getName(), "selected dir " + directory.toString());
    //  }
    //});
    //fileDialog.setSelectDirectoryOption(false);
    fileDialog.showDialog();
}
Kirill Mikhailov
sumber
8
Kelas pembantu yang luar biasa! Saya menemukan satu kesalahan kecil - saat pertama kali dijalankan loadFileList () tidak akan memfilter berdasarkan ekstensi file, karena itu belum disetel oleh SetFileEndsWith. Saya ulang konstruktor untuk menerima fileEnsWith parameter ketiga, dan mengaturnya di konstruktor sebelum loadFileList () panggilan.
southerton
hai kode yang bagus, terima kasih. dapat kode ini memilih beberapa format file yaitu fileDialog.setFileEndsWith (". txt", ". pdf"); atau fileDialog.setFileEndsWith ("fle / *"); tolong jawab
Anitha
Tidak. Tapi, ini cukup mudah untuk dimodifikasi. Masalahnya adalah .setFileEndsWith () tidak berfungsi sama sekali, karena daftar file dialokasikan di konstruktor. Anda perlu mengubah konstruktor untuk menerima beberapa input dan kemudian mengubah baris: "boolean endsWith = fileEndsWith! = Null? Filename.toLowerCase (). EndsWith (fileEndsWith): true;" untuk mencocokkan dengan benar apa pun struktur data yang Anda masukkan. Ini adalah perubahan yang sangat sepele.
Tatarize
Semua daftar pendengar yang ditakuti dan fireEvent (FireHandler <OMG>) ini terlihat tidak perlu (apakah seseorang pernah menggunakannya?), Tetapi kodenya berfungsi.
18446744073709551615
hai, terima kasih atas bantuan kelasnya. Bagaimana saya dapat mengaturCanceledOnTouchOutside untuk ini. Saya menambahkan di ajialog dalam metode acara tetapi saya tidak bekerja untuk saya
Dauezevy
15

Saya telah membuat FolderLayoutyang dapat membantu Anda. Tautan ini membantu saya

folderview.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView android:id="@+id/path" android:text="Path"
        android:layout_width="match_parent" android:layout_height="wrap_content"></TextView>
    <ListView android:layout_width="fill_parent"
        android:layout_height="wrap_content" android:id="@+id/list"></ListView>

</LinearLayout>

FolderLayout.java

package com.testsample.activity;




   public class FolderLayout extends LinearLayout implements OnItemClickListener {

    Context context;
    IFolderItemListener folderListener;
    private List<String> item = null;
    private List<String> path = null;
    private String root = "/";
    private TextView myPath;
    private ListView lstView;

    public FolderLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        // TODO Auto-generated constructor stub
        this.context = context;


        LayoutInflater layoutInflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = layoutInflater.inflate(R.layout.folderview, this);

        myPath = (TextView) findViewById(R.id.path);
        lstView = (ListView) findViewById(R.id.list);

        Log.i("FolderView", "Constructed");
        getDir(root, lstView);

    }

    public void setIFolderItemListener(IFolderItemListener folderItemListener) {
        this.folderListener = folderItemListener;
    }

    //Set Directory for view at anytime
    public void setDir(String dirPath){
        getDir(dirPath, lstView);
    }


    private void getDir(String dirPath, ListView v) {

        myPath.setText("Location: " + dirPath);
        item = new ArrayList<String>();
        path = new ArrayList<String>();
        File f = new File(dirPath);
        File[] files = f.listFiles();

        if (!dirPath.equals(root)) {

            item.add(root);
            path.add(root);
            item.add("../");
            path.add(f.getParent());

        }
        for (int i = 0; i < files.length; i++) {
            File file = files[i];
            path.add(file.getPath());
            if (file.isDirectory())
                item.add(file.getName() + "/");
            else
                item.add(file.getName());

        }

        Log.i("Folders", files.length + "");

        setItemList(item);

    }

    //can manually set Item to display, if u want
    public void setItemList(List<String> item){
        ArrayAdapter<String> fileList = new ArrayAdapter<String>(context,
                R.layout.row, item);

        lstView.setAdapter(fileList);
        lstView.setOnItemClickListener(this);
    }


    public void onListItemClick(ListView l, View v, int position, long id) {
        File file = new File(path.get(position));
        if (file.isDirectory()) {
            if (file.canRead())
                getDir(path.get(position), l);
            else {
//what to do when folder is unreadable
                if (folderListener != null) {
                    folderListener.OnCannotFileRead(file);

                }

            }
        } else {

//what to do when file is clicked
//You can add more,like checking extension,and performing separate actions
            if (folderListener != null) {
                folderListener.OnFileClicked(file);
            }

        }
    }

    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        // TODO Auto-generated method stub
        onListItemClick((ListView) arg0, arg0, arg2, arg3);
    }

}

Dan Antarmuka IFolderItemListeneruntuk menambahkan apa yang harus dilakukan ketika fileItemdiklik

IFolderItemListener.java

public interface IFolderItemListener {

    void OnCannotFileRead(File file);//implement what to do folder is Unreadable
    void OnFileClicked(File file);//What to do When a file is clicked
}

Juga xml untuk mendefinisikan baris

row.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rowtext" android:layout_width="fill_parent"
    android:textSize="23sp" android:layout_height="match_parent"/>

Cara Menggunakan di Aplikasi Anda

Di xml Anda,

folder.xml

<?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="horizontal" android:weightSum="1">
    <com.testsample.activity.FolderLayout android:layout_height="match_parent" layout="@layout/folderview"
        android:layout_weight="0.35"
        android:layout_width="200dp" android:id="@+id/localfolders"></com.testsample.activity.FolderLayout></LinearLayout>

Dalam Aktivitas Anda,

SampleFolderActivity.java

public class SampleFolderActivity extends Activity implements IFolderItemListener {

    FolderLayout localFolders;

    /** Called when the activity is first created. */

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        localFolders = (FolderLayout)findViewById(R.id.localfolders);
        localFolders.setIFolderItemListener(this);
            localFolders.setDir("./sys");//change directory if u want,default is root   

    }

    //Your stuff here for Cannot open Folder
    public void OnCannotFileRead(File file) {
        // TODO Auto-generated method stub
        new AlertDialog.Builder(this)
        .setIcon(R.drawable.icon)
        .setTitle(
                "[" + file.getName()
                        + "] folder can't be read!")
        .setPositiveButton("OK",
                new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog,
                            int which) {


                    }
                }).show();

    }


    //Your stuff here for file Click
    public void OnFileClicked(File file) {
        // TODO Auto-generated method stub
        new AlertDialog.Builder(this)
        .setIcon(R.drawable.icon)
        .setTitle("[" + file.getName() + "]")
        .setPositiveButton("OK",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,
                            int which) {


                    }

                }).show();
    }

}

Impor perpustakaan yang dibutuhkan. Semoga ini bisa membantu Anda ...

sonu thomas
sumber
terima kasih banyak yang melakukan pekerjaan untuk saya, hanya aktivitas menjelajahi file sederhana tanpa mengasapi yang tidak perlu
Mike76
3

Menambahkan ke campuran: File Manager OI memiliki api publik terdaftar di openintents.org

http://www.openintents.org/filemanager

http://www.openintents.org/action/org-openintents-action-pick-file/

Edward Falk
sumber
Tautan di atas tidak berfungsi lagi.
uaaquarius
Ya saya tahu. Siapa pun yang memelihara openintents.org telah membiarkannya rusak.
Edward Falk
Terima kasih kepada Juozas Kontvainis yang menemukan tautan baru.
Edward Falk
Juga: apakah ada cara untuk mencari, atau bahkan menelusuri maksud terdaftar?
Edward Falk
2

Saya telah menerapkan Samsung Berkas Selector Dialog, ia menyediakan kemampuan untuk membuka, menyimpan file, penyaring ekstensi file, dan membuat direktori baru pada dialog yang sama saya pikir itu layak mencoba Berikut adalah link Anda harus login untuk Samsung situs pengembang untuk lihat solusinya

Firas Shrourou
sumber