본문 바로가기

2013
임베디드월드

글: 제갈호준 / 2013-12-03





지난 호에는 타이젠 네이티브 UI 프레임워크의 구성에 대해서 살펴보았다. 이번 호에서는 타이젠 네이티브 UI 컨트롤을 살펴보도록 하겠다.

타이젠에서 디바이스 스크린은 컨테이너 컨트롤에 기반하여 구성되는데, 각 UI 컨트롤은 컨테이너 컨트롤 위에 올라가게 된다. 이제부터 몇몇 컨트롤과 컨테이너에 어떻게 컨트롤을 배치하여 레이아웃을 구성할 수 있는지 살펴보자.


[연재 차례]

1. 타이젠, 리눅스 기반 오픈소스 플랫폼
2. 타이젠 SDK(1)
3. 타이젠 SDK(2)
4. 타이젠 플랫폼의 이해
5. 타이젠 웹 애플리케이션 개발(1)
6. 타이젠 웹 애플리케이션 개발(2)
7. 타이젠 네이티브 애플리케이션 개발(1)
8. 타이젠 네이티브 애플리케이션 개발(2)
9. 타이젠 개발자 서밋 코리아 2013
10. 타이젠 플랫폼 개발



타이젠 시리즈 (8)

타이젠 네이티브 애플리케이션 개발 ②


네이티브 UI 애플리케이션


네이티브 UI 애플리케이션은 네이티브 애플리케이션 프레임워크와 네이티브 UI 프레임워크 기반으로C++ 언어를 사용하여 개발할 수 있다[1]. 네이티브 애플리케이션 프레임워크는 Tizen::App 네임스페이스로 구현되어 있는데, 이 안의 Tizen::App:App클래스가 네이티브 UI 애플리케이션의 실행과 라이프 사이클을 관리한다.



[그림 1] 네이티브 UI, 그래픽 아키텍처 (출처 : 자체 제작)


UI 컨트롤이란?

폼, 버튼, 리스트, 에디트 필드와 같은 사용자 인터페이스 요소들을 말하며, 이들은 애플리케이션 레이아웃을 작성하기 위한 기본적인 부품이 된다. 타이젠 웹 프레임워크를 비롯하여 다른 플랫폼에서는 이를 위젯이라고 부르기도 한다. 타이젠 네이티브에서는 약 40여개의 UI 컨트롤이 있다.

클래스 계층 구조를 보면, 모든 컨트롤은 추상 클래스인 Tizen::Ui::Control 부터 상속된다. 이 클래스는 다음과 같은 인터페이스를 포함한다.

• 크기, 위치와 같은 프로퍼티
• Draw, Show와 같은 함수
• 사용자 입력에 반응하는 인터페이스
• 키 입력, 포커스, 터치 입력, 제스처, 드래그 앤 드롭과 같은 이벤트를 처리하고 전달하는 구조


컨테이너 컨트롤 

이름에서 의미하듯이, 컨테이너 컨트롤은 다른 컨트롤을 담을 수 있다. 가장 기본적인 컨트롤은 GroupContainer인데, 이 컨트롤은 격자와 배경색을 통해 컨트롤을 그룹 지어 놓는다. 자식 컨트롤들은 그룹 컨테이너가 가지고 있는 각 격자에 추가 될 수 있으며, 격자를 서로 병합시킬 수도 있다. 팝업 컨테이너, 테이블 뷰 컨테이너 등은 이번호에서 자세히 다루도록 할 것이다.

<팝업>
Popup, MessageBox, ProgressPopup은 스크린 중앙에 모달(modal)이나 모달리스(modale ss) 대화창으로 나타난다. MessageBox는 Popup과 비슷한데, 다만 좀 더 설정 가능하다. Popup은 모달과 모달리스를 모두 지원하지만, MessageBox는 모달만 지원한다.

표 1은 메시지상자를 열고 사용자로부터 응답을 받는 방법을 보여준다.


<패널>
Panel 패널은 일반적인 사각형 컨테이너로서 컨트롤이나 다른 패널들까지도 그룹 지을 수 있다. Panel은 정의된 영역에 원하는 색상을 줄 수도 있으며, 자식 컨트롤을 정렬할 수도 있다. 기본적으로는 폼과 패널 모양이 같지만, 레이아웃 프로퍼티를 설정하면 룩앤필을 바꿀 수도 있다. 표 2는 Panel을 생성하는 코드이다.


[그림 1] Popup, MessageBox, ProgressPopup(출처 : 타이젠 공식 웹사이트, 이하 동일)





[그림 2] ScrollPanel과 Panel

