Создание удобного OpenFileDialog для Android
Наверное, как и многие разработчики под Android, столкнулся на днях с необходимостью реализовать в своем приложении выбор файла пользователем. Так как изначально в Android такого функционала нет, обратился к великому и ужасному. Это показалось мне странным, но из вороха вопросов на stackoverflow и небольшого числа отечественных форумов можно выделить всего три основных источника:
- Android File Dialog – почти все ссылки из stackoverflow ведут сюда. В принципе, неплохое решение, но реализовано через отдельную activity, а хотелось чего-то в духе OpenFileDialog’а из .Net.
- В данной статье речь идет вообще об отдельном файл-менеджере, и почерпнуть какие-то идеи из неё не удалось.
- Идея же отсюда очень понравилась, однако, как мне показалось реализовать все это можно несколько красивее.
В результате, начав реализовывать своё решение, я столкнулся с некоторыми трудностями решать которые показалось очень интересно. А посему, решил описать в данной статье не просто готовое решение, а все шаги, которые к нему привели. Желающие пройти их вместе –
Итак, приступим! В любой привычной среде (я использую IntelliJ IDEA) создадим новое приложение. На главной activity расположим одну единственную кнопку и напишем к ней, пока пустой, обработчик нажатия:
Создадим новый класс с конструктором:
а в обработчике кнопки вызовем диалог:
Кнопки показались, теперь надо бы и сами файлы найти. Начнем поиск с корня sdcard, для чего определим поле:
и реализуем следующий метод:
(так как главное требование к классу – работать сразу у любого разработчика, без подключения дополнительных библиотек, — то никаких google-collections использовать не будем, и с массивами приходится работать по старинке), а в конструкторе к вызову setNegativeButton добавим .setItems(getFiles(currentPath), null).
Что же, неплохо, однако файлы не отсортированы. Реализуем для этого дела Adapter как внутренний класс, заменим setItems на setAdapter и немного перепишем getFiles:
Еще лучше, но нам надо по клику на папке идти внутрь. Можно достучаться до встроенного listview, но я просто подменил его собственным (это потом пригодится). Плюс, изменения adapter’а внутри обработчика listview вызывало exception, и список файлов пришлось вынести в отдельное поле:
Отлично, вот только нажав на папку Android мы получаем список всего из одного каталога data, и наше окно тут же уменьшается в размере.
Возможно это нормально, но мне это не понравилось, и я стал искать возможности размер сохранить. Единственный найденный мною вариант – это установка setMinimumHeight. Установка этого свойства для listview вызвала дополнительные проблемы, но они решились оберткой его в LinearLayout:
Результат, все равно получился немного не таким, каким хотелось бы: при старте диалог развернут на весь экран, а после перехода в каталог Android – уменьшается до 750px. Да еще и экраны разных устройств имеют разную высоту. Решим сразу обе этих проблемы, установив setMinimumHeight в максимально возможную для текущего экрана:
Не нужно пугаться того, что мы устанавливаем в setMinimumHeight полный размер экрана, сама система уменьшит значение до максимально допустимого.
Теперь появляется проблема понимания пользователя, в каком каталоге он сейчас находится, и возврата вверх. Давайте разберемся с первой. Вроде все легко — установить значение title в currentPath и менять его при изменении последнего. Добавим в конструктор и в метод RebuildFiles вызов setTitle(currentPath).
А нет – заголовок не изменился. Почему не срабатывает setTitle после показа диалога, документация молчит. Однако мы может это исправить, создав свой заголовок и подменив им стандартный:
И снова не все ладно: если пройти достаточно далеко, то строка в заголовок влезать не будет
Решение с установкой setMaximumWidth не верно, так как пользователь будет видеть только начало длинного пути. Не знаю, насколько верно мое решение, но я сделал так:
Решим теперь проблему с возвратом. Это достаточно легко, учитывая, что у нас есть LinearLayout. Добавим в него еще один TextView и немного отрефракторим код:
Возможность возвращаться на шаг вверх, может привести пользователя в каталоги, к которым ему доступ запрещен, поэтому изменим функцию RebuildFiles:
(cообщение пока не очень информативное, но вскоре мы добавим разработчику возможность исправить это).
Ни один OpenFileDialog не обходится без фильтра. Добавим и его:
Обратите внимание — фильтр принимает регулярное выражение. Казалось бы – все хорошо, но первая выборка файлов сработает в конструкторе, до присвоения фильтра. Перенесем её в переопределенный метод show:
Осталось совсем чуть-чуть: вернуть выбранный файл. Опять же, я так и не понял зачем нужно устанавливать CHOICE_MODE_SINGLE, а потом все равно писать лишний код для подсветки выбранного элемента, когда он (код) и так будет работать без CHOICE_MODE_SINGLE, а потому обойдемся без него:
Источник
File picker dialog android
FilePicker
Android Library to select files/directories from Device Storage
And Don’t Forget To Follow Me On Instagram
Library available at JitPack.io
Latest version of this library is migrated to androidx
- Easy to Implement.
- No permissions required.
- Files, Directory Selection.
- Single or Multiple File selection.
Add it in your root build.gradle at the end of repositories:
Step 2. Add the dependency
If you are targeting Android 10 or higher. Set this to your manifest
Start by creating an instance of DialogProperties .
Now ‘DialogProperties’ has certain parameters.
Assign values to each Dialog Property using DialogConfig class.
Next create an instance of FilePickerDialog , and pass Context and DialogProperties references as parameters. Optional: You can change the title of dialog. Default is current directory name. Set the positive button string. Default is Select. Set the negative button string. Defalut is Cancel.
Next, Attach DialogSelectionListener to FilePickerDialog as below,
An array of paths is returned whenever user press the select button`.
Use dialog.show() method to show dialog.
Marshmallow and above requests for the permission on runtime. You should override onRequestPermissionsResult in Activity/AppCompatActivity class and show the dialog only if permissions have been granted.
- defaultValue , error_dir , root_dir , offset_dir must have valid directory/file paths.
- defaultValue paths should end with ‘:’.
- defaultValue can have multiple paths, there should be a ‘:’ between two paths.
- extensions must not have ‘.’.
- extensions should end with ‘:’ , also have ‘:’ between two extensions. eg. /sdcard:/mnt:
About
Android Library to select files/directories from Device Storage.
Источник
File picker dialog android
The project is no longer being maintained.
Super Lite Android Library to select files/directories from Device Storage.
Read all about internal classes and functions in the wiki.
- Easy to Implement.
- No permissions required.
- Files, Directory Selection.
- Single or Multiple File selection.
- Library is also Available in MavenCentral, So just put this in your app dependencies to use it:
Start by creating an instance of DialogProperties .
Now ‘DialogProperties’ has certain parameters.
Assign values to each Dialog Property using DialogConfig class.
Next create an instance of FilePickerDialog , and pass Context and DialogProperties references as parameters. Optional: You can change the title of dialog. Default is current directory name. Set the positive button string. Default is Select. Set the negative button string. Defalut is Cancel.
Next, Attach DialogSelectionListener to FilePickerDialog as below,
An array of paths is returned whenever user press the select button`.
Use dialog.show() method to show dialog.
Marshmallow and above requests for the permission on runtime. You should override onRequestPermissionsResult in Activity/AppCompatActivity class and show the dialog only if permissions have been granted.
Start by declaring FilePickerPreference in your settings xml file as:
Implement Preference.OnPreferenceChangeListener to class requiring selected values and Override onPreferenceChange(Preference, Object) method. Check for preference key using Preference reference.
Typecast Object o into String Object and use split(String) function in String class to get array of selected files.
That’s It. You are good to move further.
- defaultValue , error_dir , root_dir , offset_dir must have valid directory/file paths.
- defaultValue paths should end with ‘:’.
- defaultValue can have multiple paths, there should be a ‘:’ between two paths.
- extensions must not have ‘.’.
- extensions should end with ‘:’ , also have ‘:’ between two extensions. eg. /sdcard:/mnt:
FilePickerPreference stores selected directories/files as a String . It delimits multiple files/directories using ‘:’ char .
Источник
File picker dialog android
File Picker
Android Library to select Files/Directories from Device Storage.
- Easy to Implement.
- No permissions required.
- File, Directory Selection.
- Single or Multiple File/Directory Selection.
- Internationalization: Arabic, Bengali, Catalan, Chinese, Czech, Dutch, English, French, German, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean, Polish, Portuguese, Romanian, Russian, Spanish, Swedish, Turkish, Ukrainian and Urdu.
Add it in your root build.gradle at the end of repositories:
Step 2. Add the dependency
If you are targeting Android 10 or higher. Set this to your manifest
Start by creating an instance of DialogProperties .
Note: If you pass false to the second constructor is like calling the first constructor and loads the default directory, if you pass true loads the external storage directory.
Now ‘DialogProperties’ has certain parameters.
Assign values to each Dialog Property using DialogConfig class.
Note: For the root, error directory, and offset, be sure to pass them valid directory/file paths.
Next create an instance of FilePickerDialog , and pass Context and DialogProperties references as parameters. Optional: You can change the title of dialog. Default is current directory name. Set the positive button string. Default is Select. Set the negative button string. Defalut is Cancel.
Next, Attach DialogSelectionListener to FilePickerDialog as below,
An array of paths is returned whenever user press the select button`.
Use dialog.show() method to show dialog.
Marshmallow and above requests for the permission on runtime. You should override onRequestPermissionsResult in Activity/AppCompatActivity class and show the dialog only if permissions have been granted.
Initial dialog at the root
Dialog after opening a folder
Dialog after selecting a file in single mode
Dialog after selecting some files in multi mode
Initial dialog at the root
Dialog after opening a folder
Dialog after selecting a folder in single mode
Dialog after selecting some folders in multi mode
Copyright (C) 2020 File-Picker
Licensed under the Apache License, Version 2.0 (the «License»); you may not use this file except in compliance with the License. You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an «AS IS» BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
About
Android Library to select Files/Directories from Device Storage.
Источник