The [UI Sample] SNS sample application demonstrates how to make a complex view by recursive composition of standard EFL UI components and containers in a UI component hierarchy.
The sample uses UI components, such as elm_conform, elm_naviframe, elm_scroller, elm_toolbar, and elm_panel for the view management, containers, such as elm_table and elm_box for the UI component management inside the view, and UI components, such as elm_button, elm_label, elm_genlist, and elm_gengrid for the content inside the view.
The following figure illustrates the SNS view, its wireframe structure, and the UI component tree.
Figure: SNS view
Application Layout
The create_base_gui() function creates the window, conformant, and naviframe. It also creates the view layout and drawer (elm_panel). The drawer is inserted in the layout. The drawer button is inserted in the naviframe.
static void create_base_gui(appdata_s *ad) { Evas_Object *layout, *bg, *drawer, *btn; Elm_Object_Item *nf_it; ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE); elm_win_conformant_set(ad->win, EINA_TRUE); elm_win_autodel_set(ad->win, EINA_TRUE); elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW); elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE); evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, NULL); eext_object_event_callback_add(ad->win, EEXT_CALLBACK_BACK, win_back_cb, ad); ad->conform = create_conform(ad->win); // Naviframe ad->nf = elm_naviframe_add(ad->conform); elm_object_content_set(ad->conform, ad->nf); layout = create_main_view(ad); nf_it = elm_naviframe_item_push(ad->nf, _("News Feed"), NULL, NULL, layout, "basic"); // Drawer bg bg = create_bg(layout); elm_object_part_content_set(layout, "elm.swallow.bg", bg); // Drawer drawer = create_panel(layout); eext_object_event_callback_add(drawer, EEXT_CALLBACK_BACK, drawer_back_cb, ad); evas_object_smart_callback_add(drawer, "scroll", panel_scroll_cb, bg); elm_object_part_content_set(layout, "elm.swallow.right", drawer); // Drawers Button btn = create_drawers_btn(ad->nf, btn_cb, drawer); elm_object_item_part_content_set(nf_it, "title_right_btn", btn); // Show the window after the base GUI is set up evas_object_show(ad->win); evas_object_event_callback_add(ad->win, EVAS_CALLBACK_RESIZE, view_size_reset, ad); }
Main View
The create_main_view() function creates the main content. It consists of a single layout containing a box. The box contains the tab bar (elm_toolbar) and a scroller. The toolbar acts as the view changer and indicator. Its vertical weight is 0.12, which means that the toolbar occupies 12% of the box. The rest of the area contains the scroller, which includes another box. The box contains 4 views horizontally. Each view has a minimum size, which is the same as the screen width.
static Evas_Object * create_main_view(appdata_s *ad) { Evas_Object *layout, *box, *box2, *table; Evas_Object *first_view, *second_view, *third_view, *fourth_view; // Layout for drawer layout = create_drawer_layout(ad->nf); // Box box = elm_box_add(layout); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_part_content_set(layout, "elm.swallow.content", box); // Tab bar ad->tabbar = _create_tabbar(box, ad); evas_object_size_hint_weight_set(ad->tabbar, EVAS_HINT_EXPAND, 0.12); evas_object_size_hint_align_set(ad->tabbar, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_pack_end(box, ad->tabbar); // Scroller ad->scroller = create_scroller(box, ad); evas_object_size_hint_weight_set(ad->scroller, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->scroller, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_pack_end(box, ad->scroller); // Box box2 = elm_box_add(ad->scroller); elm_box_horizontal_set(box2, EINA_TRUE); evas_object_size_hint_weight_set(box2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(box2, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_content_set(ad->scroller, box2); // First view first_view = create_first_view(box2, ad); ad->first_view_rect = min_set(first_view, box2, 0, 0); return layout; }
The min_set() function is used for setting the minimum value of a UI component. Currently, the evas_object_size_hint_min_set() function does not work for an elementary UI component. Instead, this function uses the fact that a table contains a rectangle with a minimum value. The object expands to the minimum size of the rectangle.
static Evas_Object * min_set(Evas_Object *parent, Evas_Object *box, Evas_Coord w, Evas_Coord h) { Evas_Object *table, *rect; table = elm_table_add(box); evas_object_show(table); rect = evas_object_rectangle_add(evas_object_evas_get(table)); evas_object_size_hint_min_set(rect, w, h); evas_object_size_hint_weight_set(rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(rect, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_table_pack(table, rect, 0, 0, 1, 1); evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_table_pack(table, obj, 0, 0, 1, 1); evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(table, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_pack_end(box, table); return rect; }
The create_tabbar() function creates the tab bar using the elm_toolbar() function. The ELM_TOOLBAR_SHRINK_EXPAND parameter is set for items to occupy the same area in the toolbar area. The elm_toolbar_transverse_expanded_set() function expands the vertical size of the toolbar in the horizontal mode. Because the toolbar is used as a tab bar, at least 1 item should be selected. Set it using the ELM_OBJECT_SELECT_MODE_ALWAYS parameter.
static Evas_Object * create_tabbar(Evas_Object *parent, appdata_s *ad) { Evas_Object *tabbar; tabbar = elm_toolbar_add(parent); elm_toolbar_shrink_mode_set(tabbar, ELM_TOOLBAR_SHRINK_EXPAND); elm_toolbar_transverse_expanded_set(tabbar, EINA_TRUE); elm_toolbar_select_mode_set(tabbar, ELM_OBJECT_SELECT_MODE_ALWAYS); elm_toolbar_item_append(tabbar, ICON_DIR"/00_controlbar_icon_playlist.png", NULL, tabbar_first_cb, ad); elm_toolbar_item_append(tabbar, ICON_DIR"/00_controlbar_icon_artists.png", NULL, tabbar_second_cb, ad); elm_toolbar_item_append(tabbar, ICON_DIR"/00_controlbar_icon_dialer.png", NULL, tabbar_third_cb, ad); elm_toolbar_item_append(tabbar, ICON_DIR"/00_controlbar_icon_more.png", NULL, tabbar_fourth_cb, ad); evas_object_show(tabbar); return tabbar; }
When a toolbar item is clicked, the tabbar_first_cb() function is called. In the function, the naviframe title changes and sets the scroll page value to 0.
static void tabbar_first_cb(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; elm_object_item_part_text_set(elm_naviframe_top_item_get(ad->nf), "elm.text.title", "News Feed"); elm_scroller_page_bring_in(ad->scroller, 0, 0); }
The create_scroller() function creates a scroller and sets options for the page view. To use this view, the scroller should use the tabbar style instead of the default style. It creates an indicated bar above the tab bar. Since the bar is a horizontal scrollbar of the scroller, it should be always visible. Thus, the second parameter of the elm_scroller_policy_set() function is ELM_SCROLLER_POLICY_ON.
The horizontal page is set to 480 and the page moves only 1 page at a time.
The ELM_SCROLLER_SINGLE_DIRECTION_HARD parameter is for scrolling in the scroller. The scroller has 4 pages and each page can have their own scroller. In this case, if you scroll, both scrollers are scrolled. If you want the outside scroller is scrolled only horizontally and the scroller in the page is scrolled only vertically, use the elm_scroller_single_direction_set() function with the ELM_SCROLLER_SINGLE_DIRECTION_HARD parameter.
To select a toolbar item at the end of a scroll animation, use the scroll,anim,stop smart callback.
static Evas_Object * create_scroller(Evas_Object *parent, appdata_s *ad) { Evas_Object *scroller; scroller = elm_scroller_add(parent); elm_object_style_set(scroller, "tabbar"); elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_ON, ELM_SCROLLER_POLICY_OFF); elm_scroller_page_size_set(scroller, 480, 0); elm_scroller_page_scroll_limit_set(scroller, 1, 0); elm_scroller_single_direction_set(scroller, ELM_SCROLLER_SINGLE_DIRECTION_HARD); evas_object_smart_callback_add(scroller, "scroll,anim,stop", anim_stop_cb, ad); evas_object_show(scroller); return scroller; }
First View
The following figure illustrates the first view, its wireframe structure, and the UI component tree.
Figure: SNS first view
The create_first_view() function creates the first view. It creates a scroller which contains a box and packs the content created by the create_box_content() function.
static Evas_Object * create_first_view(Evas_Object *parent, appdata_s *ad) { Evas_Object *scroller, *box, *content, *table; int i; scroller = elm_scroller_add(parent); elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); elm_scroller_single_direction_set(scroller, ELM_SCROLLER_SINGLE_DIRECTION_HARD); box = elm_box_add(scroller); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_padding_set(box, 0, 30); elm_object_content_set(scroller, box); for (i = 0; i < 20; i++) { content = create_box_content(box); min_set(content, box, 0, 0); } evas_object_show(scroller); return scroller; }
The create_box_content() function creates a box which contains a label and a box. The second box contains 3 buttons and occupies 30% of the content area.
Evas_Object *create_box_content(Evas_Object *parent) { Evas_Object *box, *box2, *label, *btn; box = elm_box_add(parent); label = elm_label_add(box); evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_label_wrap_width_set(label, 30); elm_label_line_wrap_set(label, ELM_WRAP_MIXED); elm_object_text_set(label, "EFL is a collection of libraries that are independent or may build on top of each-other to provide useful features that complement an OS's existing environment, rather than wrap and abstract it, trying to be their own environment and OS in its entirety."); elm_box_pack_end(box, label); evas_object_show(label); box2 = elm_box_add(box); evas_object_size_hint_weight_set(box2, EVAS_HINT_EXPAND, 0.3); evas_object_size_hint_align_set(box2, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_horizontal_set(box2, EINA_TRUE); elm_box_padding_set(box2, 15, 0); elm_box_pack_end(box, box2); evas_object_show(box2); btn = elm_button_add(box2); evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_text_set(btn, "I like it"); elm_box_pack_end(box2, btn); evas_object_show(btn); evas_object_show(box); return box; }
The descriptions of the second, third, and fourth view are omitted.