본문 바로가기

Mobile/ApplusForm

Profile Template B01 소스 분석(1)_앱플러스폼(ApplusForm, AppForm)

ApplusForm에서 제공하는 Templete 중 VideoClipB01에 대한 강좌입니다.

홈페이지에서 소개하는 내용입니다.

Profile Template A02 Type
Profile Template은 개인 또는 행사, 홍보, 상품 등의 소개에 적합한 유형으로 다양한 애니메이션 효과와 SNS연동 기능이 들어있는 템플릿입니다.
* 주요기능
애니메이션 메뉴, 갤러리, 동영상, 배경화면 및 갤러리 저장, 배경음악 설정 등
* 활용분야
개인 프로필, 공연안내, 상품 카다로그, 청첩장, 초대장 등
* 특징
테마 기능, Twitter, facebook 연동 기능

ProfileB01은 개인용 멀티미디어 스마트폰 명함이라고 볼 수 있겠습니다.
자신의 프로필을 널리 홍보하고 싶거나 지인에게 혹은 인터뷰 대상자에게 자신의 정보를 보다 효과적으로 전달하고 싶을 때 사용하면 유용할 템플릿입니다.

테마, 다양한 애니메이션 효과, 동영상, 갤러리, SNS연동 등 많은 내용을 담고 있습니다.

홈페이지에서도 스크린샷을 볼 수 있지만 어떤 화면을 제공하는지 잠시 보겠습니다.

1

DATA.

메뉴, 갤러리의 이미지경로, 동영상 이미지경로 등 많은 정보를 담고 있습니다.
Readme.txt에 있는 내용을 발췌했습니다.

  • data.xml : 이름, 메뉴명, 탭 이름 등
  • main1.jpg, main2.jpg, main3.jpg : 첫화면의 배경
  • profile.jpg : profile 화면의 좌측 상단 사진
  • gallery1, gallery2, gallery3 : Gallery의 이미지. .jpg 나 .png 형식의 이미지를 폴더에 추가하십시오.
  • movie : 동영상을 넣으려면 .mp4, .avi 형식의 동영상 파일을 추가하고, 같은 이름으로 .jpg 확장자로 미리보기 이미지와 .txt 로 설명을 추가하십시오.
2

메뉴 개수와 갤러리 개수 등을 그대로 유지한채 내용과 이미지만 바꾼다면 /moml/data만 바꿔도 아무런 문제없이 동작합니다.

소스

늘 그렇듯이 시작은 /moml/ui/start.xml입니다.

<FUNCTIONLIST>
    <FUNCTION id="loadData">
        <FUNCTIONITEM cmd="userVariable.data.name=xpath.evaluateEx('data', '/DATA/NAME/@value')"/>
...중략...
    </FUNCTION>
</FUNCTIONLIST>

<DATASOURCELIST>
    <DATASOURCE id="data" src="/data/data.xml"/>
</DATASOURCELIST>

<FUNCTIONCALL cmd="function.loadData" />  

실행하자마자 /data/data.xml을 읽어와 userVariable에 필요한 값을 채워 넣고 있습니다.
이 값들은 앱 내에서 유용하게 사용됩니다.

UI는 뿐이므로 설명하지 않겠습니다.

의 selectedItem attribute에 기본으로 지정되어 처음 로드하는 화면을 보겠습니다.

mainMenu.xml

<UILAYOUT portrait="300,500" landscape="300,500" theme="/theme/common.xml|theme1">

theme에 |을 사용했습니다.
common.xml theme와 함께 문서내에 정의된 theme1도 사용하는 경우 |으로 연결해서 사용할 수 있습니다.
따라서, 이 xml내에서는 applicationInfo.xml에서 정의한 <THEME src="theme/white/theme.xml"/>와 /theme/common.xml, theme1의 세 theme가 함께 적용되므로, xml내에서 theme id를 찾지 못했다면 다른 파일을 찾아보기 바랍니다.

common.xml에는 상단 타이틀바 영역에 대한 정의만 되어 있으니 자주 들여다 볼 일은 없겠습니다.

<WINDOW layout="0,0,0,0" onCreate="function.init" visible="invisible"/>
<WINDOW id="bg" layout="0,0,300,500" defaultImg="/data/main1.jpg"/>
<WINDOW id="overlay" layout="0,0,300,500" visible="invisible"/>
<WINDOW themeId="themeBorderOverlay" layout="0,0,300,500"/>
<WINDOW themeId="themeFlyingObj1" id="flyingObj1"/>
<WINDOW themeId="themeFlyingObj2" id="flyingObj2"/>
<WINDOW themeId="themeFlyingObj3" id="flyingObj3"/>  

배경 이미지를 설정하고 애니메이션션에 사용되는 UI를 배치했습니다.

<!-- 메인 메뉴 -->
<BUTTON text=" {userVariable.data.menu.profile}" id="menuItem1" themeId="menuItem" layout="50,290,auto,40" fontSize="30" onClick="function.menuItemClick('profile')"/>  

text attribute는 상수값을 받아야 하지만 처음에 저장했던 userVariable.data.menu.profile의 값을 넣기 위해 {}를 사용하여 script가 실행되도록 했습니다.
layout을 보면 중간에 auto가 있습니다.
auto는 layout의 width와 height에만 사용됩니다. 이 경우엔 text길이와 fontSize에 맞춰서 <BUTTON>의 width를 자동으로 결정되어 굳이 width값을 몰라도 괜찮을 경우에 사용하면 좋습니다.

