Tizen UI Screen Layouts

hoyunadmin 12월 7, 2016 댓글 없음

Application의 UI를 개발하기 위해서는 체계적으로 UI Frame을 구성해야 효율적인 Application을 개발할 수 있습니다. 이에 이번 포스터에서는 Tizen Native Application UI개발을 위한 효율적인 UI Frame구성 방법과 각 Object의 기능에 대해 살펴보겠습니다.

Tizen Developer Site에서는 Tizen Native Application UI개발에 있어 Base Layout에 Applcation을 배치하는 것을 권장하고 있습니다. 그럼 먼저, Base Layout은 어떻게 구성되어 있는지 살펴보겠습니다.

(참고. https://developer.tizen.org/development/guides/native-application/user-interface/efl/ui-containers/creating-ui-screen-layouts)

base

<그림1. Base Layout wireframe and UI component hierarchy>

Tizen의 UI Frame은 그림1과 같이 Window – Conformant – Naviframe – View 순으로 계층형식으로 이루어져 있는 것을 볼 수 있습니다. 여기서 Window – Conformant – Naviframe은 Base Layout이고, Application Layout(View)는 Naviframe 위에 추가되는 것을 볼 수 있습니다.

각 계층은 다음과 같은 역할을 하고 있습니다.

1. Window(elm_win)

Window는 Screen Layout의 최상위 Object로 모든 UI 구성요소는 Window에 렌더링 됩니다.

2. Conformant(elm_conformant)

Conformant는 회전 또는 키패드로 인해 영역이 할당될 시 표시될 영역을 지원하고, Application의 크기를 조정합니다.

3. Naviframe(elm_naviframe)

Naviframe은 View의 Manager 역할을 하며, 선택적으로 Application의 Title을 제공합니다.

Naviframe은 잠시 후 자세히 설명하겠습니다.

Base Layout을 사용하는 것은 권장사항이며 필요에 의해 배제할 수 있습니다.(단, Window는 필수)

즉, Window에 직접적으로 View를 구성할 수 있고, 필요에 의해서 Conformant 혹은 Naviframe 혹은 둘 중하나는 배제하고 UI를 구성할 수 있습니다. 하지만, 효율적인 Layout을 구성하기 위해서는 Base Layout에 View를 구성하는 것이 좋습니다.

그럼 예제를 통해 Base Layout을 구성해보고 Base Layout에 간단한 Text를 출력하는 Application Layout을 추가해보겠습니다.

Tizen Studio에서 제공되는 ‘Basic UI with EDC’ Template을 활용하여 새로운 프로젝트를 생성하겠습니다.

생성된 프로젝트에서 create_base_gui 함수로 이동하시면 다음과 같이 Naviframe을 제외한 Base Layout이 기본적으로 생성되는 것을 볼 수 있습니다.(현 포스트에서는 가독성을 올리기 위해 소스상에서 appdata_s 구조체를 제거하였습니다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
static void
create_base_gui(appdata_s *ad)
{
    char edj_path[PATH_MAX] = {0, };
    /* Window */
    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);
    if (elm_win_wm_rotation_supported_get(ad->win)) {
        int rots[4] = { 0, 90, 180, 270 };
        elm_win_wm_rotation_available_rotations_set(ad->win, (const int *)(&rots), 4);
    }
    evas_object_smart_callback_add(ad->win, “delete,request”, win_delete_request_cb, NULL);
    /* Conformant */
    ad->conform = elm_conformant_add(ad->win);
    elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW);
    elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE);
    evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
    elm_win_resize_object_add(ad->win, ad->conform);
    evas_object_show(ad->conform);
    /* Base Layout */
    app_get_resource(EDJ_FILE, edj_path, (int)PATH_MAX);
    ad->layout = elm_layout_add(ad->win);
    elm_layout_file_set(ad->layout, edj_path, GRP_MAIN);
    elm_object_part_text_set(ad->layout, “txt_title”, “Hello Tizen”);
    evas_object_size_hint_weight_set(ad->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
    eext_object_event_callback_add(ad->layout, EEXT_CALLBACK_BACK, layout_back_cb, ad);
    elm_object_content_set(ad->conform, ad->layout);
    /* Show window after base gui is set up */
    evas_object_show(ad->win);
}

