Skip to main content

Activity and View

Activity is the core component for managing pages and user interfaces in ElenixOS. Each Activity represents an independent screen page (such as application page, watchface page), containing an associated View and complete lifecycle management.

Activity Overview

Activity is the core abstraction for page navigation and lifecycle management in ElenixOS. Each Activity contains:

  • An associated View (LVGL object tree), which is the UI content of the page
  • Complete lifecycle callbacks (enter, destroy, pause, resume)
  • UI properties such as title and title color
  • Type identifier (application, watchface, application list, etc.)
  • AppHeader visibility control

Activity Types

typedef enum {
EOS_ACTIVITY_TYPE_NULL = 0, // Null type
EOS_ACTIVITY_TYPE_APP, // Application page
EOS_ACTIVITY_TYPE_APP_LIST, // Application list
EOS_ACTIVITY_TYPE_WATCHFACE, // Watchface page
EOS_ACTIVITY_TYPE_WATCHFACE_LIST, // Watchface list
EOS_ACTIVITY_TYPE_COUNT
} eos_activity_type_t;

Lifecycle

Activity has a complete lifecycle managed by the following callback functions:

typedef struct {
eos_activity_on_enter_t on_enter; // Called when entering
eos_activity_on_destroy_t on_destroy; // Called when destroying
eos_activity_on_pause_t on_pause; // Called when pausing
eos_activity_on_resume_t on_resume; // Called when resuming
} eos_activity_lifecycle_t;

Lifecycle Flow

Create Activity (eos_activity_create)


Enter Activity (eos_activity_enter)

├── on_enter() ── Enter callback


Activity visible (visible)

├── on_resume() ── Resume callback (when returning from other Activity)


Leave Activity

├── on_pause() ── Pause callback (when switching to other Activity)


Return Activity ──► on_resume()


Destroy Activity (eos_activity_back)

└── on_destroy() ── Destroy callback

Lifecycle Callback Description

CallbackTrigger ConditionTypical Use Case
on_enterWhen Activity first displaysInitialize UI, load data
on_resumeWhen returning from other ActivityRefresh data, resume animations
on_pauseWhen switching to other ActivitySave state, pause animations
on_destroyWhen Activity is destroyedRelease resources, unsubscribe

Activity Stack Management

ElenixOS uses a stack structure to manage Activities. The watchface (Watchface) Activity is fixed at the bottom of the stack, and newly opened Activities are pushed to the top of the stack.

Root Activity Mechanism

Important Concept: The watchface serves as the Root Activity, managed independently of the Activity stack and has a special status:

Root Activity Characteristics:

FeatureNormal ActivityRoot Activity
LocationIn stackIndependent of stack
LifecycleCreated/destroyed with push/popPersists until switched
Creationeos_activity_create()eos_activity_create_root()
View CreationLazy creation (in on_enter)Immediate creation (at create_root)
Pop EffectDestroyed and releasedNot affected by pop
Switch MethodN/Aeos_activity_replace_root()

Root Activity Use Cases:

  • Watchfaces (built-in or JS)
  • Serves as the system's "home page", always present
  • Switched via replace_root() instead of push/pop

Stack Structure Diagram

Top of Stack
┌──────────────────┐
│ Activity C │ ← Currently visible Activity
├──────────────────┤
│ Activity B │ ← Paused state
├──────────────────┤
│ Activity A │ ← Paused state
└──────────────────┘

│ (Independent of stack)

┌─────────────┐
│ Watchface │ ← Root Activity (Always present)
└─────────────┘

Enter New Activity

eos_activity_enter(activity);

Pushes the Activity onto the stack and displays it. The previous Activity automatically enters the paused state.

Return to Previous Activity

eos_result_t ret = eos_activity_back();

Destroys the current top Activity and resumes the previous one. Returns EOS_OK on success.

Return to Watchface

eos_result_t ret = eos_activity_back_to_watchface();

Destroys all Activities in the stack and returns directly to the watchface.

Return in Event Callback

void eos_activity_back_cb(lv_event_t *e);

Convenient wrapper for use in LVGL event callbacks.

Core API

Creation and Initialization

// Normal Activity (for applications, lists, etc.)
eos_result_t eos_activity_controller_init(eos_activity_t *initial_activity);
void eos_activity_controller_deinit(void);
eos_activity_t *eos_activity_create(const eos_activity_lifecycle_t *lifecycle);

// Root Activity (for watchfaces only)
eos_activity_t *eos_activity_create_root(const eos_activity_lifecycle_t *lifecycle);
eos_result_t eos_activity_replace_root(eos_activity_t *new_root);
FunctionDescription
eos_activity_controller_initInitialize Activity controller, requires Root Activity (watchface) as parameter
eos_activity_controller_deinitDeinitialize, release all Activities
eos_activity_createCreate normal Activity, View is lazily created
eos_activity_create_rootCreate Root Activity (watchface), View is created immediately
eos_activity_replace_rootReplace current Root Activity (switch watchface)

