Fragment

Fragment is a concept copied from Android.

It represents a reusable portion of your app's UI. A fragment defines and manages its own layout, has its own lifecycle, and can handle its own events. Like Android's Fragment that must be hosted by an activity or another fragment, Fragment in LVGL needs to be hosted by an object, or another fragment. The fragment’s view hierarchy becomes part of, or attaches to, the host’s view hierarchy.

Such concept also has some similarities to UiViewController on iOS.

Fragment Manager is a manager holding references to fragments attached to it, and has an internal stack to achieve navigation. You can use fragment manager to build navigation stack, or multi pane application easily.

Usage

Enable LV_USE_FRAGMENT in lv_conf.h.

Create Fragment Class

struct sample_fragment_t {
    /* IMPORTANT: don't miss this part */
    lv_fragment_t base;
    /* States, object references and data fields for this fragment */
    const char *title;
};

const lv_fragment_class_t sample_cls = {
        /* Initialize something needed */
        .constructor_cb = sample_fragment_ctor,
        /* Create view objects */
        .create_obj_cb = sample_fragment_create_obj,
        /* IMPORTANT: size of your fragment struct */
        .instance_size = sizeof(struct sample_fragment_t)
};

Use lv_fragment_manager

/* Create fragment instance, and objects will be added to container */
lv_fragment_manager_t *manager = lv_fragment_manager_create(container, NULL);
/* Replace current fragment with instance of sample_cls, and init_argument is user defined pointer */
lv_fragment_manager_replace(manager, &sample_cls, init_argument);

Fragment Based Navigation

/* Add one instance into manager stack. View object of current fragment will be destroyed,
 * but instances created in class constructor will be kept.
 */
lv_fragment_manager_push(manager, &sample_cls, NULL);

/* Remove the top most fragment from the stack, and bring back previous one. */
lv_fragment_manager_pop(manager);

Example

Basic fragment usage

C code  

 GitHub
/**
 * @file lv_example_fragment_1.c
 * @brief Basic usage of obj fragment
 */
#include "../../lv_examples.h"

#if LV_USE_FRAGMENT && LV_BUILD_EXAMPLES

static void sample_fragment_ctor(lv_fragment_t * self, void * args);

static lv_obj_t * sample_fragment_create_obj(lv_fragment_t * self, lv_obj_t * parent);

static void sample_container_del(lv_event_t * e);

static lv_obj_t * root = NULL;

struct sample_fragment_t {
    lv_fragment_t base;
    const char * name;
};

static const lv_fragment_class_t sample_cls = {
    .constructor_cb = sample_fragment_ctor,
    .create_obj_cb = sample_fragment_create_obj,
    .instance_size = sizeof(struct sample_fragment_t)
};

void lv_example_fragment_1(void)
{
    root = lv_obj_create(lv_scr_act());
    lv_obj_set_size(root, LV_PCT(100), LV_PCT(100));
    lv_fragment_manager_t * manager = lv_fragment_manager_create(NULL);
    /* Clean up the fragment manager before objects in containers got deleted */
    lv_obj_add_event_cb(root, sample_container_del, LV_EVENT_DELETE, manager);

    lv_fragment_t * fragment = lv_fragment_create(&sample_cls, "Fragment");
    lv_fragment_manager_replace(manager, fragment, &root);
}

static void sample_fragment_ctor(lv_fragment_t * self, void * args)
{
    ((struct sample_fragment_t *) self)->name = args;
}

static lv_obj_t * sample_fragment_create_obj(lv_fragment_t * self, lv_obj_t * parent)
{
    lv_obj_t * label = lv_label_create(parent);
    lv_obj_set_style_bg_opa(label, LV_OPA_COVER, 0);;
    lv_label_set_text_fmt(label, "Hello, %s!", ((struct sample_fragment_t *) self)->name);
    return label;
}

static void sample_container_del(lv_event_t * e)
{
    lv_fragment_manager_t * manager = (lv_fragment_manager_t *) lv_event_get_user_data(e);
    lv_fragment_manager_del(manager);
}

#endif

MicroPython code  

 GitHub Simulator
Error encountered while trying to open /home/runner/work/lvgl/lvgl/examples/others/fragment/lv_example_fragment_1.py

Stack navigation example

C code  

 GitHub
/**
 * @file lv_example_fragment_2.c
 * @brief Navigation stack using obj fragment
 */
#include "../../lv_examples.h"

#if LV_USE_FRAGMENT && LV_USE_WIN && LV_BUILD_EXAMPLES