그럼, Conformant 밑에 Naviframe을 추가하여 Base Layout을 완성해보겠습니다.

1
2
3
4
5
6
7
/* naviframe */
Evas_Object *naviframe;
naviframe = elm_naviframe_add(ad->conform);
evas_object_size_hint_weight_set(naviframe, EVAS_HINT_EXPAND,EVAS_HINT_EXPAND);
elm_object_content_set(ad->conform, naviframe);
evas_object_show(naviframe);

위 naviframe소스는 예제소스로 상황에 맞춰 변경될 수 있습니다.

이로서 Base Layout은 완료되었습니다. Base Layout에 사용된 중요 API를 설명드리겠습니다.

1. elm_win_util_standard_add() : Window Object 생성 API

Parameter : Window Name, Window Title

2. elm_object_smart_callback_add() : 위젯 혹은 컨터이너 같은 스마트 object에 이벤트 콜백 함수를 지정하는 API

Parameter : Smart Object, Event Name(String), Callback Function, Data

3. elm_conformant_add() : Conformant Object 생성 API. 하나의 APP은 하나의 Conformant 만을 가져야 하며, 필요에 의해 Conformant가 없어도 문제 되지 않습니다.

Parameter : Parent Object

4. elm_win_indicator_mode_set() : indicator 표시 여부를 지정하는 API

