Wybierz okno dialogowe pliku [zamknięte]

146

Czy ktoś zna pełne okno dialogowe wyboru plików? Może taki, w którym możesz odfiltrować wszystkie pliki oprócz tych z określonymi rozszerzeniami?

Nie znalazłem niczego na tyle lekkiego, aby łatwo go wdrożyć w jednym z moich projektów. Jedyną inną opcją wydaje się być użycie otwartych intencji OI FileManager, ale to wymaga, aby użytkownik miał już zainstalowany menedżer plików.

Byłbym wdzięczny, gdyby ktoś wskazał okno dialogowe, które pozwoliłoby użytkownikowi przeglądać foldery i wybierać plik oraz zwracać ścieżkę.

Aymon Fournier
źródło
5
Jeśli, jak mówisz, „Internet potrzebuje takiego przykładu”, to jest TWOJA okazja, aby stworzyć taki w tak szczytnym celu. SO nie jest witryną „wypożycz programistę”. Z drugiej strony, jeśli próbujesz zbudować / użyć okna dialogowego wyboru plików i napotkasz problemy, to jest to miejsce, w którym możesz zadać konkretne pytanie.
Cal Jacobson
1
sprawdź to dreamincode.net/forums/topic/…
DroidBot,
33
Pytanie brzmi, czy istnieje coś takiego jak ALLREADY, co jest dobre, ponieważ nie chcesz odkrywać na nowo siły.
Velrok
9
To pytanie nie powinno być zamknięte. Miałem zamieścić odpowiedź za pomocą aFileChooser ( github.com/iPaulPro/aFileChooser ), ale nie mogę, więc miejmy nadzieję, że ci, którzy potrzebują tego komentarza.
Tiago
2
Zgadzam się, to przydatne pytanie. Miałem nadzieję, że wniesie do odpowiedzi tę prostą implementację jednoklasową: ninthavenue.com.au/simple-android-file-chooser
Roger Keays.

Odpowiedzi:

184

Musisz tylko nadpisać onCreateDialogw działaniu.

//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
źródło
4
Dodaj możliwość poruszania się po folderach i przejdź do folderu nadrzędnego, i masz to
Aymon Fournier
48
Jeśli nie możesz zmodyfikować powyższego, aby poruszać się po systemie plików, nie wiem, jak zamierzasz go zaszczepić w swojej aplikacji. Kiedy już nagiął „zasady” i napisał dla ciebie kod, mam nadzieję, że tak naprawdę nie będziesz mieć za to okupu.
Blumer
6
Edytowałem powyższy kod, aby pokazać, jak dołączyć foldery. Resztę powinieneś wymyślić. Jeśli zauważysz, że naciśnięty plik jest katalogiem w onClick, po prostu ustaw nową ścieżkę i ponownie wywołaj onCreateDialog.
Nathan Schwermann
1
Hej, co to jest „Environmet”, to jest zmienna, właściwie używam Twojego kodu i nie jest w stanie wykryć, co to jest „Środowisko”.
TRonZ
6
Nie zapomnij dodać uprawnienia <używa-pozwolenia android: name = "android.permission.READ_EXTERNAL_STORAGE" /> do Manifestu
Zar E Ahmer
73

Dzięki za pomysł! Oto zmodyfikowane rozwiązanie:

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;
    }
}

Użyj go w aktywności onCreate (opcja wyboru katalogu jest komentowana):

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 Michailov
źródło
8
Świetna klasa pomocnicza! Znalazłem jedną małą usterkę - przy pierwszym uruchomieniu loadFileList () nie przefiltruje według rozszerzenia pliku, ponieważ nie zostałby jeszcze ustawiony przez SetFileEndsWith. Przerobiłem konstruktor, aby akceptował trzeci parametr fileEnsWith i ustawiłem go w konstruktorze przed wywołaniem loadFileList ().
Southerton
cześć niezły kod, dzięki. czy ten kod może wybrać wiele formatów plików, np. fileDialog.setFileEndsWith (". txt", ". pdf"); lub fileDialog.setFileEndsWith ("fle / *"); proszę odpowiedzieć
Anitha
Nie. Ale to dość łatwe do zmodyfikowania. Problem polega na tym, że .setFileEndsWith () w ogóle nie działa, ponieważ lista plików jest przydzielona w konstruktorze. Musisz zmienić konstruktor, aby akceptował wiele danych wejściowych, a następnie zmienić linię: "boolean endWith = fileEndsWith! = Null? Filename.toLowerCase (). EndWith (fileEndsWith): true;" aby odpowiednio dopasować dowolną strukturę danych, w której je umieścisz. To dość trywialna zmiana.
Tatarize
Wszystkie te przerażające listy słuchaczy i fireEvent (FireHandler <OMG>) wyglądają na niepotrzebne (czy ktoś ich kiedykolwiek używał?), Ale kod działa.
18446744073709551615
cześć, dzięki za świetną klasę pomocnika. Jak mogę ustawić dla tego CanceledOnTouchOutside. Dodałem w filedialog w metodzie pokazowej, ale nie działa dla mnie
Dauezevy
15

Stworzyłem FolderLayoutcoś, co może ci pomóc. Ten link mi pomógł

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);
    }

}

I interfejs, IFolderItemListeneraby dodać, co zrobić po fileItemkliknięciu

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
}

Również XML do zdefiniowania wiersza

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"/>

Jak używać w swojej aplikacji

W twoim xml

foldery.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>

W Twojej aktywności

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();
    }

}

Zaimportuj potrzebne biblioteki. Mam nadzieję, że te pomogą Ci ...

sonu thomas
źródło
bardzo dziękuję, że działa za mnie, po prostu prosta czynność eksploracji plików bez zbędnego
nadużywania
5

Sam ostatnio szukałem przeglądarki plików / folderów i postanowiłem wykonać nową aktywność eksploratora (biblioteka Androida): https://github.com/vaal12/AndroidFileBrowser

Dopasowanie aplikacji testowej https://github.com/vaal12/FileBrowserTestApplication- to przykład użycia.

Umożliwia wybieranie katalogów i plików ze struktury plików telefonu.

Alexey Vassiliev
źródło
sprawdź to też: stackoverflow.com/a/59104787/3141844
Criss
3

Dodając do tego: menedżer plików OI ma publiczny interfejs API zarejestrowany na openintents.org

http://www.openintents.org/filemanager

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

Edward Falk
źródło
Powyższy link już nie działa.
uaaquarius
Tak, wiem. Ktokolwiek utrzymywał openintents.org, pozwolił mu się zepsuć.
Edward Falk
Podziękowania dla Juozasa Kontvainisa, który odkrył nowy link.
Edward Falk
Ponadto: czy istnieje sposób na wyszukiwanie, a nawet przeglądanie zarejestrowanych intencji?
Edward Falk
2

Zaimplementowałem okno dialogowe selektora plików Samsung, które zapewnia możliwość otwierania, zapisywania pliku, filtrowania rozszerzeń plików i tworzenia nowego katalogu w tym samym oknie dialogowym Myślę, że warto spróbować Oto łącze, które musisz zalogować się do witryny programistów Samsung, aby zobacz rozwiązanie

Firas Shrourou
źródło