I had a problem creating a loading scene in between scenes, the solution I got was to use an overlay, I've been trying this for days but for some reason I can't get it to work. I have two scenes, one that shows a list of items, and another that shows a page of text based on which row was clicked. The problem now is the first scene, that shows the list, downloads images to display and of course this takes a while so whenever i transition into that screen, the app appears to be frozen while everything loads up.
I've found out that it does actually go into the overlay scene, since the print statements i put in it print out, but it just doesn't display anything and when i removed the code that hides the overlay after, it still appears to hang, it goes into the overlay scene, doesn't display anything and then renders the table before finally displaying the overlay so instead of showing an overlay, having everything load up beneath, and then hiding the overlay, it appears to be frozen in the current scene, loads up everything beneath, shows overlay and then hides overlay right after.
My code for the three scenes are below, the one I'm posting now is the only one that actually worked once and then never again, it showed the overlay while everything loaded like I wanted but for some reason, it never worked again after that one time. I'm getting really frustrated with it and no forum has given me a solution, I'd really really appreciate some help. Thanks!
ItemListPage.lua
local composer = require ( "composer" )
local widget = require( "widget" )
local json = require( "json" )
-- Load the relevant LuaSocket modules
local http = require( "socket.http" )
local ltn12 = require( "ltn12" )
local scene = composer.newScene()
--NavigationBar elements initiated
--Removed for readability
--image handler
local function networkListener( event )
if ( event.isError ) then
print ( "Network error - download failed" )
end
print ( "event.response.fullPath: ", event.response.fullPath )
print ( "event.response.filename: ", event.response.filename )
print ( "event.response.baseDirectory: ", event.response.baseDirectory )
end
local function onRowRender( event )
-- Get reference to the row group
local row = event.row
local params=event.row.params
local itemRow=3;
-- Cache the row "contentWidth" and "contentHeight" because the row bounds can change as children objects are added
local rowHeight = row.contentHeight
local rowWidth = row.contentWidth
row.rowTitle = display.newText( row, params.topic, 0, 0, nil, 14 )
row.rowTitle:setFillColor( 0 )
row.rowTitle.anchorX = 0
row.rowTitle.x = 0
row.rowTitle.y = (rowHeight/2) * 0.5
--Other elements removed for readabilty (it's all just text objects)
--Download Image
--params referring to items[i]
local imagelink =params.imagelink
-- Create local file for saving data
local path = system.pathForFile( params.imagename, system.TemporaryDirectory )
myFile = io.open( path, "w+b" )
-- Request remote file and save data to local file
http.request{
url = imagelink,
sink = ltn12.sink.file( myFile )
}
row.Image = display.newImageRect(row, params.imagename, system.TemporaryDirectory, 25, 25)
row.Image.x = 20
row.Image.y = (rowHeight/2) * 1.5
row:insert( row.rowTitle )
row:insert( row.Image )
end
local function onRowTouch( event )
local row = event.target
local params=event.target.params
composer.removeScene(composer.getSceneName("current"))
composer.gotoScene( "itempage" , {params=params})
end
function scene:create( event )
local sceneGroup = self.view
end
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if phase == "will" then
-- Called when the scene is still off screen and is about to move on screen
--overlay
composer.showOverlay( "loading", { isModal = true })
elseif phase == "did" then
--Table stuff
local scrollBarOptions = {
sheet = scrollBarSheet, -- Reference to the image sheet
topFrame = 1, -- Number of the "top" frame
middleFrame = 2, -- Number of the "middle" frame
bottomFrame = 3 -- Number of the "bottom" frame
}
-- Table
local tableView = widget.newTableView(
{
left = 0,
top = navBar.height,
height = display.contentHeight-navBar.height,
width = display.contentWidth,
onRowRender = onRowRender,
onRowTouch = onRowTouch,
listener = scrollListener
}
)
--json work
local filename = system.pathForFile( "items.json", system.ResourceDirectory )
local decoded, pos, msg = json.decodeFile( filename )
if not decoded then
print( "Decode failed at "..tostring(pos)..": "..tostring(msg) )
else
print( "File successfully decoded!" )
end
local items=decoded.items
-- create a white background to fill screen
local background = display.newRect( display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight )
background:setFillColor( 1 ) -- white
sceneGroup:insert( background )
-- Insert rows
for i = 1, #items do
-- Insert a row into the tableView
print( "Adding a row!" )
tableView:insertRow{
rowHeight = 100,
rowColor = { default={ 0.8, 0.8, 0.8, 0.8 } },
lineColor = { 1, 0, 0 },
params=items[i]
}
end
sceneGroup:insert( tableView )
composer.hideOverlay( "fade", 100 )
end
end
-- other functions and elements unused and removed for readability
loading.lua
local composer = require ( "composer" )
local widget = require( "widget" )
local json = require( "json" )
local scene = composer.newScene()
-- Create the widget
function scene:create( event )
local sceneGroup = self.view
local background = display.newRect( display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight )
background:setFillColor( 1 ) -- white
local text = display.newText( "Loading scene", 0, 0, nil, 14 )
text:setFillColor( 0 )
text.anchorX = display.contentCenterX
text.x = display.contentCenterX
text.y = display.contentCenterY
sceneGroup:insert( background )
sceneGroup:insert( text )
print ( "In loading create")
end
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if phase == "will" then
elseif phase == "did" then
print ( "In loading show")
end
end
-- other functions and elements unused and removed for readability
ItemDisplayPage.lua
local composer = require ( "composer" )
local widget = require( "widget" )
local json = require( "json" )
local scene = composer.newScene()
--NavigationBar elements initiated
--This creates the "back button", when clicked it returns to the previous scene, in this case "itemListPage"
--it takes, no parameters
local function handleLeftButton( event )
if ( event.phase == "ended" ) then
composer.removeScene(composer.getSceneName("current"))
composer.gotoScene(composer.getSceneName("previous"))
end
return true
end
--Remaining navbar elements removed for readability
function scene:create( event )
local sceneGroup = self.view
local params=event.params
-- create a white background to fill screen
local background = display.newRect( display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight )
background:setFillColor( 1 ) -- white
--creating header bar
local bar = display.newRect( navBar.height + (headerBarHeight*0.5), display.contentCenterY, display.contentWidth, headerBarHeight )
bar:setFillColor( 1 )
-- create stuff
local title = display.newText(params.topic, 0, 0, nil, 14 )
title:setFillColor( 0 )
title.anchorX = 0
title.x = margin
title.y = ((2*headerBarHeight/2) * 0.5)+navBar.height
local Image = display.newImageRect(params.imagename, system.TemporaryDirectory, 25, 25)
Image.x = 50
Image.y = display.contentCenterY
-- all objects must be added to group (e.g. self.view)
sceneGroup:insert( background )
sceneGroup:insert( title )
sceneGroup:insert( Image)
end
-- other functions and elements unused and removed for readability
I suggest you do not use scene.show event for loading.
Use timer.performWithDelay
to load all data:
--in scene:show
elseif phase == "did" then
timer.performWithDelay(0, function()
local scrollBarOptions = {
--put your code here
composer.hideOverlay( "fade", 100 )
end)
Your current code didn't show overlay because engine waits for scene:show event before rendering anything. So rendering of overlay and images occured after all images are loaded.
In my code timer.performWithDelay
doesn't block scene:show
execution, so you will see overlay rendered before loading images