Parameter : Window Object, 설정 모드(#Elm_Win_Indicator_Mode 중 선택)

5. elm_win_indicator_opacity_set() : indicator 투명도 지정 API

Parameter : Window Object, 설정 모드(#Elm_Win_Indicator_Opacity_Mode 중 선택)

6. elm_object_resize_object_add() : Window Object에 다른 Object를 추가하면서 크기를 변경하는 API

Parameter : Window Object, resize할 Object

Base Layout이 완료되었으므로 간단한 text를 출력하는 Application Layout을 Base Layout에 추가해보겠습니다.

(Application Layout은 Layout 뿐만 아니라 Table, Grid 등 상황에 맞춰 적용이 가능합니다.)

1
2
3
4
5
6
7
8
9
/* Base Layout */
layout = elm_layout_add(naviframe);
elm_layout_file_set(layout, EDJ_FILE, GRP_MAIN);
evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_object_content_set(naviframe, layout);
evas_object_show(layout);
elm_naviframe_item_push(naviframe,NULL,NULL,NULL,layout,”empty”);

Application Layout은 지난 포스터와 같이 text를 출력하는 EDJ파일의 PATH를 잡아 layout에 적용하였습니다.

여기서 중요한 부분은 코드의 마지막 줄인 elm_naviframe_item_push() API 입니다.

elm_naviframe_item_push() API에 대해 살펴보겠습니다.

1. elm_naviframe_item_push() : 새 item을 naviframe stack 위에 추가합니다.(and show)

Parameter : naviframe Object, lable in the title area, 이전 항목 이동 버튼, 다음 항목으로 이동 버튼,                                                                   main content Object, 현재 item style name

Return : Success Or Fail

즉, 위 소스에서 생성한 Item인 layout을 naviframe Stack 최상단에 올려 화면에 출력하는 것입니다. Application Layout은 layout, table, grid등 상황에 맞춰 적용이 가능하기 때문에 naviframe에 push되는 item은 사용자가 원하는 item을 지정할 수 있습니다. 이로서, Base layout에 Application layout을 올려 화면에 출력되는 것을 볼 수 있습니다.

hello-hoyun

<사진1. Base Layout and Application Layout>

위에 언급 했듯이, naviframe은 View의 Manager역할을 합니다. 단 하나의 화면을 출력할 경우에는 naviframe없이 window에 직접적으로 Layout을 적용할 수 있습니다. 하지만, 여러 개의 화면을 가지고 있는 Application의 경우 naviframe 활용에 따라 더욱 효율적인 UI를 개발할 수 있습니다. 이에 naviframe에 대해 조금 더 살펴보겠습니다.

naviframe을 통해 현 화면에 어떠한 view를 출력할지 결정하고 또한, view의 전환이 될 수 있게 지원합니다. naviframe은 view stack으로 구성되어 있습니다. 새로 push된 view는 이전 view 위에 push되고 stack 최상단 view만 화면에 출력됩니다. 이전 view는 삭제되지 않습니다. 이전 view는 상단의 view가 POP되면 화면에 출력됩니다. 이해를 돕기 위해 그림을 통해 설명하겠습니다.

asfsf

<그림2. naviframe Stack>

A라는 Layout과 B라는 Layout 두 개의 Layout을 가지고 있는 Application이 있습니다. 첫 화면인 A Layout을 출력하기 위해 navifarme stack에    A Layout을 Push하여 화면에 출력합니다. 이어서 어떠한 이벤트를 통해 B Layout이 화면 출력이 요구되는 상황이 발생하면, B Layout을 출력하기 위해 B Layout을 navifarme에 Push하여 화면에 출력합니다. navifarme은 Stack 최상단 View만 출력하기 때문에 최상단 View인 B Layout만 출력하게 됩니다. B Layout이 화면에 출력이 되고 있지만, A Layout은 제거가 된 것이 아니고, B Layout 밑에 존재하고 있게 됩니다. B Layout이 A Layout을 가리고 있다고 생각하면 쉽습니다. 다시 A Layout을 출력하기 위해서는 Stack 최상단 View인 B Layout을 POP하게 되면 Stack의 최상단인 A Layout이 화면에 출력됩니다.

그럼 이제 소스코드를 작성하여 naviframe에 대해 살펴보겠습니다.

예제로 개발될 프로젝트는 Main View에서 버튼을 클릭하면 Sub View가 출력되고 다시 버튼을 클릭하면 Main View가 출력되는 화면 전환 프로젝트입니다.

Tizen Studio에서 제공되는 ‘Basic UI with EDC’ Template을 통해 프로젝트를 생성합니다.

먼저 EDC 파일을 통해 다음과 같이 두 개의 Layout에 적용될 UI를 두 개의 Group으로 나누어 만듭니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
collections {
   group { name: “main_layout”;
      parts {
         part { name: “txt_title”;
            type: TEXT;
            mouse_events: 0;
            description { state: “default” 0.0;
               text { text: “A Layout”; font: “Tizen:style=regular”; size: 20; min: 1 1; align: 0.5 0; ellipsis: -1; }
               color: 0 255 255 255;
               rel1.relative: 0.5 0.25;
               rel2.relative: 0.5 0.5;
            }
         }
      }
   }
   group { name: “sub_layout”;
      parts {
         part { name: “txt_title”;
            type: TEXT;
            mouse_events: 0;
            description { state: “default” 0.0;
               text { text: “B Layout”; font: “Tizen:style=regular”; size: 20; min: 1 1; align: 0.5 0; ellipsis: -1; }
               color: 0 255 255 255;
               rel1.relative: 0.5 0.25;
               rel2.relative: 0.5 0.5;
            }
         }
      }
   }
}

다음으로 create_base_gui함수로 이동하여 다음과 같이 conformant 밑에 nivaframe을 추가하여 base layout을 소스를 작성합니다.

1
2
3
4
5
6
7
8
/* naviframe */
Evas_Object *naviframe;
naviframe = elm_naviframe_add(conformant);
evas_object_size_hint_weight_set(naviframe, EVAS_HINT_EXPAND,
EVAS_HINT_EXPAND);
elm_object_content_set(conformant, naviframe);
evas_object_show(naviframe);

이어서 naviframe에 다음과 같이 main Layout을 추가 후 EDJ FILE의 PATH를 설정하고, Sub Layout으로 이동할 수 있는 버튼을 만들겠습니다.

먼저 layout에 적용할 EDJ파일의 PATH를 define합니다.

#define EDJ_FILE “/opt/usr/apps/org.example.screenlayouts/res/edje/screenlayouts.edj”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* main Layout */
Evas_Object *main_layout;
main_layout = elm_layout_add(naviframe);
elm_layout_file_set(main_layout, EDJ_FILE, “main_layout”);
evas_object_size_hint_weight_set(main_layout, EVAS_HINT_EXPAND,EVAS_HINT_EXPAND);
evas_object_show(main_layout);
/* main button */
Evas_Object *main_button;
main_button = elm_button_add(main_layout);
elm_object_text_set(main_button,
        “<align=center><font_size=20>Go To <br> Sub Layout</font_size></align>”);
evas_object_resize(main_button, 150, 50);
evas_object_move(main_button, 110, 200);
elm_object_content_set(main_layout, main_button);
evas_object_show(main_button);
elm_naviframe_item_push(naviframe, NULL, NULL, NULL, main_layout,”empty”);

생성된 itme 즉, main Layout을 elm_naviframe_item_push를 통해 naviframe stack 최상단에 push시키는 것을 볼 수 있습니다.

프로젝트를 run하게되면 다음과 같이 Main화면이 출력되는 것을 볼 수 있습니다.

main

<사진2. Main Layout>

이어서, 다음과 같이 두 번째 화면이 되는 sub layout을 create_base_gui 함수 위에 create_sub_layout함수를 작성하여 추가 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void create_sub_layout(void *data, Evas_Object *obj, void *event_info) {
    Evas_Object *naviframe = data;
    /* sub layout */
    Evas_Object *sub_layout;
    sub_layout = elm_layout_add(naviframe);
    elm_layout_file_set(sub_layout, EDJ_FILE, “sub_layout”);
    evas_object_size_hint_weight_set(sub_layout, EVAS_HINT_EXPAND,
    EVAS_HINT_EXPAND);
    evas_object_show(sub_layout);
    Evas_Object *sub_button;
    sub_button = elm_button_add(sub_layout);
    elm_object_text_set(sub_button,
            “<align=center><font_size=20>Go To <br> Main Layout</font_size></align>”);
    evas_object_resize(sub_button, 150, 50);
    evas_object_move(sub_button, 110, 200);
    elm_object_content_set(sub_layout, sub_button);
    evas_object_show(sub_button);
    elm_naviframe_item_push(naviframe, NULL, NULL, NULL, sub_layout, “empty”);
}

두 번째 화면이 호출될 시 naviframe에 새 item 즉, sub Layout이 push되게 됩니다. 이로서 naviframe stack의 최상단에는 sub Layout이 존재하게 되고 출력되는 것입니다.

이제 각 버튼에 evas_object_smart_callback_add() API를 통해 클릭 event를 부여하여 버튼을 클릭 시 화면이 전환되는 것을 확인해보겠습니다.

먼저, main Layout에서 sub Layout으로 전환될 수 있게 main_button에 다음과 같이 이벤트를 부여합니다.

1
2
evas_object_smart_callback_add(main_button, “clicked”, create_sub_layout,
            naviframe);

create_sub_layout 함수에 sub Layout을 구성해두었기 때문에, 버튼이 클릭되면 create_sub_layout 함수가 호출되고, sub layout이 naviframe stack의 최상단에 push되어 화면에 출력이 될것입니다.

이어서 sub Layout에서 main Layout으로 화면이 전환될 수 있게 sub_button에 다음과 같이 이벤트를 부여합니다.

1
2
evas_object_smart_callback_add(sub_button, “clicked”, naviframe_pop_cb,
            naviframe);

그리고, create_sub_layout 함수 위에 다음과 같은 함수를 추가합니다.

1
2
3
4
5
void naviframe_pop_cb(void *data, Evas_Object *obj, void *event_info) {
    Evas_Object *naviframe = data;
    elm_naviframe_item_pop(naviframe);
}

sub Layout에서 버튼을 클릭 시 elm_naviframe_item_pop() API를 통해 naviframe stack 최상단에 있는 item을 POP시키는 것을 볼 수 있습니다.

1. elm_naviframe_item_pop() : naviframe 최상단 item pop

Parameter : naviframe

즉, Application이 처음 실행될 시 naviframe stack 최상단에는 main Layout이 존재하고 있습니다. 버튼을 클릭하여 sub Layout으로 화면 전환을 요구시 sub Layout이 naviframe stack 최상단에 Push되어 최상단 item인 sub Layout이 화면에 출력되게됩니다. 다시 main Layout으로 전환하기 위해 버튼을 클릭하면 naviframe 최상단 item 즉, sub layout이 POP이 되어 main layout이 naviframe 스택의 최상단에 위치하게 되어 main layout이 화면에 출력됨을 볼 수 있습니다.

gjsgsksj

<사진3. Naviframe을 통한 화면 전환>

추가로 naviframe에 사용되는 API입니다.

https://developer.tizen.org/dev-guide/native/2.3.0/org.tizen.mobile.native.apireference/group__Naviframe.html

 

감사합니다.

Prepared by : 신재규

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.