Take Focus Not Working Properly in ScrollView

I am really stuck here. I am using take focus to transfer a touch event from a button to the scroll view. This works. However, when I scroll again, the button I last touched has it’s event triggered again (I can see the over imagine changing and the logs), even if I’m not touching the button or touching another button. Scrolling again works once I move enough to trigger the takeFocus function. It sseems like teh oriignal button is holding teh focus. I’ve tried manually triggering the cancelled phase, and playing with the setFocus functions but nothing.  

Things go back to “normal” when I simply click on another button or the background on the scroll view. This seems to somehow stop this strange relationship. If I click on another button when doing his, it doesn’t actually work and I see the over image get triggered on the original button. 

I’ve included a short video of the problem too. 

local buttonsGroup = widget.newScrollView { x = CX, y = CY, width = W, height = H, scrollWidth = W, scrollHeight = H, horizontalScrollDisabled = true, hideBackground = true } group:insert(buttonsGroup) local function onLevelButtonRelease(event) print('buttonPhase' .. event.phase) if event.phase == 'began' then event.target.initialY = event.y elseif event.phase == 'moved' and math.abs(event.target.initialY - event.y) \> 10 then buttonsGroup:takeFocus( event ) elseif event.phase == 'ended' then sounds.play('tap') composer.gotoScene('scenes.reload\_game', {params = event.target.id}) end return true end -- Button positioning is grid based, x,y are grid points local x, y = -2, 0 local spacing = 136 for i = 1, composer.getVariable('levelCount') do local button = widget.newButton({ id = i, label = i, labelColor = {default = {1}, over = {0.5}}, font = native.systemFontBold, fontSize = 50, labelYOffset = -10, defaultFile = 'images/buttons/level.png', overFile = 'images/buttons/level-over.png', width = 128, height = 128, x = x \* spacing + CX, y = 32 + y \* spacing + 87, onEvent = onLevelButtonRelease }) buttonsGroup:insert(button) -- Check if this level was completed if databox['level' .. i] then local check = display.newImageRect('images/check.png', 36, 36) check.anchorX, check.anchorY = 1, 1 check.x, check.y = button.width - 3, button.height - 18 button:insert(check) -- Insert after positioning, because if inserted before, button.width/height will be different end x = x + 1 if x == 3 then x = -2 y = y + 1 end end

Hi @tomekgt,

At an initial glance, I think it has something to do with your setting/usage of “initialY”. Is there a reason you modified the example given in the “takeFocus()” documentation? That routine has been known to work nicely for a long, long time.

https://docs.coronalabs.com/api/type/ScrollViewWidget/takeFocus.html

Take care,

Brent

I still can’t get it working. I’ve taken the example code (which works on it’s own), but when transplanted into a composer scene that loads up, I get the same issue. Should I file a bug report?

Here is the code. If you launch this scene from the main file, You can see the strange behaviour in the log. By scrolling from a button, the button listener keeps firing the next time you scroll, even if it’s outside the button. 

local composer = require('composer') local widget = require('widget') local scene = composer.newScene() function scene:create() local group = self.view local scrollView = widget.newScrollView { top = 100, left = 10, width = 300, height = 400, scrollWidth = 600, scrollHeight = 800, horizontalScrollDisabled = true } group:insert(scrollView) -- The touch listener function for the button (created below) local function handleButtonEvent( event ) print("A BUTTON listener") local phase = event.phase if ( phase == "moved" ) then local dy = math.abs( ( event.y - event.yStart ) ) -- If the touch on the button has moved more than 10 pixels, -- pass focus back to the scroll view so it can continue scrolling if ( dy \> 10 ) then print("TAKEN") scrollView:takeFocus( event ) end elseif ( phase == "ended" ) then print("CLICK A") end return true end local button1 = widget.newButton { left = 100, top = 200, id = "button1", label = "Default A", onEvent = handleButtonEvent } scrollView:insert( button1 ) local function handleButtonEventB( event ) print("B BUTTON listener") local phase = event.phase if ( phase == "moved" ) then local dy = math.abs( ( event.y - event.yStart ) ) -- If the touch on the button has moved more than 10 pixels, -- pass focus back to the scroll view so it can continue scrolling if ( dy \> 10 ) then print("TAKEN") scrollView:takeFocus( event ) end elseif ( phase == "ended" ) then print("CLICK B") end return true end local button2 = widget.newButton { left = 100, top = 300, id = "button2", label = "Default B", onEvent = handleButtonEventB } scrollView:insert( button2 ) end scene:addEventListener('create') return scene