<BUTTON text="About" onClick="container.open('about.xml', 'about')" id="subItem4" themeId="subMenuItem" layout="110,120,100,30"/>  

새로운 화면을 띄우고 싶을 때 container.open()을 사용합니다.
about.xml을 띄우는데 대상은 현재 document의 about이라는 <CONTAINER>에 로드하도록 했습니다.
만약 about이라는 id를 갖는 <CONTAINER>가 정의되어 있지 않으면 현재 document에 about이라는 id로 생성하게 됩니다.

document, container의 용어는 MOMLAPIReference문서에 다음과 같이 정의되어 있습니다.

• parent : 부모 윈도우
- UI event attribute(ex:BUTTON.onClick)에서는 caller의 부모 window. parent == caller.parent
- FUNCTIONLIST element 내에서는 FUNCTIONLIST의 CONTAINER. parent == container == document
- FUNCTIONCALL element 내에서는 FUNCTIONCALL의 CONTAINER. parent == container == document == caller
• container : 현재 윈도우나 FUNCTION이 속한 컨테이너
• document : 키워드가 쓰인 현재 개체 기준(function or ui)이 정의된 xml 파일을 로딩한 컨테이너, parent 중에 동일한 파일 내의 최상위 container

메뉴의 애니메이션 부분 Function입니다.

theme/common.xml

<THEME id="menuItem" parent="titleLabel" pressedImg="/res/flare2.png" visible="invisible" onCreate="function.aniMenu" />  

Function

<FUNCTION id="aniMenu"> <!-- 메뉴 등장 애니메이션 -->
    <FUNCTIONITEM cmd="userVariable.aniDelay = userVariable.aniDelay + 1"/>
    <FUNCTIONITEM cmd="userVariable.aniDelayTime = 1000 + 200 * userVariable.aniDelay"/>
    <FUNCTIONITEM cmd="animation.flyIn('caller', -200,100, 100, 25, 'easeOut3', 1000, ''),animation.show('caller', 'fade', '', 1000, '')" delay="userVariable.aniDelayTime"/>
</FUNCTION>  

UI

<BUTTON text=" {userVariable.data.menu.profile}" id="menuItem1" themeId="menuItem" layout="50,290,auto,40" fontSize="30" onClick="function.menuItemClick('profile')"/>
<BUTTON text=" {userVariable.data.menu.gallery}" id="menuItem2" themeId="menuItem" layout="70,340,auto,40" fontSize="30" onClick="function.menuItemClick('gallery')"/>
<BUTTON text=" {userVariable.data.menu.movie}" id="menuItem3" themeId="menuItem" layout="90,390,auto,40" fontSize="30" onClick="function.menuItemClick('movie')"/>

<BUTTON text=" {userVariable.data.menu.link}" id="menuItem4" themeId="menuItem" layout="110,440,auto,30" onClick="function.menuItemClick2('links')"/>  

메뉴 UI인 <BUTTON>은 menuItem Theme를 적용받고 있습니다.
onCreate=“function.aniMenu” 가 theme에 있으므로 각각 <BUTTON>이 생성될 때마다 aniMenu가 실행됩니다.
aniMenu function에서 animation.flyIn(’caller’에서 ’caller’의 자리에는 UI Element의 id가 들어가는 자리입니다만, 아무리 찾아봐도 caller라는 id를 부여받은 UI Element는 찾아볼 수가 없습니다.
’caller’는 예약어이기 때문입니다. caller는 자기 자신이라고 보면 됩니다. <BUTTON>인 menuItem1의 caller 는 menuItem1입니다.
따라서 각 <BUTTON>의 onClick에서 function.aniMenu가 호출되므로 animation.flyIn(’caller’의 ’caller’는 각 <BUTTON>의 id가 됩니다.

이와 같은 caller를 이용한 부분이 많이 있으므로 다른 Function도 한번 분석해보시기 바랍니다.

Theme를 변경하는 Function입니다.

<FUNCTION id="changeTheme">
    <FUNCTIONITEM condition="application.themeSrc=='theme/black/theme.xml'" cmd="application.loadTheme('theme/white/theme.xml')" elseCmd="application.loadTheme('theme/black/theme.xml')"/>
</FUNCTION>  

application.laodTheme를 이용하면 앱 전체에 적용되는 theme xml를 실시간으로 교체할 수 있습니다.
theme가 교체되면 모든 리소스 및 값들이 변경되므로 화면이 한차례 깜박이며 교체된 화면으로 출력됩니다.

Webbrowser를 실행하거나 외부 애플리케이션을 호출할 때 appLauncher.openUri를 이용합니다.
여기서는 카카오톡을 실행하여 메시지를 보내는 기능을 예로 들었습니다.

<FUNCTION id="kakaoLink(appId, msg, url)">  <!-- 카톡으로 링크 보내기 -->
    <FUNCTIONITEM cmd="appLauncher.openUri('kakaolink://sendurl?appid=' +appId + '&amp;appver='+ application.version + '&amp;msg=' + msg + '&amp;url=' + url, '')"/>
</FUNCTION>
<FUNCTION id="smsLink(msg, url)"> <!-- SMS로 링크 보내기 -->
    <FUNCTIONITEM cmd="device.sms('', msg + '\n' + url, '')"/>
</FUNCTION>  

단말에 내장된 SMS 작성기로 전송하고 싶을 때에는 device.sms를 호출하면서 수신번호와 메시지를 함께 넘겨주면 메시지 작성화면으로 이동하여 SMS를 보낼 수 있습니다.

VideoClipA01은 분량이 많아 2회에 걸쳐 강좌를 올리겠습니다.