2013-05-30 88 views
0

这是一个具体问题,但我仍然发布它...在运行时更改静态变量

我无法在运行时更改静态变量。我的问题是,我不能在运行时更改列表视图中的行数。它适用于下面的代码,但此列表现在是静态的。如果用户想要添加或删除一个项目,则此示例中的列表仍有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. 
+0

我不明白,你想在运行时改变什么? –

+0

不容易解释,对不起。但我解决了它(希望)。在静态SimpleMenuItem menu_section0_items [5];我可以在一个部分中设置最大的项目。在这一行.items = menu_section0_items我用uint32_t变量交换了menu_section0_items。现在它可以工作。也许最好删除这个问题:( – Peter

回答

0

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

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)

这种方法需要比SimpleMenuLayer方法设置以下,除去重复调用类似/相同功能,可在菜单(其成为容易出错的应用程序的增长),使代码更容易阅读和理解,并且与其他API/SDK如何实现相同目标更接近。

我也认为这是Pebble的人们如何实现动态菜单的原因,如果您将其与feature_simple_menu_layer示例进行比较,我认为您会同意这是一个更清晰,更易于理解的实现一个动态菜单。