Stop object dragging where its overlapped by another object

So I have an image thats a map which is wider than my screen. The map has a touch listener on it so I can drag it around.

I have an image across the top and bottom - like a header and footer, which are drawn on top of the map.

There is a touch event listener on the header image also which acts as a button.

However if I touch on those where the map would be underneath and drag I can drag the map.

How do I stop this from happening?

print("cork") local leftSide = display.screenOriginX; local rightSide = display.contentWidth-display.screenOriginX; local topSide = display.screenOriginY; local bottomSide = display.contentHeight-display.screenOriginY; --------------------------------------------------------------------------------------- local composer = require "composer" local scene = composer.newScene() local widget = require "widget" math.randomseed(os.time()) local function btnTouch( event ) if event.phase == "ended" then print ("button pressed") composer.gotoScene(event.target.btnDestination, {time=250, effect="crossFade"}) return true end end local function locationTouch( event ) if event.phase == "ended" then print (myCurrentImage.currentImageIndex) if myCurrentImage.currentImageIndex == 1 then composer.gotoScene("Cork.location1", {time=250, effect="crossFade"}) end if myCurrentImage.currentImageIndex == 2 then composer.gotoScene("Cork.location2", {time=250, effect="crossFade"}) end if myCurrentImage.currentImageIndex == 3 then composer.gotoScene("Cork.location3", {time=250, effect="crossFade"}) end if myCurrentImage.currentImageIndex == 4 then composer.gotoScene("Cork.location4", {time=250, effect="crossFade"}) end if myCurrentImage.currentImageIndex == 5 then composer.gotoScene("Cork.location5", {time=250, effect="crossFade"}) end if myCurrentImage.currentImageIndex == 6 then composer.gotoScene("Cork.location6", {time=250, effect="crossFade"}) end if myCurrentImage.currentImageIndex == 7 then composer.gotoScene("Cork.location7", {time=250, effect="crossFade"}) end return true end end -- Called when the scene's view does not exist: function scene:create( event ) local sceneGroup = self.view local map = display.newImageRect("images/corkMap.jpg", 792, 560) map.x = display.contentCenterX map.y = display.contentCenterY sceneGroup:insert( map ) local Footerbg = display.newImageRect("images/footerbg.jpg", 360, 60) Footerbg.x = display.contentCenterX Footerbg.y = bottomSide -30 sceneGroup:insert( Footerbg ) -- code to slide through locations -- myImages = {"images/Cork/location1.jpg", "images/Cork/location2.jpg", "images/Cork/location3.jpg", "images/Cork/location4.jpg", "images/Cork/location5.jpg", "images/Cork/location6.jpg", "images/Cork/location7.jpg" } -- name of images currentImageIndex = 1 -- this is index to track your current image -- display the first image myCurrentImage = display.newImageRect( myImages[1],240,60) myCurrentImage.x = display.contentCenterX myCurrentImage.y = bottomSide -30 myCurrentImage.currentImageIndex = 1 sceneGroup:insert( myCurrentImage ) myCurrentImage:addEventListener( "touch", locationTouch ) -- Function to handle back and forward buttons local function handleButtonEvent( event ) if ( "ended" == event.phase ) then if event.target.id == "back" and currentImageIndex \> 1 then print( "Back" ) myCurrentImage:removeSelf() myCurrentImage = nil myCurrentImage = display.newImage( myImages[currentImageIndex - 1]) myCurrentImage.x = display.contentCenterX myCurrentImage.y = bottomSide -30 sceneGroup:insert( myCurrentImage ) arrowLeft:toFront() arrowRight:toFront() currentImageIndex = currentImageIndex - 1 myCurrentImage.currentImageIndex = currentImageIndex myCurrentImage:addEventListener( "touch", locationTouch ) elseif event.target.id == "fwd" and currentImageIndex \< 7 then print( "fwd" ) myCurrentImage:removeSelf() myCurrentImage = nil myCurrentImage = display.newImage( myImages[currentImageIndex + 1]) myCurrentImage.x = display.contentCenterX myCurrentImage.y = bottomSide -30 sceneGroup:insert( myCurrentImage ) arrowLeft:toFront() arrowRight:toFront() currentImageIndex = currentImageIndex + 1 myCurrentImage.currentImageIndex = currentImageIndex myCurrentImage:addEventListener( "touch", locationTouch ) end return true end end local backBtn = display.newImageRect("images/button\_cork.jpg", 360, 40) backBtn.x = display.contentCenterX backBtn.y = display.screenOriginY+20; backBtn.btnDestination = "Scene1" backBtn:addEventListener( "touch", btnTouch ) sceneGroup:insert( backBtn ) -- drag map function -- local function moveMap( event ) xMax = leftSide + map.width/2 ; xMin = rightSide - map.width/2 ; yMax = topSide + map.height/2 + backBtn.height; yMin = bottomSide - (map.height/2+ Footerbg.height); local t = event.target local phase = event.phase if "began" == phase then t.isFocus = true -- Store initial touch position on the actual object - prevents jumping when touched t.xStart = event.x - t.x t.yStart = event.y - t.y elseif t.isFocus then if "moved" == phase then print( display.actualContentWidth ) print("posx:"..t.x) print("xMin:"..xMin) print("xMax:"..xMax) print("pos:"..t.y) print("yMin:"..yMin) print("yMax"..yMax) t.x = event.x - t.xStart t.y = event.y - t.yStart if (t.x \> xMax) then t.x = xMax end if (t.x \< xMin) then t.x = xMin end if (t.y \> yMax) then t.y = yMax end if (t.y \< yMin) then t.y = yMin end elseif "ended" == phase or "cancelled" == phase then t.isFocus = false end end --This tells the system that the event -- should not be propagated to listeners of any objects underneath. return true end -- end of drag map function -- map:addEventListener( "touch", moveMap ) arrowLeft = display.newImageRect("images/arrowLeft.png", 12, 21) arrowLeft.x = display.screenOriginX+20 arrowLeft.y = bottomSide -30 arrowLeft:toFront( ) arrowLeft.id = "back" arrowLeft:addEventListener( "touch", handleButtonEvent ) sceneGroup:insert( arrowLeft ) arrowRight = display.newImageRect("images/arrowRight.png", 12, 21) arrowRight.x = display.contentWidth-display.screenOriginX -20; arrowRight.y = bottomSide -30 arrowRight:toFront( ) arrowRight.id = "fwd" arrowRight:addEventListener( "touch", handleButtonEvent ) sceneGroup:insert( arrowRight ) end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if "did" == phase then print( "1: show event, phase did" ) local sceneName = composer.getSceneName( "previous" ) if sceneName ~= nil then composer.removeScene( sceneName, true ) end end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if "will" == phase then print( "1: hide event, phase will" ) -- remove touch listener for image --audioBtn:removeEventListener( "touch", myAudio ) --back:removeEventListener( "touch", btnTouch ) -- remove audio audio.stop() audio.dispose( audioSound ) audioSound = nil -- cancel timer -- timer.cancel( memTimer ); memTimer = nil; end end function scene:destroy( event ) print( "((destroying scene 1's view))" ) local sceneGroup = self.view end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) --------------------------------------------------------------------------------- return scene

In your btnTouch handler, you are only returning true in the ended phase, so the touch can propagate down in the began and moved phases. Just add another return true at the end of the function.

Thanks that worked. One other issue from it.

The footer is made up of some different images.

a footer image - no touch event listener

and then on top of that a png with an event listener thats not the full width of the footer.

On the footer image I can still go through it and move the map - how do I stop it on this one as there is no function attached to it.

Can’t you just put the event listener on the back footer image? If that’s not adequate for some reason, you could just add a separate listener onto it and just have it return true.

Yeah of course I can just put one with return true on it - bit of a brain fart there.

Cheers

In your btnTouch handler, you are only returning true in the ended phase, so the touch can propagate down in the began and moved phases. Just add another return true at the end of the function.

Thanks that worked. One other issue from it.

The footer is made up of some different images.

a footer image - no touch event listener

and then on top of that a png with an event listener thats not the full width of the footer.

On the footer image I can still go through it and move the map - how do I stop it on this one as there is no function attached to it.

Can’t you just put the event listener on the back footer image? If that’s not adequate for some reason, you could just add a separate listener onto it and just have it return true.

Yeah of course I can just put one with return true on it - bit of a brain fart there.

Cheers