ScrollPanel은 스크롤바를 자동으로 생성해주는 패널이며, SplitPanel은 여러 페인(pane)으로 구분된 패널이다. 일반적으로 왼쪽 페인에는 선택 가능한 아이템을 놓고, 오른쪽에는 그것에 관한 자세한 정보를 보여주는데 사용되기도 한다. SplitPanel의 인스턴스를 만들려면, 페인을 나눌 방향이 수직인지 수평인지 정해야 한다.



[그림 3] SplitPanel

<레이아웃>
컨테이너를 사용하여 컨트롤을 그룹 지었다면, 자식 컨트롤을 원하는 레이아웃으로 만들기 쉽다.
예를 들면 'OK' 와 'Cancel' 버튼은 수평으로 배치되며, 화면의 아래쪽에 오른 정렬로 배치될 수 있다.

Tizen::Ui::RelativeLayout 클래스는 각 자식 컨트롤의 크기와 위치를 컨테이너 안의 다른 자식 컨트롤의 크기와 위치에 자동으로 비례하여 바뀌도록 할 수 있다. 컨테이너에 레이아웃을 적용하려면 표 4와 같이 RelativeLayout을 컨테이너의 Construct()에 인자로 명시하여야 한다.


RelativeLayout은 SetHeight(), SetCenterAligned(), SetMargin(), SetRelation(), SetWidth() 메소드를 제공한다. 표 5와같이 이 메소드를 통해, 컨트롤을 다른 컨트롤에 상대적으로 배치하거나 수직이나 수평 중앙에 배치할 수 있다.


그 외에도 다른 레이아웃 컨트롤이 더 있는데, CardLayout은 자식 컨트롤을 부모 컨트롤의 영역에 꽉 차도록 하며, HorizontalBoxLa yout과 VerticalBoxLayout은 수직이나 수평으로 컨트롤을 정렬한다. 또한 GridLayout은 자식 컨트롤을 격자로 나뉘어진 영역에 배치할 수 있다.


기본 UI 컨트롤

이번 절에서는 Button, EditField, CheckBox 등과 같은 기본적인 UI 컨트롤에 대해서 설명한다.

<버튼>
버튼컨트롤은 더 이상의 설명이 필요 없을 만큼 우리에게 친숙한 컨트롤이다. 버튼 위에 텍스트를 쓸 수도 있으며, 색을 바꾸거나 이미지를 입힐 수도 있다.

버튼은 normal, highlighted, pressed, disabled와 같이 여러 상태가 있을 수 있으며, 버튼의 이벤트를 처리하기 위해서는 표 6과 같이 OnActionPerformed()라는 이벤트 핸들러를 사용하면 된다.


<텍스트박스 등>
EditArea, EditField, Textbox, ExpandableEditArea는 간단한 숫자에서부터 복잡한 URL까지 여러 가지 종류의 텍스트 입력을 받을 수 있다. 사용자가 각 컨트롤의 입력 부분을 터치하면, 키패드와 커서가 자동으로 나타난다. 이러한 컨트롤 역시 배경 이미지를 입히거나 색상을 바꿀 수 있다.

각 컨트롤의 차이점을 설명하자면 EditField는 한 줄 입력만 가능하고, EditArea는 여러 줄 입력이 가능하다.

ExpandableEditArea는 여러 줄 입력이 가능하면서 현재 라인 수에 따라 컨트롤의 높이가 자동으로 조정된다. TextBox는 텍스트를 보여주기만 하고 수정할 수는 없다.

<갤러리>
Gallery는 이미지를 한 장씩 보여주는 UI 컨트롤이다. 또한 자동으로 다음 사진을 보여주는 '슬라이드 쇼' 방식으로도 이미지를 보여줄 수 있다. Gallery는 더블 클릭이나 핀치 제스처를 이용하여 이미지의 확대 축소가 가능하다.

Gallery를 통해 이미지를 추가, 삭제, 얻어오기를 할 수 있는데, Gallery의 각 아이템은 Galle ryItem 클래스로 표현된다. GalleryItem을 갤러리 인스턴스에 추가하기 위해서는 IGalleryIte mProvider 인터페이스를 구현해야 한다.
표 7의 코드는 IGalleryItemProvider 인터페이스의 CreateItem() 구현 예제다.

[그림 4] EditFiled, EditArea, ExpandableEditArea, TextBox 



IGalleryItemProvider를 구현한 클래스의 인스턴스는 표 8과 같이 갤러리 인스턴스에 추가되어야 한다.


