File Explorer
lv_file_explorer
provides a UI enabling the end user to browse the contents of a
file system. Its main area is called the "Browsing Area" and provides the list of
files contained in the currently-viewed directory.
When enabled, there is also a "Quick-Access" panel on the left, which provides a convenient way to reach parts of the file system that are frequently accessed. Available "Quick-Access" destinations are:
File System,
HOME,
Video,
Pictures,
Music, and
Documents.
You specify what paths these lead to during lv_file_explorer
's initialization.
lv_file_explorer
only provides the file browsing and events caused by user
activity (e.g. clicking a file), but does not provide the actual file operations.
Client code must hook various events and decide what to do when they are emitted
(e.g. a click or double-click on a file). The actions taken might to open the file,
display it, send it to some other part of the application, etc..
lv_file_explorer
passes the full path and name of file that was clicked to the
event callback functions. What happens next is up to the application designer.
lv_file_explorer
uses the Table (lv_table) Widget for the "Browsing Area", and the
List (lv_list) Widget for the "Quick-Access" panel when it is enabled. Thus,
LV_USE_TABLE
macro must be set to a non-zero value in lv_conf.h
in
order to use lv_file_explorer
, and and LV_USE_LIST
must be set to a
non-zero value to use the "Quick-Access" panel.
Note
In order to use File Explorer, File System (lv_fs_drv) has to be set up and know about all the drive letters you use when passing paths to File System (described below).
Prerequisites
If you haven't already done so, you will need to learn about the LVGL File System abstraction, since it must be set up and be functional for File Explorer to work.
Usage
Set LV_USE_FILE_EXPLORER
to a non-zero value in lv_conf.h
.
First use lv_file_explorer_create(lv_screen_active()) to create a File Explorer. The default size is the screen size. After that, you can customize the style like any Widget.
The size of the current_path
buffer is set by LV_FILE_EXPLORER_PATH_MAX_LEN
in lv_conf.h
.
The object hierarchy of a freshly-created File Explorer looks like this:
File Explorer
: occupies full area of parent Widget, typically a Screen (Flex-Flow COLUMN)Container
: occupies full area of File Explorer (Flex grow 1)Quick-Access Panel
:Device List
: grows to accommodate childrenFile System
: button
Places List
: grows to accommodate childrenHOME
: buttonVideo
: buttonPictures
: buttonMusic
: buttonDocuments
: button
Browser Panel
:Header
: 14% ofBrowser Panel
heightCurrent Path
: label
File Table
: with 1 column, 86% ofBrowser Panel
height
Fields:
home_dir
= NULLvideo_dir
= NULLpictures_dir
= NULLmusic_dir
= NULLdocs_dir
= NULLfs_dir
= NULLcurrent_path
= [empty buffer]sel_fn
(selected file)sort
(defaultLV_EXPLORER_SORT_NONE
)
Accessing the Parts
This list of functions provides access to the parts shown in diagram above:
lv_file_explorer_get_selected_file_name(explorer) (pointer to NUL-terminated string containing file-path user selected; typically used inside an
LV_EVENT_CLICKED
event)lv_file_explorer_get_current_path(explorer) (pointer to
current_path
char
buffer)lv_file_explorer_get_file_table(explorer) (pointer to
File Table
Table (lv_table) Widget)lv_file_explorer_get_header(explorer) (pointer to
Header
Base Widget Widget)lv_file_explorer_get_path_label(explorer) (pointer to
Current Path Label
Label (lv_label) Widget)lv_file_explorer_get_quick_access_area(explorer) (pointer to
Quick-Access Panel
Base Widget)lv_file_explorer_get_places_list(explorer) (pointer to
Places List
List (lv_list) Widget)lv_file_explorer_get_device_list(explorer) (pointer to
Device List
List (lv_list) Widget)
Quick-Access Panel
The Quick-Access Panel
behaves like a typical navigation panel and appears on the
left, while the Browser Panel
appears on the right
This panel is optional. If you set LV_FILE_EXPLORER_QUICK_ACCESS
to 0
in lv_conf.h
, the Quick-Access Panel
will not be created. This saves only a
little bit of memory.
Soon after the File Explorer is created, you typically use
lv_file_explorer_set_quick_access_path(explorer, LV_EXPLORER_XXX_DIR, "path")
to set the path that will be navigated to when the buttons in the Quick-Access Panel
are clicked, which is currently a fixed list. The corresponding values you will need
to pass as the 2nd argument are the following:
Sort
You can use lv_file_explorer_set_sort(explorer, LV_EXPLORER_SORT_XX) to set the sorting method.
These are the possible sorting methods:
LV_EXPLORER_SORT_NONE
(default)
lv_file_explorer_get_sort(explorer) returns the current sorting method.
Events
LV_EVENT_READY
Sent when a directory is opened, which can happen:when the File Explorer is initially opened,
after a user clicks on a
Quick-Access Panel
navigation button, andafter the user clicks on a directory displayed in the
Browser Panel
.
You can use it to, for example, customize the file sort.
LV_EVENT_VALUE_CHANGED
Sent once when any item (file) in theBrwoser Panel
's file list is clicked.LV_EVENT_CLICKED
Sent twice when an item in theBrowser Panel
is clicked: once as a result of the input-deviceLV_EVENT_RELEASED
event and a second as a result of the input deviceLV_EVENT_CLICKED
event. This applies to files, directories, and the "< Back" item in theBrowser Panel
.
In these events you can use lv_file_explorer_get_current_path()
to get the
current path and lv_file_explorer_get_selected_file_name()
to get the name
of the currently selected file in the event processing function. For example:
static void file_explorer_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
char * cur_path = lv_file_explorer_get_current_path(widget);
char * sel_fn = lv_file_explorer_get_selected_file_name(widget);
LV_LOG_USER("%s%s", cur_path, sel_fn);
}
}
You can also save the obtained path and file name into an array
through functions such as strcpy()
and strcat()
for later use.
Example
Simple File Explorer
C code
View on GitHub
#include "../../lv_examples.h"
#if LV_USE_TABLE && LV_USE_FILE_EXPLORER && (LV_USE_FS_STDIO || LV_USE_FS_POSIX || LV_USE_FS_WIN32 || LV_USE_FS_FATFS) && LV_BUILD_EXAMPLES
#include <stdlib.h>
#include <string.h>
static void file_explorer_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
const char * cur_path = lv_file_explorer_get_current_path(obj);
const char * sel_fn = lv_file_explorer_get_selected_file_name(obj);
LV_LOG_USER("%s%s", cur_path, sel_fn);
}
}
void lv_example_file_explorer_1(void)
{
lv_obj_t * file_explorer = lv_file_explorer_create(lv_screen_active());
lv_file_explorer_set_sort(file_explorer, LV_EXPLORER_SORT_KIND);
#if LV_USE_FS_WIN32
/* Note to Windows users: the initial "C:" on these paths corresponds to
* the value of `LV_FS_WIN32_LETTER` in `lv_conf.h`, and should not be
* confused with the Windows/DOS drive letter. It is an identifier that
* is used to enable LVGL to look up the appropriate driver from a list of
* registered file-system drivers. `lv_fs_win32_init()` happens to use the
* identifier letter 'C' so "C:" is the driver-identifier-prefix used here.
* The "C:" following that is indeed the Windows/DOS drive letter and is
* part of the actual path that gets passed to the OS-level functions.
*
* See https://docs.lvgl.io/master/details/main-components/fs.html for details.
* File Explorer uses `lv_fs` internally, thus the required prefix in path strings.
*/
lv_file_explorer_open_dir(file_explorer, "C:C:/");
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, "C:C:/Users/Public/Desktop");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, "C:C:/Users/Public/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, "C:C:/Users/Public/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, "C:C:/Users/Public/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, "C:C:/Users/Public/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "C:C:/");
#endif
#else
/* linux */
lv_file_explorer_open_dir(file_explorer, "A:/");
#if LV_FILE_EXPLORER_QUICK_ACCESS
char * envvar = "HOME";
char home_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(home_dir, "A:");
/* get the user's home directory from the HOME environment variable*/
strcat(home_dir, getenv(envvar));
LV_LOG_USER("home_dir: %s\n", home_dir);
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, home_dir);
char video_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(video_dir, home_dir);
strcat(video_dir, "/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, video_dir);
char picture_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(picture_dir, home_dir);
strcat(picture_dir, "/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, picture_dir);
char music_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(music_dir, home_dir);
strcat(music_dir, "/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, music_dir);
char document_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(document_dir, home_dir);
strcat(document_dir, "/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, document_dir);
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "A:/");
#endif
#endif
lv_obj_add_event_cb(file_explorer, file_explorer_event_handler, LV_EVENT_ALL, NULL);
}
#endif
Control File Explorer
C code
View on GitHub
#include "../../lv_examples.h"
#if LV_USE_TABLE && LV_USE_DROPDOWN && LV_USE_FILE_EXPLORER && (LV_USE_FS_STDIO || LV_USE_FS_POSIX || LV_USE_FS_WIN32 || LV_USE_FS_FATFS) && LV_BUILD_EXAMPLES
#include <stdlib.h>
#include <string.h>
static void file_explorer_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
const char * cur_path = lv_file_explorer_get_current_path(obj);
const char * sel_fn = lv_file_explorer_get_selected_file_name(obj);
LV_LOG_USER("%s%s", cur_path, sel_fn);
}
}
#if LV_FILE_EXPLORER_QUICK_ACCESS
static void btn_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * btn = lv_event_get_target(e);
lv_obj_t * file_explorer = lv_event_get_user_data(e);
if(code == LV_EVENT_VALUE_CHANGED) {
if(lv_obj_has_state(btn, LV_STATE_CHECKED))
lv_obj_add_flag(file_explorer, LV_OBJ_FLAG_HIDDEN);
else
lv_obj_remove_flag(file_explorer, LV_OBJ_FLAG_HIDDEN);
}
}
static void dd_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * dd = lv_event_get_target(e);
lv_obj_t * fe_quick_access_obj = lv_event_get_user_data(e);
if(code == LV_EVENT_VALUE_CHANGED) {
char buf[32];
lv_dropdown_get_selected_str(dd, buf, sizeof(buf));
if(strcmp(buf, "NONE") == 0) {
lv_file_explorer_set_sort(fe_quick_access_obj, LV_EXPLORER_SORT_NONE);
}
else if(strcmp(buf, "KIND") == 0) {
lv_file_explorer_set_sort(fe_quick_access_obj, LV_EXPLORER_SORT_KIND);
}
}
}
#endif
void lv_example_file_explorer_2(void)
{
lv_obj_t * file_explorer = lv_file_explorer_create(lv_screen_active());
#if LV_USE_FS_WIN32
/* Note to Windows users: the initial "C:" on these paths corresponds to
* the value of `LV_FS_WIN32_LETTER` in `lv_conf.h`, and should not be
* confused with the Windows/DOS drive letter. It is an identifier that
* is used to enable LVGL to look up the appropriate driver from a list of
* registered file-system drivers. `lv_fs_win32_init()` happens to use the
* identifier letter 'C' so "C:" is the driver-identifier-prefix used here.
* The "C:" following that is indeed the Windows/DOS drive letter and is
* part of the actual path that gets passed to the OS-level functions.
*
* See https://docs.lvgl.io/master/details/main-components/fs.html for details.
* File Explorer uses `lv_fs` internally, thus the required prefix in path strings.
*/
lv_file_explorer_open_dir(file_explorer, "C:C:/");
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, "C:C:/Users/Public/Desktop");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, "C:C:/Users/Public/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, "C:C:/Users/Public/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, "C:C:/Users/Public/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, "C:C:/Users/Public/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "C:C:/");
#endif
#else
/* linux */
lv_file_explorer_open_dir(file_explorer, "A:/");
#if LV_FILE_EXPLORER_QUICK_ACCESS
char * envvar = "HOME";
char home_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(home_dir, "A:");
/* get the user's home directory from the HOME environment variable*/
strcat(home_dir, getenv(envvar));
LV_LOG_USER("home_dir: %s\n", home_dir);
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, home_dir);
char video_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(video_dir, home_dir);
strcat(video_dir, "/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, video_dir);
char picture_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(picture_dir, home_dir);
strcat(picture_dir, "/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, picture_dir);
char music_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(music_dir, home_dir);
strcat(music_dir, "/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, music_dir);
char document_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(document_dir, home_dir);
strcat(document_dir, "/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, document_dir);
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "A:/");
#endif
#endif
lv_obj_add_event_cb(file_explorer, file_explorer_event_handler, LV_EVENT_ALL, NULL);
#if LV_FILE_EXPLORER_QUICK_ACCESS
/*Quick access status control button*/
lv_obj_t * fe_quick_access_obj = lv_file_explorer_get_quick_access_area(file_explorer);
lv_obj_t * fe_header_obj = lv_file_explorer_get_header(file_explorer);
lv_obj_t * btn = lv_button_create(fe_header_obj);
lv_obj_set_style_radius(btn, 2, 0);
lv_obj_set_style_pad_all(btn, 4, 0);
lv_obj_align(btn, LV_ALIGN_LEFT_MID, 0, 0);
lv_obj_add_flag(btn, LV_OBJ_FLAG_CHECKABLE);
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text(label, LV_SYMBOL_LIST);
lv_obj_center(label);
lv_obj_add_event_cb(btn, btn_event_handler, LV_EVENT_VALUE_CHANGED, fe_quick_access_obj);
/*Sort control*/
static const char * opts = "NONE\n"
"KIND";
lv_obj_t * dd = lv_dropdown_create(fe_header_obj);
lv_obj_set_style_radius(dd, 4, 0);
lv_obj_set_style_pad_all(dd, 0, 0);
lv_obj_set_size(dd, LV_PCT(30), LV_SIZE_CONTENT);
lv_dropdown_set_options_static(dd, opts);
lv_obj_align(dd, LV_ALIGN_RIGHT_MID, 0, 0);
lv_obj_add_event_cb(dd, dd_event_handler, LV_EVENT_VALUE_CHANGED, file_explorer);
#endif
}
#endif
Custom sort
C code
View on GitHub
#include "../../lv_examples.h"
#if LV_USE_TABLE && LV_USE_FILE_EXPLORER && (LV_USE_FS_STDIO || LV_USE_FS_POSIX || LV_USE_FS_WIN32 || LV_USE_FS_FATFS) && LV_BUILD_EXAMPLES
#include <stdlib.h>
#include <string.h>
static void exch_table_item(lv_obj_t * tb, int16_t i, int16_t j)
{
const char * tmp;
tmp = lv_table_get_cell_value(tb, i, 0);
lv_table_set_cell_value(tb, 0, 2, tmp);
lv_table_set_cell_value(tb, i, 0, lv_table_get_cell_value(tb, j, 0));
lv_table_set_cell_value(tb, j, 0, lv_table_get_cell_value(tb, 0, 2));
tmp = lv_table_get_cell_value(tb, i, 1);
lv_table_set_cell_value(tb, 0, 2, tmp);
lv_table_set_cell_value(tb, i, 1, lv_table_get_cell_value(tb, j, 1));
lv_table_set_cell_value(tb, j, 1, lv_table_get_cell_value(tb, 0, 2));
}
/*Quick sort 3 way*/
static void sort_by_file_kind(lv_obj_t * tb, int16_t lo, int16_t hi)
{
if(lo >= hi) return;
int16_t lt = lo;
int16_t i = lo + 1;
int16_t gt = hi;
const char * v = lv_table_get_cell_value(tb, lo, 1);
while(i <= gt) {
if(strcmp(lv_table_get_cell_value(tb, i, 1), v) < 0)
exch_table_item(tb, lt++, i++);
else if(strcmp(lv_table_get_cell_value(tb, i, 1), v) > 0)
exch_table_item(tb, i, gt--);
else
i++;
}
sort_by_file_kind(tb, lo, lt - 1);
sort_by_file_kind(tb, gt + 1, hi);
}
static void file_explorer_event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
const char * cur_path = lv_file_explorer_get_current_path(obj);
const char * sel_fn = lv_file_explorer_get_selected_file_name(obj);
LV_LOG_USER("%s%s", cur_path, sel_fn);
}
else if(code == LV_EVENT_READY) {
lv_obj_t * tb = lv_file_explorer_get_file_table(obj);
uint16_t sum = lv_table_get_row_count(tb);
sort_by_file_kind(tb, 0, (sum - 1));
}
}
void lv_example_file_explorer_3(void)
{
lv_obj_t * file_explorer = lv_file_explorer_create(lv_screen_active());
/*Before custom sort, please set the default sorting to NONE. The default is NONE.*/
lv_file_explorer_set_sort(file_explorer, LV_EXPLORER_SORT_NONE);
#if LV_USE_FS_WIN32
/* Note to Windows users: the initial "C:" on these paths corresponds to
* the value of `LV_FS_WIN32_LETTER` in `lv_conf.h`, and should not be
* confused with the Windows/DOS drive letter. It is an identifier that
* is used to enable LVGL to look up the appropriate driver from a list of
* registered file-system drivers. `lv_fs_win32_init()` happens to use the
* identifier letter 'C' so "C:" is the driver-identifier-prefix used here.
* The "C:" following that is indeed the Windows/DOS drive letter and is
* part of the actual path that gets passed to the OS-level functions.
*
* See https://docs.lvgl.io/master/details/main-components/fs.html for details.
* File Explorer uses `lv_fs` internally, thus the required prefix in path strings.
*/
lv_file_explorer_open_dir(file_explorer, "C:C:/");
#if LV_FILE_EXPLORER_QUICK_ACCESS
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, "C:C:/Users/Public/Desktop");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, "C:C:/Users/Public/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, "C:C:/Users/Public/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, "C:C:/Users/Public/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, "C:C:/Users/Public/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "C:C:/");
#endif
#else
/* linux */
lv_file_explorer_open_dir(file_explorer, "A:/");
#if LV_FILE_EXPLORER_QUICK_ACCESS
char * envvar = "HOME";
char home_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(home_dir, "A:");
/* get the user's home directory from the HOME environment variable*/
strcat(home_dir, getenv(envvar));
LV_LOG_USER("home_dir: %s\n", home_dir);
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, home_dir);
char video_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(video_dir, home_dir);
strcat(video_dir, "/Videos");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, video_dir);
char picture_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(picture_dir, home_dir);
strcat(picture_dir, "/Pictures");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, picture_dir);
char music_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(music_dir, home_dir);
strcat(music_dir, "/Music");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, music_dir);
char document_dir[LV_FS_MAX_PATH_LENGTH];
strcpy(document_dir, home_dir);
strcat(document_dir, "/Documents");
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, document_dir);
lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "A:/");
#endif
#endif
lv_obj_add_event_cb(file_explorer, file_explorer_event_handler, LV_EVENT_ALL, NULL);
}
#endif