Fragment(片段)

Fragment 是从 Android 借鉴的一个概念。

它表示应用程序 UI 的一个可重用部分。Fragment 定义并管理其自己的布局,具有自己的生命周期,并可以处理自己的事件。与 Android 的 Fragment 必须由活动或另一个 Fragment 托管类似,LVGL 中的 Fragment 需要由一个对象或另一个 Fragment 托管。Fragment 的视图层次结构成为或附加到宿主的视图层次结构的一部分。

这一概念与 iOS 上的 UiViewController 也有一些相似之处。

Fragment Manager 是一个管理器,用于保存附加到它的 Fragment 的引用,并具有一个内部堆栈以实现导航。您可以使用 Fragment Manager 轻松构建导航堆栈或多窗格应用程序。

使用方法

lv_conf.h 中启用 LV_USE_FRAGMENT

创建 Fragment 类

struct sample_fragment_t {
    /* 重要:不要遗漏这一部分 */
    lv_fragment_t base;
    /* 此 Fragment 的状态、对象引用和数据字段 */
    const char *title;
};

const lv_fragment_class_t sample_cls = {
        /* 初始化所需内容 */
        .constructor_cb = sample_fragment_ctor,
        /* 创建视图对象 */
        .create_obj_cb = sample_fragment_create_obj,
        /* 重要:您的 Fragment 结构体的大小 */
        .instance_size = sizeof(struct sample_fragment_t)
};

使用 lv_fragment_manager

/* 创建 Fragment 实例,对象将被添加到容器中 */
lv_fragment_manager_t *manager = lv_fragment_manager_create(container, NULL);
/* 用 sample_cls 的实例替换当前 Fragment,init_argument 是用户定义的指针 */
lv_fragment_manager_replace(manager, &sample_cls, init_argument);

基于 Fragment 的导航

/* 将一个实例添加到管理器堆栈中。当前 Fragment 的视图对象将被销毁,
 * 但在类构造函数中创建的实例将被保留。
 */
lv_fragment_manager_push(manager, &sample_cls, NULL);

/* 从堆栈中移除最顶部的 Fragment,并恢复前一个 Fragment。 */
lv_fragment_manager_pop(manager);

示例

基本片段用法

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 D:\lv_port_pc_eclipse-release-v8.3\lvgl\examples\others\fragment\lv_example_fragment_1.py

堆栈导航示例

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 D:\lv_port_pc_eclipse-release-v8.3\lvgl\examples\others\fragment\lv_example_fragment_2.py

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

Parameters
  • self -- Fragment instance

  • args -- Arguments assigned by fragment manager

void (*destructor_cb)(lv_fragment_t *self)

Destructor function for fragment class

Parameters

self -- Fragment instance, will be freed after this call

void (*attached_cb)(lv_fragment_t *self)

Fragment attached to manager

Parameters

self -- Fragment instance

void (*detached_cb)(lv_fragment_t *self)

Fragment detached from manager

Parameters

self -- Fragment instance

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

Create objects

Parameters
  • self -- Fragment instance

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

Returns

Created object, NULL if multiple objects has been created

void (*obj_created_cb)(lv_fragment_t *self, lv_obj_t *obj)
Parameters
  • self -- Fragment instance

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

Parameters
  • self -- Fragment instance

  • 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

Parameters
  • self -- Fragment instance

  • obj -- object with this fragment

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

Handle event

Parameters
  • self -- Fragment instance

  • which -- User-defined ID of event

  • data1 -- User-defined data

  • 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