<체크버튼>
CheckButton은 선택/해제 할 수 있는 상태를 보여주고, 입력을 받는다. 그림 6과 같은 스타일의 체크 버튼이 가능하다. 상세 버튼 (  )은 추가적인 선택을 제공하고자 할 때 주로 사용하는 인터페이스이다.

라디오 스타일의 체크버튼은 여러 개의 버튼 중 한 개만 선택할 수 있다. 슬라이딩 스위치 스타일의 체크 버튼은 ON/OFF와 같은 상태를 표시하는데 유용하며 다음과 같은 모양을 하고 있다.

체크 박스나 레이블 부분을 터치하면 체크 상태가 토글 되면서 이벤트가 발생하며, 상세 버튼은 다른 이벤트를 발생시킨다.

Tizen::Ui::Controls::RadioGroup은 여러 개의 체크 박스를 그룹으로 묶어서 라디오 버튼으로 만들어주는데, 다음 코드는 체크 박스를 생성하고 라디오 버튼으로 그룹 짓는 과정을 보여준다.

<컨텍스트 메뉴, 옵션 메뉴>
ContextMenu와 OptionMenu 모두 옵션을 보여주기 위해 사용된다. 컨텍스트 메뉴는 아이콘 버튼을 포함할 수 있으며 서브 메뉴를 가질 수 있다.

ContextMenu의 인스턴스를 생성할 때, 앵커(  )가 가리키는 포인터의 위치를 지정해야 한다. 일반적으로 그림 7에서처럼, 메뉴를 부른 컨트롤의 중앙 위에 위치시키면 된다.

ContextMenu는 표 10과 같이 Construct(  )에서 CONTEXT_MENU_STYLE_LIST 혹은 CON TEXT_MENU_STYLE_ICON로 지정할 수 있다. 메뉴 아이템은 표 11과 같이 추가한다.

컨텍스트 메뉴를 보여주기 위해서는 표 12와 같이 SetShowState(true)를 호출한다.

OptionMenu는 하드웨어 메뉴 키가 눌릴 때만 활성화 되는데, 타이젠 디바이스에서 메뉴 키의 존재는 필수 사항이다. OptionMenu는 Contex tMenu와는 달리 OptionMenu의 특정 위치에만 나타나며, 서브 메뉴를 가질 수 있지만, 서브 메뉴의 서브 메뉴는 가질 수 없다. OptionMenu의 서브 메뉴를 보여줄 필요가 있으면 그림 8과 같이 ContextMenu가 서브 메뉴로서 나타난다.

<헤더와 푸터>
Header와 Footer 컨트롤은 애플리케이션 안에서 화면 전환을 하는데 용이하게 쓰인다. Header와 Footer는 많은 스타일을 포함하고 있으며, 이름처럼 애플리케이션 레이아웃 상단과 하단에 위치한다. 예를 들어 Header는 애플리케이션의 타이틀을 표시해주기도 하며, 탭이나 버튼을 보여주는데 사용된다.

표현 형식에 따라 Header는 그림 9와 같이 다양한 스타일을 가질 수 있다. 기본 헤더는 텍스트만 들어간 모습이지만, 텍스트, 아이콘, 버튼, 애니메이션, 로딩 상태 등을 표시할 수도 있다.



[그림 5] Gallery 컨트롤







[그림 6] 다양한 체크버튼(출처 : 타이젠 공식 웹사이트)





'검색' 이나 '새로고침'과 같은 버튼을 넣는 것도 좋은 방법이며, 화면에 따라 휴지통 버튼 같은 것을 넣는 것도 좋겠다. 탭을 넣을 수도 있는데, 탭은 여러 화면간 전환이나, 내용을 구분하거나 할 때 사용하면 좋다.

푸터는 그림 10과 같으며, 헤더와 같이 여러 가지 용도로 사용된다.


[그림 7] Context Menu





[그림 8] 옵션 메뉴와 옵션 메뉴의 서브 메뉴로 나타난 컨텍스트 메뉴

Header와 Footer를 생성하기 위해서는 Form 인스턴스를 생성할 때 표 13과 같이 지정해주어야 한다.

헤더와 푸터의 인스턴스를 얻어내기 위해서 GetHeader()와 GetFooter() 메소드를 사용하며, 표 14와 같이 얻어낸 인스턴스에 원하는 스타일을 설정할 수 있다.

Header와 Footer는 ButtonItem과 FooterItem 인스턴스를 각각 가지고 있으며 아이템을 추가하는 방법은 표 15와 같다.

Header와 Footer 모두 클라이언트 영역의 크기에 영향을 받으며, 폼 클라이언트 영역에 잡히지 않기 때문에, 두 컨트롤을 삽입하면 실제 클라이언트 영역은 줄어들게 된다.


