在运行时更改静态变量

时间:2013-05-30 15:37:28

标签: c pebble-watch

这是一个具体的问题,但无论如何我发布了......

我无法在运行时更改静态变量。我的问题是我无法在运行时更改列表视图中的行数。它适用于下面的代码,但此列表现在是静态的。如果用户想要添加或删除一个项目,则此示例中的列表仍有5行。

这些是关于部分中项目的脚本行:

#include "pebble_os.h"
#include "pebble_app.h"
#include "pebble_fonts.h"
#include "settings.h"

static Window window;
static SimpleMenuLayer menu_layer;
static SimpleMenuSection menu_sections[1];
static SimpleMenuItem menu_section0_items[5];

[..]

void init_settings_window()

[..]

    menu_sections[0] = (SimpleMenuSection) {
        .title = "Things to buy...",
        .items = menu_section0_items,
        .num_items = ARRAY_LENGTH(menu_section0_items)
    };

API参考中的SimpleMenuSection定义:

struct SimpleMenuSection
Data structure containing the information of a menu section.

Data Fields
const SimpleMenuItem *   items   Array of items in the section.
uint32_t     num_items   Number of items in the .items array.
const char *     title   Title of the section. Optional, leave NULL if unused.

2 个答案:

答案 0 :(得分:1)

更好的解决方案(我认为)是将所有MenuLayer回调设置为函数,并在项目更改时调用menu_layer_reload_data()。如果在运行时期间行数会发生变化,那么为每个部分设置显式回调并不是最佳解决方案,尤其是如果最终可能有多个具有相同回调行为的部分或行。另外,如果你有很多行和/或部分,你的代码会变得非常混乱。除非您要应用的回调对于每一行或每个部分都不同,否则回调应设置一次,在所有行的一个位置。

SimpleMenu示例主要是为非动态菜单设计的。您应该从demos/feature_menu_layer查看演示,而不是如何按预期启动动态菜单。更好的解决方案(IMO)是为整个MenuLayer设置回调(而不是使用SimpleMenuLayer

我会做更像这样的事情:

MenuLayer menu_layer;
uint16_t menu_get_num_sections_callback( MenuLayer *me, void *data )
{
    return 1; // for now, there is only ever 1 section
}

uint16_t menu_get_num_rows_callback(MenuLayer *me, uint16_t section_index, void *data)
{
    return my_var_that_holds_current_row_count;
}

int16_t menu_get_header_height_callback( MenuLayer *me, uint16_t section_index, void *data )
{
    return MENU_CELL_BASIC_HEADER_HEIGHT;
}

void menu_draw_header_callback(GContext* ctx, const Layer *cell_layer, uint16_t section_index, void *data)
{
    menu_cell_basic_header_draw( ctx, cell_layer, "Things to buy..." );
}

void menu_draw_row_callback( GContext* ctx, const Layer *cell_layer, MenuIndex *cell_index, void *data )
{
    switch( cell_index->row )
    {
        // Fill in row content here
    }
}

void window_load( Window *me )
{
    // ... other window code here
    // Set all the callbacks for the menu layer
    menu_layer_set_callbacks( &menu_layer, NULL, (MenuLayerCallbacks )
    {
        .get_num_sections = menu_get_num_sections_callback,
        .get_num_rows = menu_get_num_rows_callback,
        .get_header_height = menu_get_header_height_callback,
        .get_cell_height = menu_get_cell_height_callback,
        .draw_header = menu_draw_header_callback,
        .draw_row = menu_draw_row_callback,

    });
}

如果采用这种方法,您只需刷新菜单即可:

  1. 更新包含行数的变量
  2. 更新包含行/单元格内容的变量
  3. 致电menu_layer_reload_data( menu_layer )
  4. 此方法需要的设置少于SimpleMenuLayer方法,在整个菜单中删除对类似/相同功能的重复调用(随着应用程序的增长而变得容易出错),使代码更易于阅读和理解,并且更多内容与其他API / SDK如何实现相同的目标。

    我也认为这是Pebble的人们想要实现动态菜单的方式,如果你将它与feature_simple_menu_layer例子进行比较,我想你会同意这个更清洁,更容易了解动态菜单的实现。

答案 1 :(得分:0)

您可能需要使用可变长度数组来确定运行时的数组大小。 Varialble长度数组是c99 std的一部分,可用于gcc编译器。