static void sample_fragment_ctor(lv_fragment_t * self, void * args);

static lv_obj_t * sample_fragment_create_obj(lv_fragment_t * self, lv_obj_t * parent);

static void sample_push_click(lv_event_t * e);

static void sample_pop_click(lv_event_t * e);

static void sample_container_del(lv_event_t * e);

static void sample_fragment_inc_click(lv_event_t * e);

typedef struct sample_fragment_t {
    lv_fragment_t base;
    lv_obj_t * label;
    int depth;
    int counter;
} sample_fragment_t;

static const lv_fragment_class_t sample_cls = {
    .constructor_cb = sample_fragment_ctor,
    .create_obj_cb = sample_fragment_create_obj,
    .instance_size = sizeof(sample_fragment_t)
};

static lv_obj_t * container = NULL;

void lv_example_fragment_2(void)
{
    lv_obj_t * root = lv_obj_create(lv_scr_act());
    lv_obj_set_size(root, LV_PCT(100), LV_PCT(100));
    lv_obj_set_layout(root, LV_LAYOUT_GRID);
    static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
    static const lv_coord_t row_dsc[] = {LV_GRID_FR(1), LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
    lv_obj_set_grid_dsc_array(root, col_dsc, row_dsc);
    container = lv_obj_create(root);
    lv_obj_remove_style_all(container);
    lv_obj_set_grid_cell(container, LV_GRID_ALIGN_STRETCH, 0, 2, LV_GRID_ALIGN_STRETCH, 0, 1);

    lv_obj_t * push_btn = lv_btn_create(root);
    lv_obj_t * push_label = lv_label_create(push_btn);
    lv_label_set_text(push_label, "Push");

    lv_obj_t * pop_btn = lv_btn_create(root);
    lv_obj_t * pop_label = lv_label_create(pop_btn);
    lv_label_set_text(pop_label, "Pop");
    lv_obj_set_grid_cell(push_btn, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_CENTER, 1, 1);
    lv_obj_set_grid_cell(pop_btn, LV_GRID_ALIGN_END, 1, 1, LV_GRID_ALIGN_CENTER, 1, 1);

    lv_fragment_manager_t * manager = lv_fragment_manager_create(NULL);
    /* Clean up the fragment manager before objects in containers got deleted */
    lv_obj_add_event_cb(root, sample_container_del, LV_EVENT_DELETE, manager);

    int depth = 0;
    lv_fragment_t * fragment = lv_fragment_create(&sample_cls, &depth);
    lv_fragment_manager_push(manager, fragment, &container);
    lv_obj_add_event_cb(push_btn, sample_push_click, LV_EVENT_CLICKED, manager);
    lv_obj_add_event_cb(pop_btn, sample_pop_click, LV_EVENT_CLICKED, manager);
}

static void sample_fragment_ctor(lv_fragment_t * self, void * args)
{
    LV_UNUSED(args);
    ((sample_fragment_t *) self)->depth = *((int *) args);
    ((sample_fragment_t *) self)->counter = 0;
}

static lv_obj_t * sample_fragment_create_obj(lv_fragment_t * self, lv_obj_t * parent)
{
    sample_fragment_t * fragment = (sample_fragment_t *) self;
    lv_obj_t * content = lv_obj_create(parent);
    lv_obj_remove_style_all(content);
    lv_obj_set_style_bg_opa(content, LV_OPA_50, 0);
    lv_obj_set_style_bg_color(content, lv_palette_main(LV_PALETTE_YELLOW), 0);
    lv_obj_set_size(content, LV_PCT(100), LV_PCT(100));
    lv_obj_set_flex_flow(content, LV_FLEX_FLOW_COLUMN);
    lv_obj_t * depth = lv_label_create(content);
    lv_label_set_text_fmt(depth, "Depth: %d", fragment->depth);
    lv_obj_t * label = lv_label_create(content);
    fragment->label = label;
    lv_label_set_text_fmt(label, "The button has been pressed %d times", fragment->counter);

    lv_obj_t * inc_btn = lv_btn_create(content);
    lv_obj_t * inc_label = lv_label_create(inc_btn);
    lv_label_set_text(inc_label, "+1");
    lv_obj_add_event_cb(inc_btn, sample_fragment_inc_click, LV_EVENT_CLICKED, fragment);

    return content;
}

static void sample_push_click(lv_event_t * e)
{
    lv_fragment_manager_t * manager = (lv_fragment_manager_t *) lv_event_get_user_data(e);
    size_t stack_size = lv_fragment_manager_get_stack_size(manager);
    lv_fragment_t * fragment = lv_fragment_create(&sample_cls, &stack_size);
    lv_fragment_manager_push(manager, fragment, &container);
}

static void sample_pop_click(lv_event_t * e)
{
    lv_fragment_manager_t * manager = (lv_fragment_manager_t *) lv_event_get_user_data(e);
    lv_fragment_manager_pop(manager);
}

static void sample_container_del(lv_event_t * e)
{
    lv_fragment_manager_t * manager = (lv_fragment_manager_t *) lv_event_get_user_data(e);
    lv_fragment_manager_del(manager);
}

static void sample_fragment_inc_click(lv_event_t * e)
{
    sample_fragment_t * fragment = (sample_fragment_t *) lv_event_get_user_data(e);
    fragment->counter++;
    lv_label_set_text_fmt(fragment->label, "The button has been pressed %d times", fragment->counter);
}

#endif

MicroPython code  

 GitHub Simulator
Error encountered while trying to open /home/runner/work/lvgl/lvgl/examples/others/fragment/lv_example_fragment_2.py

language

c

API

Public header for Fragment

Typedefs

typedef struct _lv_fragment_manager_t lv_fragment_manager_t
typedef struct _lv_fragment_t lv_fragment_t
typedef struct _lv_fragment_class_t lv_fragment_class_t
typedef struct _lv_fragment_managed_states_t lv_fragment_managed_states_t

Fragment states

Functions

lv_fragment_manager_t *lv_fragment_manager_create(lv_fragment_t *parent)

Create fragment manager instance

Parameters

parent -- Parent fragment if this manager is placed inside another fragment, can be null.

Returns

Fragment manager instance

void lv_fragment_manager_del(lv_fragment_manager_t *manager)

Destroy fragment manager instance

Parameters

manager -- Fragment manager instance

void lv_fragment_manager_create_obj(lv_fragment_manager_t *manager)

Create object of all fragments managed by this manager.

Parameters

manager -- Fragment manager instance

void lv_fragment_manager_del_obj(lv_fragment_manager_t *manager)

Delete object created by all fragments managed by this manager. Instance of fragments will not be deleted.

Parameters

manager -- Fragment manager instance

void lv_fragment_manager_add(lv_fragment_manager_t *manager, lv_fragment_t *fragment, lv_obj_t *const *container)

Attach fragment to manager, and add to container.

Parameters
  • manager -- Fragment manager instance

  • fragment -- Fragment instance

  • container -- Pointer to container object for manager to add objects to

void lv_fragment_manager_remove(lv_fragment_manager_t *manager, lv_fragment_t *fragment)

Detach and destroy fragment. If fragment is in navigation stack, remove from it.

Parameters
  • manager -- Fragment manager instance

  • fragment -- Fragment instance

void lv_fragment_manager_push(lv_fragment_manager_t *manager, lv_fragment_t *fragment, lv_obj_t *const *container)

Attach fragment to manager and add to navigation stack.

Parameters
  • manager -- Fragment manager instance

  • fragment -- Fragment instance

  • container -- Pointer to container object for manager to add objects to

bool lv_fragment_manager_pop(lv_fragment_manager_t *manager)

Remove the top-most fragment for stack

Parameters

manager -- Fragment manager instance

Returns

true if there is fragment to pop

void lv_fragment_manager_replace(lv_fragment_manager_t *manager, lv_fragment_t *fragment, lv_obj_t *const *container)

Replace fragment. Old item in the stack will be removed.

Parameters
  • manager -- Fragment manager instance

  • fragment -- Fragment instance

  • container -- Pointer to container object for manager to add objects to

bool lv_fragment_manager_send_event(lv_fragment_manager_t *manager, int code, void *userdata)

Send event to top-most fragment

Parameters
  • manager -- Fragment manager instance

  • code -- User-defined ID of event

  • userdata -- User-defined data

Returns

true if fragment returned true

size_t lv_fragment_manager_get_stack_size(lv_fragment_manager_t *manager)

Get stack size of this fragment manager

Parameters

manager -- Fragment manager instance

Returns

Stack size of this fragment manager

lv_fragment_t *lv_fragment_manager_get_top(lv_fragment_manager_t *manager)

Get top most fragment instance

Parameters

manager -- Fragment manager instance

Returns

Top most fragment instance

lv_fragment_t *lv_fragment_manager_find_by_container(lv_fragment_manager_t *manager, const lv_obj_t *container)

Find first fragment instance in the container

Parameters
  • manager -- Fragment manager instance

  • container -- Container which target fragment added to

Returns

First fragment instance in the container

lv_fragment_t *lv_fragment_manager_get_parent_fragment(lv_fragment_manager_t *manager)

Get parent fragment

Parameters

manager -- Fragment manager instance

Returns

Parent fragment instance

lv_fragment_t *lv_fragment_create(const lv_fragment_class_t *cls, void *args)

Create a fragment instance.

Parameters
  • cls -- Fragment class. This fragment must return non null object.

  • args -- Arguments assigned by fragment manager

Returns

Fragment instance

void lv_fragment_del(lv_fragment_t *fragment)

Destroy a fragment.

Parameters

fragment -- Fragment instance.

lv_fragment_manager_t *lv_fragment_get_manager(lv_fragment_t *fragment)

Get associated manager of this fragment

Parameters

fragment -- Fragment instance

Returns

Fragment manager instance

lv_obj_t *const *lv_fragment_get_container(lv_fragment_t *fragment)

Get container object of this fragment

Parameters

fragment -- Fragment instance

Returns

Reference to container object

lv_fragment_t *lv_fragment_get_parent(lv_fragment_t *fragment)

Get parent fragment of this fragment

Parameters

fragment -- Fragment instance

Returns

Parent fragment

lv_obj_t *lv_fragment_create_obj(lv_fragment_t *fragment, lv_obj_t *container)

Create object by fragment.

Parameters
  • fragment -- Fragment instance.

  • container -- Container of the objects should be created upon.

Returns

Created object

void lv_fragment_del_obj(lv_fragment_t *fragment)

Delete created object of a fragment

Parameters

fragment -- Fragment instance.

void lv_fragment_recreate_obj(lv_fragment_t *fragment)

Destroy obj in fragment, and recreate them.

Parameters

fragment -- Fragment instance

struct _lv_fragment_t

Public Members

const lv_fragment_class_t *cls

Class of this fragment

lv_fragment_managed_states_t *managed

Managed fragment states. If not null, then this fragment is managed.

Warning

Don't modify values inside this struct!

lv_fragment_manager_t *child_manager

Child fragment manager

lv_obj_t *obj

lv_obj returned by create_obj_cb

struct _lv_fragment_class_t

Public Members

void (*constructor_cb)(lv_fragment_t *self, void *args)

Constructor function for fragment class

Param self

Fragment instance

Param args

Arguments assigned by fragment manager

void (*destructor_cb)(lv_fragment_t *self)

Destructor function for fragment class

Param self

Fragment instance, will be freed after this call

void (*attached_cb)(lv_fragment_t *self)

Fragment attached to manager

Param self

Fragment instance

void (*detached_cb)(lv_fragment_t *self)

Fragment detached from manager

Param self

Fragment instance

lv_obj_t *(*create_obj_cb)(lv_fragment_t *self, lv_obj_t *container)

Create objects

Param self

Fragment instance

Param container

Container of the objects should be created upon

Return

Created object, NULL if multiple objects has been created

void (*obj_created_cb)(lv_fragment_t *self, lv_obj_t *obj)
Param self

Fragment instance

Param obj

lv_obj returned by create_obj_cb

void (*obj_will_delete_cb)(lv_fragment_t *self, lv_obj_t *obj)

Called before objects in the fragment will be deleted.

Param self

Fragment instance

Param obj

object with this fragment

void (*obj_deleted_cb)(lv_fragment_t *self, lv_obj_t *obj)

Called when the object created by fragment received LV_EVENT_DELETE event

Param self

Fragment instance

Param obj

object with this fragment

bool (*event_cb)(lv_fragment_t *self, int code, void *userdata)

Handle event

Param self

Fragment instance

Param which

User-defined ID of event

Param data1

User-defined data

Param data2

User-defined data

size_t instance_size

REQUIRED: Allocation size of fragment

struct _lv_fragment_managed_states_t
#include <lv_fragment.h>

Fragment states

Public Members

const lv_fragment_class_t *cls

Class of the fragment

lv_fragment_manager_t *manager

Manager the fragment attached to

lv_obj_t *const *container

Container object the fragment adding view to

lv_fragment_t *instance

Fragment instance

bool obj_created

true between create_obj_cb and obj_deleted_cb

bool destroying_obj

true before lv_fragment_del_obj is called. Don't touch any object if this is true

bool in_stack

true if this fragment is in navigation stack that can be popped