리스트 뷰와 테이블 뷰

<리스트 뷰>

ListView, GrupedListView, IconListView는 리스트를 표시한다.
ListView는 비트맵, 글자 등과 같은 단순한 아이템 및 애플리케이션에서 정의한 커스텀 아이템을 출력한다. GroupedListView는 리스트 내에 아이템을 그룹화시켜 보여주며, IconListView는 비트맵 이미지나 아이콘을 2차원으로 보여준다(그림 11).


[그림 9] Header의 다양한 스타일




[그림 10] Footer의 다양한 스타일(출처 : 타이젠 공식 웹사이트)



[그림 11] ListView, GroupedListView, IconListView







<테이블 뷰>

TableView는 사용자가 설정한 간단한 아이템들을 표시한다.

ListView는 컨테이너 컨트롤이 아니지만, TableView는 컨테이너 컨트롤이므로 더 다양한 컨트롤들을 아이템으로 가질 수 있다.

그림 12에서 보듯이, 세 가지 타입종류의 테이블 뷰가 있다. GroupedTableView는 그룹을 관리할 수 있으며, 그룹들은 선으로 구분된 영역에 표시된다. SectionTableView는 네모난 상자로 아이템들을 그룹 지어서 표시한다.

TableView를 생성하기 위해서 Construct()를 부를 때, 표 16과 같이 TableView 크기와 아이템 구분선의 존재 여부, 스크롤 스타일 등을 지정해 주어야 한다.

리스트의 아이템을 관리하기 위해서는 모든 리스트 뷰는 아이템 프로바이더를 가져야 한다.

구현된 아이템 프로바이더가 대신 아이템의 생성, 삭제, 업데이트 기능을 제공하게 된다. 각 형태의 테이블뷰는 ITableViewItemProvider,  IGroupedListViewItemProvider, ISectionTable ViewItemProvider와 같은 인터페이스를 가지고 있다.

예를 들어 ITableViewItemProvider를 구현해보면 표 17과 같다.

이제 표 18과 같이 TableView에 해당 아이템 프로바이더를 추가하면 된다.

아이템의 이벤트를 처리하기 위해서는 ITableV iewItemEventListener, IGroupedTableViewItem EventListener, ISectionTableViewItemEventLis tener 인터페이스를 각각 구현해야 한다.

OnTableViewItemStateChanged() 이벤트 핸들러는 사용자가 아이템을 선택하거나, 체크, 해제할 때 발생한다. 리스너인스턴스는 표 19와 같이 추가하면 된다.

테이블 뷰 아이템은 그림 13처럼 수평으로 쓸어내리는 제스처에 대해서 표시할 수 있는 컨텍스트 아이템을 가지고 있다. 컨텍스트 아이템은 리스트 아이템에서 숨겨진 추가 기능을 제공한다. 컨텍스트 아이템은 텍스트, 비트맵 등이 될 수도 있다(표 20).




[그림 12] 테이블 뷰의 종류

마치며

지금까지 타이젠 네이티브 플랫폼에서 제공하는 주요 UI 컨트롤에 대해서 살펴보았다. 몇몇 기본적인 코드를 살펴보면서 컨트롤의 생성과 동작에 대해서 이해하는데 도움이 되었으면 좋겠다.

타이젠 SDK는 모든 UI 컨트롤에 대해서 샘플 애플리케이션을 제공하고 있으며, SDK의 IDE에서Tizen Native Project Wizard의 Sample 탭을 통해서 프로젝트를 생성할 수 있다.

이 프로젝트를 통해서 UI의 실제 실행 모습과 생성 방법을 확인할 수 있으니 꼭 참고해보기 바란다.

참고

[1] Tizen Developers 공식 웹사이트 https://developer.tizen.org/
[2] 모든 그림의 출처 https://developer.tizen.org/



/필/자/소/개/

필자

제갈호준

삼성전자에서 타이젠 네이티브 아키텍처와 테스트 프레임워크 업무를 하였고, 현재는 스마트폰 서비스 플랫폼 개발에 힘쓰고 있다. Software Architecture, Information Retr ieval, Data Mining, Software Engineering, Auto mated Testing 등에 관심을 가지고 있으며 아이오와 주립대에서 박사학위를 취득하였다.





※ 본 내용은 (주)테크월드(http://www.embeddedworld.co.kr)의 저작권 동의에 의해 공유되고 있습니다.
    Copyright ⓒ Techworld, Inc. 무단전재 및 재배포 금지
맨 위로
맨 위로