Smart Lazy Loading Mechanism

The Activity system adopts a smart lazy loading design to simplify initialization:

Activity Query

eos_activity_t *eos_activity_get_current(void);
eos_activity_t *eos_activity_get_visible(void);
eos_activity_t *eos_activity_get_previous(void);
eos_activity_t *eos_activity_get_bottom(void);
eos_activity_t *eos_activity_get_watchface(void);
bool eos_activity_is_transition_in_progress(void);
FunctionDescription
eos_activity_get_currentGet current Activity (top of stack)
eos_activity_get_visibleGet currently fully displayed Activity
eos_activity_get_previousGet previous Activity (used in event callbacks to get source page)
eos_activity_get_bottomGet bottom Activity (usually watchface)
eos_activity_get_watchfaceGet watchface Activity
eos_activity_is_transition_in_progressCheck if transition animation is in progress

View Management

lv_obj_t *eos_activity_get_view(eos_activity_t *activity);
void eos_activity_set_view(eos_activity_t *activity, lv_obj_t *view);
lv_obj_t *eos_activity_get_root_screen(void);
lv_obj_t *eos_view_active(void);
FunctionDescription
eos_activity_get_viewGet View object associated with Activity
eos_activity_set_viewSet View object for Activity
eos_activity_get_root_screenGet root screen object
eos_view_activeGet View of current Activity (convenient method)

Title Management

const char *eos_activity_get_title(eos_activity_t *activity);
void eos_activity_set_title(eos_activity_t *activity, const char *title);
void eos_activity_set_title_id(eos_activity_t *activity, lang_string_id_t id);
lv_color_t eos_activity_get_title_color(eos_activity_t *activity);
void eos_activity_set_title_color(eos_activity_t *activity, lv_color_t color);
FunctionDescription
eos_activity_get_titleGet Activity title
eos_activity_set_titleSet Activity title (string)
eos_activity_set_title_idSet title via internationalization string ID
eos_activity_get_title_colorGet title color
eos_activity_set_title_colorSet title color

Type Management

void eos_activity_set_type(eos_activity_t *activity, eos_activity_type_t type);
eos_activity_type_t eos_activity_get_type(eos_activity_t *activity);

AppHeader Visibility Control

void eos_activity_set_app_header_visible(eos_activity_t *activity, bool visible);
void eos_activity_set_app_header_visible_animated(eos_activity_t *activity, bool visible, uint32_t duration_ms);
bool eos_activity_is_app_header_visible(eos_activity_t *activity);
void eos_activity_set_app_header_time_only(eos_activity_t *activity, bool time_only);
bool eos_activity_is_app_header_time_only(eos_activity_t *activity);
void eos_activity_set_app_header_time_only_text_color(eos_activity_t *activity, lv_color_t color);
lv_color_t eos_activity_get_app_header_time_only_text_color(eos_activity_t *activity);
FunctionDescription
eos_activity_set_app_header_visibleSet AppHeader visibility
eos_activity_set_app_header_visible_animatedSet AppHeader visibility with animation, duration_ms of 0 switches immediately
eos_activity_is_app_header_visibleCheck if AppHeader is visible
eos_activity_set_app_header_time_onlySet AppHeader to show only time
eos_activity_is_app_header_time_onlyCheck if AppHeader shows only time
eos_activity_set_app_header_time_only_text_colorSet font color for time-only mode
eos_activity_get_app_header_time_only_text_colorGet font color for time-only mode

User Data

void *eos_activity_get_user_data(eos_activity_t *activity);
void eos_activity_set_user_data(eos_activity_t *activity, void *user_data);

Snapshot

lv_obj_t *eos_activity_take_snapshot(eos_activity_t *activity, bool include_header);

Get snapshot image of Activity view. include_header controls whether to include AppHeader.

Note: Snapshot image resources are automatically released when the object is deleted.

Transition Animation

eos_result_t eos_activity_register_anim_route(
eos_activity_type_t from_type,
eos_activity_type_t to_type,
eos_activity_anim_cb_t cb);

eos_activity_anim_cb_t eos_activity_get_anim_route(
eos_activity_type_t from_type,
eos_activity_type_t to_type);

Register and query transition animation routes between pages.

View Details

View is the LVGL object associated with Activity, serving as the root container for the Activity page's UI content. Each Activity should set a View after creation.

Create View

// Create Activity
eos_activity_t *activity = eos_activity_create(&lifecycle);

// Create View (based on root screen)
lv_obj_t *view = lv_obj_create(eos_activity_get_root_screen());
lv_obj_remove_style_all(view);
lv_obj_set_size(view, EOS_DISPLAY_WIDTH, EOS_DISPLAY_HEIGHT);

// Associate View with Activity
eos_activity_set_view(activity, view);

