Elija el diálogo de archivo [cerrado]

146

¿Alguien sabe de un diálogo completo de elegir archivo? ¿Tal vez uno donde pueda filtrar todos los archivos, excepto los que tengan extensiones específicas?

No he encontrado nada lo suficientemente ligero como para implementarlo fácilmente en uno de mis proyectos. La única otra opción parece estar usando las intenciones abiertas de OI FileManager, pero eso requiere que el usuario ya tenga instalado el administrador de archivos.

Estaría agradecido si alguien pudiera señalar un Diálogo que permitiera al usuario explorar carpetas y seleccionar un archivo, y devolver la ruta.

Aymon Fournier
fuente
55
Si, como usted dice, "Internet necesita un ejemplo así", entonces esta es SU oportunidad de crear uno para un propósito tan noble. SO no es un sitio de "alquilar un codificador". Por otro lado, si está tratando de construir / usar un cuadro de diálogo de selección de archivos y tiene problemas, este es el lugar para responder a su pregunta específica.
Cal Jacobson
1
mira
DroidBot
33
La pregunta es si existe algo así como ALLREADY, lo cual es bueno, porque no desea reinventar la suela.
Velrok
9
Esta pregunta no debe cerrarse. Iba a publicar una respuesta con aFileChooser ( github.com/iPaulPro/aFileChooser ) pero no puedo, así que esperemos que quienes necesiten ver este comentario.
Tiago
2
Estoy de acuerdo, esta es una pregunta útil. Esperaba contribuir con esta sencilla implementación de clase única a las respuestas: ninthavenue.com.au/simple-android-file-chooser
Roger Keays

Respuestas:

184

Solo necesita anular onCreateDialogen una Actividad.

//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
fuente
44
Agregue la capacidad de navegar por las carpetas y subir a la carpeta principal, y lo
tendrá
48
Si no puede modificar lo anterior para navegar por el sistema de archivos, no sé cómo va a injertarlo en su aplicación en primer lugar. Cuando ya haya doblado las "reglas" y haya escrito el código para usted, espero que realmente no tenga el rescate de recompensa por eso.
Blumer
66
Edité el código anterior para mostrar cómo incluir las carpetas. Deberías poder averiguar el resto. Si detecta que el archivo presionado es un directorio en onClick, simplemente configure la nueva ruta y llame a onCreateDialog nuevamente.
Nathan Schwermann
1
Hola, ¿cuál es "Environment?", Es una variable, en realidad estoy usando su código y no es capaz de detectar cuál es "Environment".
TRonZ
66
No olvide agregar <usos-permiso android: name = "android.permission.READ_EXTERNAL_STORAGE" /> permiso para Manifiesto
Zar E Ahmer
73

Gracias schwiz por idea! Aquí está la solución 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;
    }
}

Úselo en la actividad onCreate (se comenta la opción de selección de directorio):

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
fuente
8
¡Gran clase de ayuda! Encontré un pequeño error: en la primera ejecución, loadFileList () no se filtrará por extensión de archivo, porque SetFileEndsWith aún no lo establecería. Reformé el constructor para aceptar el tercer parámetro fileEnsWith, y lo configuré en el constructor antes de la llamada loadFileList ().
southerton el
hola buen código, gracias. ¿Puede este código elegir múltiples formatos de archivo, es decir, fileDialog.setFileEndsWith (". txt", ". pdf"); o fileDialog.setFileEndsWith ("fle / *"); por favor answr
Anitha
No. Pero es bastante fácil de modificar. El problema es que .setFileEndsWith () no funciona en absoluto, porque la lista de archivos está asignada en el constructor. Debe cambiar el constructor para aceptar múltiples entradas y luego cambiar la línea: "boolean endsWith = fileEndsWith! = Null? Filename.toLowerCase (). EndsWith (fileEndsWith): true;" para que coincida adecuadamente con la estructura de datos en la que la colocas. Es un cambio bastante trivial.
Tatarizar
Todas estas temidas listas de oyentes y fireEvent (FireHandler <OMG>) parecen innecesarias (¿alguien las usó alguna vez?), Pero el código funciona.
18446744073709551615
hola, gracias por la gran clase de ayuda. ¿Cómo puedo configurar CanceledOnTouchOutside para esto? Agregué el archivo de diálogo en el método show pero no funciona para mí
Dauezevy
15

He creado lo FolderLayoutque puede ayudarte. Este enlace me ayudó

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

}

Y una interfaz IFolderItemListenerpara agregar qué hacer cuando fileItemse hace clic en un

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
}

También un xml para definir la fila

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

Cómo usar en su aplicación

En tu xml,

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>

En su actividad,

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

}

Importar las bibliotecas necesarias. Espero que esto te ayude ...

sonu thomas
fuente
muchas gracias que hace el trabajo por mí, solo una simple actividad de exploración de archivos sin ninguna hinchazón innecesaria
Mike76
3

Agregando a la mezcla: el Administrador de archivos OI tiene una API pública registrada en openintents.org

http://www.openintents.org/filemanager

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

Edward Falk
fuente
El enlace de arriba ya no funciona.
uaaquarius
Sí, lo sé. Quien haya mantenido openintents.org ha dejado que se rompa.
Edward Falk el
Gracias a Juozas Kontvainis que descubrió el nuevo enlace.
Edward Falk
Además: ¿hay alguna forma de buscar, o incluso navegar por los intentos registrados?
Edward Falk
2

He implementado el archivo Samsung Selector de diálogo, que ofrece la posibilidad de abrir, guardar archivos, filtro de extensión de archivo, y crear nuevo directorio en el mismo cuadro de diálogo que creo que vale la pena probar Aquí está el enlace que tiene que conectarse al sitio de desarrolladores de Samsung para ver la solución

Firas Shrourou
fuente