Caixa de diálogo Escolher arquivo [fechado]

146

Alguém sabe de uma caixa de diálogo de escolha de arquivo completa? Talvez aquele em que você possa filtrar todos os arquivos, exceto aqueles com extensões específicas?

Não encontrei nada leve o suficiente para ser implementado facilmente em um dos meus projetos. A única outra opção parece estar usando as intenções abertas do OI FileManager, mas isso requer que o usuário já tenha o gerenciador de arquivos instalado.

Ficaria muito grato se alguém pudesse apontar uma caixa de diálogo que permitisse ao usuário navegar nas pastas, selecionar um arquivo e retornar o caminho.

Aymon Fournier
fonte
5
Se, como você diz, "a Internet precisa de um exemplo", esta é SUA oportunidade de criar um para um propósito tão nobre. SO não é um site "alugue um codificador". Por outro lado, se você estiver tentando criar / usar uma caixa de diálogo de seleção de arquivos e encontrar problemas, então este é o lugar para sua pergunta específica.
precisa saber é o seguinte
1
verifique esta dreamincode.net/forums/topic/… #
DroidBot 18/11
33
A questão é se existe algo como o ALLREADY, o que é bom, porque você não deseja reinventar o weel.
Velrok
9
Esta questão não deve ser encerrada. Eu estava indo postar uma resposta com um arquivoFileChooser ( github.com/iPaulPro/aFileChooser ), mas não posso, então vamos esperar que aqueles que precisam ver este comentário.
Tiago
2
Eu concordo, esta é uma pergunta útil. Eu esperava contribuir com essa implementação simples de classe única para as respostas: ninthavenue.com.au/simple-android-file-chooser
Roger Keays

Respostas:

184

Você só precisa substituir onCreateDialoguma Atividade.

//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
fonte
4
Adicione a capacidade de navegar pelas pastas e ir até a pasta pai e você conseguiu
Aymon Fournier
48
Se você não pode modificar o item acima para navegar no sistema de arquivos, não sei como você o inserirá no aplicativo em primeiro lugar. Quando ele já cumpriu as "regras" e escreveu o código para você, espero que você não tenha o resgate por isso.
Blumer
6
Editei o código acima para mostrar como incluir as pastas. Você deve descobrir o resto. Se você detectar que o arquivo pressionado é um diretório no onClick, defina o novo caminho e chame o onCreateDialog novamente.
Nathan Schwermann
1
Ei, o que é "Environmet", é uma variável, na verdade eu estou usando seu código e não é capaz de detectar o que é "Ambiente".
TRonZ 7/08
6
Não se esqueça de adicionar <permissão de uso android: name = "android.permission.READ_EXTERNAL_STORAGE" /> permissão para manifestar
Zar E Ahmer
73

Thanx schwiz pela idéia! Aqui está a solução modificada:

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

Use-o na atividade onCreate (a opção de seleção de diretório é comentada):

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
fonte
8
Ótima classe auxiliar! Eu encontrei uma pequena falha - na primeira execução, loadFileList () não filtrará por extensão de arquivo, porque ainda não seria definida por SetFileEndsWith. Reescrevi o construtor para aceitar o terceiro parâmetro fileEnsWith e o defini no construtor antes da chamada loadFileList ().
Southerton
oi código legal, obrigado. esse código pode escolher vários formatos de arquivo, por exemplo, fileDialog.setFileEndsWith (". txt", ". pdf"); ou fileDialog.setFileEndsWith ("fle / *"); por favor responda
Anitha
Não. Mas é muito fácil de modificar. O problema é que o .setFileEndsWith () não funciona, porque a lista de arquivos está alocada no construtor. Você precisa alterar o construtor para aceitar várias entradas e alterar a linha: "booleano endsWith = fileEndsWith! = Null? Filename.toLowerCase (). EndsWith (fileEndsWith): true;" para corresponder adequadamente à estrutura de dados em que você a inseriu. É uma mudança bastante trivial.
Tatarize
Todas essas listas de ouvintes temidas e fireEvent (FireHandler <OMG>) parecem desnecessárias (alguém as usou?), Mas o código funciona.
18446744073709551615
oi, obrigado pela excelente classe auxiliar.Como posso definir oCanceledOnTouchOutside para isso. Eu adicionei em filedialog no método show, mas eu não funciona para mim
Dauezevy
15

Eu criei o FolderLayoutque pode ajudá-lo. Esse link me ajudou

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>

Pasta / ProcessoLayout.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);
    }

}

E uma interface IFolderItemListenerpara adicionar o que fazer quando um fileItemé clicado

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
}

Também um xml para definir a linha

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

Como usar em seu aplicativo

No seu xml,

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

Em sua atividade,

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

}

Importe as bibliotecas necessárias. Espero que estes o ajudem ...

sonu thomas
fonte
muito obrigado que faz o trabalho para mim, apenas uma atividade explorar arquivo simples, sem qualquer inchaço desnecessário
Mike76
5

Eu estava procurando um navegador de arquivos / pastas recentemente e decidi fazer uma nova atividade do explorador (biblioteca Android): https://github.com/vaal12/AndroidFileBrowser

Aplicativo de Teste de Correspondência https://github.com/vaal12/FileBrowserTestApplication- é um exemplo de como usar.

Permite escolher diretórios e arquivos da estrutura de arquivos do telefone.

Alexey Vassiliev
fonte
verifique isso também: stackoverflow.com/a/59104787/3141844
Criss
3

Adicionando à mistura: o OI File Manager possui uma API pública registrada em openintents.org

http://www.openintents.org/filemanager

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

Edward Falk
fonte
O link acima não está mais funcionando.
uaaquarius
Sim eu conheço. Quem quer que estivesse mantendo o openintents.org, deixou que se quebrasse.
Edward Falk
Obrigado a Juozas Kontvainis, que descobriu o novo link.
Edward Falk
Além disso: existe uma maneira de pesquisar ou até mesmo procurar as intenções registradas?
Edward Falk
2

Eu implementei o Samsung File Selector Dialog, ele oferece a capacidade de abrir, salvar arquivos, filtro de extensão de arquivo e criar um novo diretório na mesma caixa de diálogo. Acho que vale a pena tentar. Aqui está o link que você deve fazer login no site de desenvolvedores da Samsung para veja a solução

Firas Shrourou
fonte