Get Current View

// Method 1: Via Activity
lv_obj_t *view = eos_activity_get_view(activity);

// Method 2: Convenient method (get current Activity's View)
lv_obj_t *active_view = eos_view_active();

View Layout Recommendations

Since ElenixOS targets small-screen devices like smartwatches (typically 390x450), View layout should follow these principles:

  • Use lv_obj_remove_style_all(view) to clear default styles
  • Set View size to screen dimensions: lv_obj_set_size(view, EOS_DISPLAY_WIDTH, EOS_DISPLAY_HEIGHT)
  • Use LVGL's Flex layout or manual positioning to arrange child components

AppHeader

AppHeader is ElenixOS's unified top navigation bar component, displayed in the lv_layer_top() layer, above all Views.

AppHeader API

void eos_app_header_init(void);
void eos_app_header_hide(void);
void eos_app_header_show(eos_activity_t *a);
void eos_app_header_set_visible_animated(eos_activity_t *a, bool visible, uint32_t duration_ms);
bool eos_app_header_is_visible(void);
FunctionDescription
eos_app_header_initInitialize AppHeader (can only be called once)
eos_app_header_hideHide AppHeader
eos_app_header_showShow AppHeader, refresh title of current Activity
eos_app_header_set_visible_animatedShow/hide AppHeader with animation
eos_app_header_is_visibleCheck if AppHeader is visible

Usage Examples

Create Standard Application Activity

// Define lifecycle callbacks
static void on_enter(eos_activity_t *activity) {
lv_obj_t *view = lv_obj_create(eos_activity_get_root_screen());
lv_obj_remove_style_all(view);
lv_obj_set_size(view, EOS_DISPLAY_WIDTH, EOS_DISPLAY_HEIGHT);
eos_activity_set_view(activity, view);

// Set title
eos_activity_set_title(activity, "My App");

// Add UI components
lv_obj_t *label = lv_label_create(view);
lv_label_set_text(label, "Hello, ElenixOS!");
lv_obj_center(label);
}

static void on_destroy(eos_activity_t *activity) {
// Clean up resources
}

// Create Activity
const eos_activity_lifecycle_t lifecycle = {
.on_enter = on_enter,
.on_destroy = on_destroy,
.on_pause = NULL,
.on_resume = NULL,
};

eos_activity_t *activity = eos_activity_create(&lifecycle);
eos_activity_set_type(activity, EOS_ACTIVITY_TYPE_APP);
// Enter new page from current page
eos_activity_enter(new_activity);

// Return to previous page
eos_activity_back();

// Return directly to watchface
eos_activity_back_to_watchface();

Control AppHeader

// Hide AppHeader
eos_activity_set_app_header_visible(activity, false);

// Hide with animation
eos_activity_set_app_header_visible_animated(activity, false, 300);

// Show only time
eos_activity_set_app_header_time_only(activity, true);

Register Transition Animation

static void my_anim_cb(lv_anim_timeline_t *at, eos_activity_t *from, eos_activity_t *to) {
// Custom transition animation
lv_obj_t *from_view = eos_activity_get_view(from);
lv_obj_t *to_view = eos_activity_get_view(to);

// Create animation timeline
// ...
}

// Register transition animation from application to application
eos_activity_register_anim_route(
EOS_ACTIVITY_TYPE_APP,
EOS_ACTIVITY_TYPE_APP,
my_anim_cb);

Activity and Event System

The Activity system is tightly integrated with the Event System. When Activity page switching is complete, the EOS_EVENT_ACTIVITY_SCREEN_SWITCHED event is broadcast:

// Listen for page switch complete event
eos_event_add_cb(some_obj, my_cb, EOS_EVENT_ACTIVITY_SCREEN_SWITCHED, NULL);

static void my_cb(lv_event_t *e) {
lv_obj_t *current_view = lv_event_get_param(e);
// Page switch complete, current_view is the View of current page
}

Activity System Initialization Flow

System Startup


eos_activity_controller_init(watchface_activity)

├── Create Activity stack
├── Get root screen
├── Set watchface Activity as current
└── Call on_enter()


eos_app_header_init()

├── Create AppHeader UI
└── Place in lv_layer_top() layer


System Running

Error Handling

ConditionReturn Value
Activity controller not initializedFunction returns EOS_FAILED
NULL Activity passedFunction checks internally and returns directly
Activity stack is emptyeos_activity_get_current returns NULL
Transition animation in progresseos_activity_is_transition_in_progress returns true

Performance Recommendations

  1. Lazy Initialization: Create UI in on_enter callback, avoid time-consuming operations in constructor
  2. Resource Release: Release all dynamically allocated resources in on_destroy callback
  3. Snapshot Management: Snapshots consume additional memory, avoid holding snapshots for multiple Activities simultaneously
  4. Transition Animation: Animation duration should be controlled between 200-500ms to avoid affecting user experience