I am seeing a new problem with build 3135 with modal overlays and overlay transition effects.
Scenario:
scene1 has an image with touch listener. when touched, it shows overlay1 (isModal=true, effect=“crossFade”, time=500)
overlay 1 has two buttons:
-
Green button calls hideOverlay (effect=“crossFade”, time=500) and then shows overlay2 (isModal=true, effect=“crossFade”, time=500)
-
Red button calls hideOverlay (effect=“crossFade”, time=500)
overlay 2 has one Blue button, which calls hideOverlay(effect=“crossFade”, time=500) and then shows overlay1 (isModal=true, effect=“crossFade”, time=500)
The problem that is occurring is that when all the modal overlays are shown and then eventually hidden, the original parent scene is not receiving touch events.
Steps to reproduce:
- tap image
- overlay1 is shown
- tap green button
- overlay2 is shown
- tap blue button
- overlay1 is shown
- tap red button
- all overlays are hidden
- tap image
- touch events do not occur
The problem appears to be a regression caused by the fix for the issue described here:
The problem does not occur on build 3118, but does occur on 3119 and 3135.
Project files are below. “world.png” image was taken from the HelloWorld sample.
main.lua
local composer = require("composer") composer.gotoScene( "scene1" )
scene1.lua
local composer = require( "composer" ) local scene = composer.newScene() -- ----------------------------------------------------------------------------------- -- Code outside of the scene event functions below will only be executed ONCE unless -- the scene is removed entirely (not recycled) via "composer.removeScene()" -- ----------------------------------------------------------------------------------- local helpText = nil function worldTouched( self, event ) if ( event.phase == "began" ) then print( "Touch event began on: " .. self.id ) -- Set touch focus display.getCurrentStage():setFocus( self ) self.isFocus = true elseif ( self.isFocus ) then if ( event.phase == "moved" ) then --print( "Moved phase of touch event detected." ) elseif ( event.phase == "ended" or event.phase == "cancelled" ) then print("Touch event ended on: " .. self.id) scene:showOverlay1() -- Reset touch focus display.getCurrentStage():setFocus( nil ) self.isFocus = nil end end return true end function scene:showOverlay1() helpText.isVisible = false composer.hideOverlay( "crossFade", 500) local options = { parent = sceneGroup, isModal = true, effect = "crossFade", time = 500 } composer.showOverlay( "overlay1", options ) end function scene:showHelpText() helpText.isVisible = true end -- ----------------------------------------------------------------------------------- -- Scene event functions -- ----------------------------------------------------------------------------------- -- create() function scene:create( event ) local sceneGroup = self.view -- Code here runs when the scene is first created but has not yet appeared on screen local world = display.newImageRect(sceneGroup, "world.png", system.ResourceDirectory, 250, 250) world.x = display.contentCenterX world.y = display.contentCenterY world.id = "world" world.touch = worldTouched world:addEventListener("touch") local textOpts = { parent = sceneGroup, x = display.contentCenterX, y = 30, text = "Tap the world to show overlay 1", font = native.systemFont, fontSize = 18 } helpText = display.newText( textOpts ) end -- show() function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Code here runs when the scene is still off screen (but is about to come on screen) scene:showOverlay1() elseif ( phase == "did" ) then -- Code here runs when the scene is entirely on screen end end -- hide() function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Code here runs when the scene is on screen (but is about to go off screen) elseif ( phase == "did" ) then -- Code here runs immediately after the scene goes entirely off screen end end -- destroy() function scene:destroy( event ) local sceneGroup = self.view -- Code here runs prior to the removal of scene's view world:removeEventListener("touch") o1Button:removeEventListener("touch") end -- ----------------------------------------------------------------------------------- -- Scene event function listeners -- ----------------------------------------------------------------------------------- scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) -- ----------------------------------------------------------------------------------- return scene
overlay1.lua
local composer = require( "composer" ) local scene = composer.newScene() -- ----------------------------------------------------------------------------------- -- Code outside of the scene event functions below will only be executed ONCE unless -- the scene is removed entirely (not recycled) via "composer.removeScene()" -- ----------------------------------------------------------------------------------- local overlayParent = nil function ButtonTouched( self, event ) if ( event.phase == "began" ) then print( "Touch event began on: " .. self.id ) -- Set touch focus display.getCurrentStage():setFocus( self ) self.isFocus = true elseif ( self.isFocus ) then if ( event.phase == "moved" ) then --print( "Moved phase of touch event detected." ) elseif ( event.phase == "ended" or event.phase == "cancelled" ) then print( "Touch event ended on: " .. self.id ) if ( self.action ) then self.action() end -- Reset touch focus display.getCurrentStage():setFocus( nil ) self.isFocus = nil end end return true end function Button1Action() composer.hideOverlay("crossFade", 500) local options = { parent = sceneGroup, isModal = true, effect = "crossFade", time = 500 } composer.showOverlay("overlay2", options) end function Button2Action() composer.hideOverlay("crossFade", 500) overlayParent:showHelpText() end -- ----------------------------------------------------------------------------------- -- Scene event functions -- ----------------------------------------------------------------------------------- -- create() function scene:create( event ) local sceneGroup = self.view -- Code here runs when the scene is first created but has not yet appeared on screen local textOpts = { parent = sceneGroup, text = "This is overlay 1", x = display.contentCenterX, y = 30, font = native.systemFont, fontSize = 18 } local o1Text = display.newText(textOpts) local o1Button = display.newCircle(sceneGroup, 30, 30, 20) o1Button:setFillColor(0, 1, 0, 1) o1Button.id = "ShowOverlay2Button" o1Button.touch = ButtonTouched o1Button.action = Button1Action o1Button:addEventListener("touch") local o2Button = display.newCircle(sceneGroup, display.contentWidth - 30, 30, 20) o2Button:setFillColor(1, 0, 0, 1) o2Button.id = "HideOverlayButton" o2Button.touch = ButtonTouched o2Button.action = Button2Action o2Button:addEventListener("touch") end -- show() function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Code here runs when the scene is still off screen (but is about to come on screen) overlayParent = event.parent elseif ( phase == "did" ) then -- Code here runs when the scene is entirely on screen end end -- hide() function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Code here runs when the scene is on screen (but is about to go off screen) elseif ( phase == "did" ) then -- Code here runs immediately after the scene goes entirely off screen end end -- destroy() function scene:destroy( event ) local sceneGroup = self.view -- Code here runs prior to the removal of scene's view end -- ----------------------------------------------------------------------------------- -- Scene event function listeners -- ----------------------------------------------------------------------------------- scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) -- ----------------------------------------------------------------------------------- return scene
overlay2.lua
local composer = require( "composer" ) local scene = composer.newScene() -- ----------------------------------------------------------------------------------- -- Code outside of the scene event functions below will only be executed ONCE unless -- the scene is removed entirely (not recycled) via "composer.removeScene()" -- ----------------------------------------------------------------------------------- local overlayParent = nil function ButtonTouched( self, event ) if ( event.phase == "began" ) then print( "Touch event began on: " .. self.id ) -- Set touch focus display.getCurrentStage():setFocus( self ) self.isFocus = true elseif ( self.isFocus ) then if ( event.phase == "moved" ) then --print( "Moved phase of touch event detected." ) elseif ( event.phase == "ended" or event.phase == "cancelled" ) then print( "Touch event ended on: " .. self.id ) if ( self.action ) then self.action() end -- Reset touch focus display.getCurrentStage():setFocus( nil ) self.isFocus = nil end end return true end function Button1Action() composer.hideOverlay("crossFade", 500) overlayParent:showOverlay1() end -- ----------------------------------------------------------------------------------- -- Scene event functions -- ----------------------------------------------------------------------------------- -- create() function scene:create( event ) local sceneGroup = self.view -- Code here runs when the scene is first created but has not yet appeared on screen local textOpts = { parent = sceneGroup, text = "This is overlay 2", x = display.contentCenterX, y = 30, font = native.systemFont, fontSize = 18 } local o1Text = display.newText(textOpts) local o1Button = display.newCircle(sceneGroup, 30, 30, 20) o1Button:setFillColor(0, 0, 1, 1) o1Button.id = "HideOverlay2Button" o1Button.touch = ButtonTouched o1Button.action = Button1Action o1Button:addEventListener("touch") end -- show() function scene:show( event ) local sceneGroup = self.view local phase = event.phase overlayParent = event.parent if ( phase == "will" ) then -- Code here runs when the scene is still off screen (but is about to come on screen) elseif ( phase == "did" ) then -- Code here runs when the scene is entirely on screen end end -- hide() function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Code here runs when the scene is on screen (but is about to go off screen) elseif ( phase == "did" ) then -- Code here runs immediately after the scene goes entirely off screen end end -- destroy() function scene:destroy( event ) local sceneGroup = self.view -- Code here runs prior to the removal of scene's view end -- ----------------------------------------------------------------------------------- -- Scene event function listeners -- ----------------------------------------------------------------------------------- scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) -- ----------------------------------------------------------------------------------- return scene