Hi @tomekgt,

Just to confirm, you’re saying that this exact same code, if taken out of the Composer scene and tested directly in a main.lua file, works as you need? But putting it into Composer breaks it?

Brent

Hi @Brent Sorrentino

Yes. I just tested it by placing the code in the main.lua file and works fine. The button listener doesn’t fire in the weird way after scrolling from a button. 

I also discovered the problem. 

If i take out the following line from the main.lua file it works fine:

system.activate('multitouch')

However, is this a bug, or would one need to handle this differently when using multi touch capabilities?

Hi @tomekgt,

Handling multitouch usually takes a little extra code, yes. Can you isolate this down to the most basic example possible (absolutely no Composer implementation), zip it up, and post it here? I’ll take a look and then, if necessary, we can proceed with a bug report.

Thanks,

Brent

Hi @tomekgt,

At an initial glance, I think it has something to do with your setting/usage of “initialY”. Is there a reason you modified the example given in the “takeFocus()” documentation? That routine has been known to work nicely for a long, long time.

https://docs.coronalabs.com/api/type/ScrollViewWidget/takeFocus.html

Take care,

Brent

I still can’t get it working. I’ve taken the example code (which works on it’s own), but when transplanted into a composer scene that loads up, I get the same issue. Should I file a bug report?

Here is the code. If you launch this scene from the main file, You can see the strange behaviour in the log. By scrolling from a button, the button listener keeps firing the next time you scroll, even if it’s outside the button. 

local composer = require('composer') local widget = require('widget') local scene = composer.newScene() function scene:create() local group = self.view local scrollView = widget.newScrollView { top = 100, left = 10, width = 300, height = 400, scrollWidth = 600, scrollHeight = 800, horizontalScrollDisabled = true } group:insert(scrollView) -- The touch listener function for the button (created below) local function handleButtonEvent( event ) print("A BUTTON listener") local phase = event.phase if ( phase == "moved" ) then local dy = math.abs( ( event.y - event.yStart ) ) -- If the touch on the button has moved more than 10 pixels, -- pass focus back to the scroll view so it can continue scrolling if ( dy \> 10 ) then print("TAKEN") scrollView:takeFocus( event ) end elseif ( phase == "ended" ) then print("CLICK A") end return true end local button1 = widget.newButton { left = 100, top = 200, id = "button1", label = "Default A", onEvent = handleButtonEvent } scrollView:insert( button1 ) local function handleButtonEventB( event ) print("B BUTTON listener") local phase = event.phase if ( phase == "moved" ) then local dy = math.abs( ( event.y - event.yStart ) ) -- If the touch on the button has moved more than 10 pixels, -- pass focus back to the scroll view so it can continue scrolling if ( dy \> 10 ) then print("TAKEN") scrollView:takeFocus( event ) end elseif ( phase == "ended" ) then print("CLICK B") end return true end local button2 = widget.newButton { left = 100, top = 300, id = "button2", label = "Default B", onEvent = handleButtonEventB } scrollView:insert( button2 ) end scene:addEventListener('create') return scene

Hi @tomekgt,

Just to confirm, you’re saying that this exact same code, if taken out of the Composer scene and tested directly in a main.lua file, works as you need? But putting it into Composer breaks it?

Brent

Hi @Brent Sorrentino

Yes. I just tested it by placing the code in the main.lua file and works fine. The button listener doesn’t fire in the weird way after scrolling from a button. 

I also discovered the problem. 

If i take out the following line from the main.lua file it works fine:

system.activate('multitouch')

However, is this a bug, or would one need to handle this differently when using multi touch capabilities?

Hi @tomekgt,

Handling multitouch usually takes a little extra code, yes. Can you isolate this down to the most basic example possible (absolutely no Composer implementation), zip it up, and post it here? I’ll take a look and then, if necessary, we can proceed with a bug report.

Thanks,

Brent