오랜만에 코로나쪽을 공부해 보겠습니다.
얼마전에 기능이 추가 된 화면전환 효과 Story Board 샘플 소스를 분석해 볼께요.
Story Board API는 예전에 살펴 본 바 있습니다.
이 샘플 예제는 Corona SDK/interface 안에 storyboard 라는 폴더에 있습니다.
우선 main.lua 소스 파일 입니다.
display.setStatusBar( display.HiddenStatusBar )
-- require controller module
local storyboard = require "storyboard"
local widget = require "widget"
-- load first scene
storyboard.gotoScene( "scene1", "fade", 400 )
-- Display objects added below will not respond to storyboard transitions
-- table to setup tabBar buttons
local tabButtons = {
{ label="First", up="icon1.png", down="icon1-down.png", width = 32, height = 32, selected=true },
{ label="Second", up="icon2.png", down="icon2-down.png", width = 32, height = 32 },
}
-- create the actual tabBar widget
local tabBar = widget.newTabBar{
top = display.contentHeight - 50, -- 50 is default height for tabBar widget
buttons = tabButtons
}
main.lua에서는 딱 두 부분으로 나뉘어 져 있습니다.
첫번째는 Story Board 를 이용한 부분이고 두번째는 Tab Button을 이용한 부분입니다.
이 두 기능을 이용하기 위해 storyboard와 widget 을 require 했습니다.
그리고 storyboard 부분은 gotoScene 을 이용해서 화면 전환 한 것 밖에는 없습니다.
scene1.lua 로 가는데 0.4초동안 fade 효과를 이용해서 화면 전환을 합니다.
화면 전환 효과는 fade를 포함해서 모두 20개의 효과가 있습니다.
내용은
여기를 클릭하시면 보실 수 있습니다.
두번째는 탭바를 생성하는 건데요. 일단 tabButtons 테이블 안에 탭버튼 두개의 정보들을 담아 놓습니다. 그리고 widget.newTabBar로 Tabbar를 만드는데요. 중요한건 이 탭 바는 화면전환해도 계속 남아 있는 다는 겁니다.
Story Board API 에서는 scene 의 life cycle 메소드가 4개 있습니다.
createScene,enterScene,exitScene,destroyScene
그리고 이 메소드 안에서 생성한 object 들만 화면전환시 적용이 됩니다.
director.lua 클래스는 localGroup을 생성해서 그 그룹에 insert 한 객체들만 적용이 됐었습니다.
이번에 코로나에서 제공한 화면전환 API는 이보다 더 세밀한 화면 전환 단계를 이용할 수 있게 만들었습니다.
이 4개 메소드가 적용된 예는 Scene1 설명할 때 나올겁니다.
일단 여기서 만드는 tabbar 는 화면전환시 적용되지 않고 처음부터 끝까지 계속 남아있을 겁니다.
(그리고 tab bar 관련된 글을 한번도 안 다뤄봤는데요. 이 기능은 나중에 자세히 다뤄볼께요.)
-- storyboard.gotoScene( "scene1", "fade", 400 )
이렇게 scene1.lua로 넘어가는 부분을 주석 걸어놓고 실행하면 위 화면이 나옵니다.
이게 온전히 main.lua만을 실행했을 때 나오는 화면입니다.
그 다음에 scene1.lua를 보겠습니다.
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
---------------------------------------------------------------------------------
-- BEGINNING OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------
local image, text1, text2, text3, memTimer
-- Touch event listener for background image
local function onSceneTouch( self, event )
if event.phase == "began" then
storyboard.gotoScene( "scene2", "slideLeft", 800 )
return true
end
end
-- Called when the scene's view does not exist:
function scene:createScene( event )
local screenGroup = self.view
image = display.newImage( "bg.jpg" )
screenGroup:insert( image )
image.touch = onSceneTouch
text1 = display.newText( "Scene 1", 0, 0, native.systemFontBold, 24 )
text1:setTextColor( 255 )
text1:setReferencePoint( display.CenterReferencePoint )
text1.x, text1.y = display.contentWidth * 0.5, 50
screenGroup:insert( text1 )
text2 = display.newText( "MemUsage: ", 0, 0, native.systemFont, 16 )
text2:setTextColor( 255 )
text2:setReferencePoint( display.CenterReferencePoint )
text2.x, text2.y = display.contentWidth * 0.5, display.contentHeight * 0.5
screenGroup:insert( text2 )
text3 = display.newText( "Touch to continue.", 0, 0, native.systemFontBold, 18 )
text3:setTextColor( 255 ); text3.isVisible = false
text3:setReferencePoint( display.CenterReferencePoint )
text3.x, text3.y = display.contentWidth * 0.5, display.contentHeight - 100
screenGroup:insert( text3 )
print( "\n1: createScene event")
end
-- Called immediately after scene has moved onscreen:
function scene:enterScene( event )
print( "1: enterScene event" )
-- remove previous scene's view
storyboard.purgeScene( "scene4" )
-- Update Lua memory text display
local showMem = function()
image:addEventListener( "touch", image )
text3.isVisible = true
text2.text = text2.text .. collectgarbage("count")/1000 .. "MB"
text2.x = display.contentWidth * 0.5
end
memTimer = timer.performWithDelay( 1000, showMem, 1 )
end
-- Called when scene is about to move offscreen:
function scene:exitScene( event )
print( "1: exitScene event" )
-- remove touch listener for image
image:removeEventListener( "touch", image )
-- cancel timer
timer.cancel( memTimer ); memTimer = nil;
-- reset label text
text2.text = "MemUsage: "
end
-- Called prior to the removal of scene's "view" (display group)
function scene:destroyScene( event )
print( "((destroying scene 1's view))" )
end
---------------------------------------------------------------------------------
-- END OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------
-- "createScene" event is dispatched if scene's view does not exist
scene:addEventListener( "createScene", scene )
-- "enterScene" event is dispatched whenever scene transition has finished
scene:addEventListener( "enterScene", scene )
-- "exitScene" event is dispatched before next scene's transition begins
scene:addEventListener( "exitScene", scene )
-- "destroyScene" event is dispatched before view is unloaded, which can be
-- automatically unloaded in low memory situations, or explicitly via a call to
-- storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( "destroyScene", scene )
---------------------------------------------------------------------------------
return scene
이 scene1.lua 는 onSceneTouch 함수와 StoryBoard 에 소속된 4개 함수로 구성된 간단한 구조입니다
이 함수 호출은 Storyboard 4인방은 scene:addEventListener 를 사용해서 호출이 되고 onSceneTouch 는 배경이미지에 리스너를 달아서 화면을 터치하면 scene2로 이동하게끔 하는 겁니다.
4인방 메소드에서는 self.view를 이용해서 객체들을 그룹화 하면서 화면에 보여줄 수 있도록 합니다.
처음 createScene 에서는 배경이미지와 텍스트 등 기본 display 요소들을 정의하고 표시합니다.
enterScene 에서는 0.1초 후에 실행되는 타이머를 달아서 showMem 함수를 실행하도록 했습니다.
이 함수는 배경이미지를 터치하면 scene2.lua로 가도록 하는 onSceneTouch 함수를 Call 하는 리스너를 달았고 현재 메모리를 모여주는 로직이 있습니다.
그 이전에 storyboard.purgeScene( "scene4" ) 이 있는데요. purgeScene 은 해당 scene(여기서는 scene4) 에 있는 객체들을 모두 unload 합니다. purge말고 remove를 사용하면 unload 될 뿐만 아니라 메모리에서도 사라집니다.
이 기능은 메모리를 절약하거나 할 때 사용하는 건데 scene1에서 scene2로 넘어 갈때 터미널에 뭐가 찍히는지 보면 잘 알 수 있습니다.
보시다시피 scene1이 시작되면 scene4 의 destroy 가 호출 되서 그 안의 내용이 실행 됩니다.
scene1에서 scene2로 넘어갈 때 destroyScene 함수가 호출되는게 아니라 해당 scene이 unload 될 때 destroyScene 이 호출 됩니다.
그리고 purgeScene 하게 되면 해당 scene 의 destroyScene 이 호출 됩니다.
removeScene 하게 되면 purgeScene 한 후 메모리에서 없애므로 자연히 destroyScene 이 호출 됩니다.
exitScene 은 다음 화면으로 넘어갈 때 실행 되는데 여기서는 모든 리스너를 remove 하고 timer 도 cancel 합니다.
여기까지 하면 실행되는 화면이 아래와 같습니다.
나머지 scene2,scene3,scene4 도 이 scene1과 구조가 동일 합니다.
그런데 여기서 드는 한가지 의문점은 Tab Bar 는 화면 전환에 상관 없이 계속 있는데요.
특정 화면에서 이 TabBar 를 안 보이게 하거나 없애거나 아니면 어떻게 콘트롤을 할 수 있을까요?
그렇게 하려면 main.lua 에서 tabBar 를 local 이 아니라 glabal 변수로 선언하면 됩니다. 그냥 local 이란 글자만 지우세요.
그리고 scene3.lua 맨 밑에 (return scene 바로 윗줄에) tabBar.isVisible = false; 를 넣어보시고. scene4.lua에는 tabBar.isVisible = true 를 넣어보세요.
그러면 이렇게 scene3에는 탭바가 없어지고 scene4에는 나타나게 됩니다.
이런식으로 tabbar를 제어하시면 됩니다.