How do I detect a list is still (roll) Scrolling, when user hits another button to change scenes?

I have a situation (I am sure others have overcome…) in that I have a list view and the list is quite long. The user can ‘scroll’ this list up and down quite fast. While the scrolling is happening the user can/might hit a (settings) button to exit the scene (for example the settings allows user to change the list content, so if the user sees content they do or donot require they can click a settings button to change list content options)

This all works well, except when the button is clicked while the scrolling is still moving (default low friction).

The onRender event fails because the button has/ is in the process of removing the scene and I think that there is now no data to access because it has been ‘purged/killed/nill’ ed by the removescene.

I therefore need a way to communicate between the list events and the button events so they can tell that the list is still moving so don’t removescene until stopped scrolling. I suspect I need to set up a few statemachine settings, but how can I tell when the scrolling has stopping (There is no event.direction property as far as I can tell on listview otherwise maybe event.direction may have helped).

Any suggestions please…

Thanks

Alec

Ref Statemachine…  it would seem possible to enable and disable widgets (display objects) so the buttons can change state depending on user actions to lock out in-appropriate user action/pressing using the isEnabled property, but this still leaves the question How can I tell if the list is still sr (Rolling)?

hi cockle,

since the widget code is open source, you could always modify it to do what you want. :slight_smile: for example, you could dispatch a new event from the table view for ‘isMoving’ with values true/false and watch for that in your code.

but, without doing that, is there a way in the row render function (or where ever it is that you’re getting nil) that you could check to see if the items are still available, either by setting a property or checking for an existing method/function ? for example:

function myOnRender() -- jump out of render method if image\_object == nil then return end ... render code here end

i did something similar to a recent project, i set a custom property ‘isRendered’ on my rows, for example. after they were destroyed i would get ‘nil’ back from a property lookup. (however, i also modified the table view code a bit to better handle rendering, which helped this issue.)
point is, i focused on whether the objects/methods/table still existed as opposed to whether the table was still moving.

also, do you have to kill/purge the scene ? in the same project, we kept scenes around in case we wanted to show them again. we did this so we didn’t have to incur the penalty of re-rendering the entire scene.

cheers,
dmc

Hi dmc,

Thanks for the suggestions (open source eh!. I did not expect to have to take that route at this (st)age, after paying a subscription to Corona. I left all that under the ‘bonnot/hood’ some time ago…

I like your suggestion on a custom property ‘isRendered’. I will take that path as it is quicker. I just wanted to be sure I had not missed a trick like the event.direction on the scrollview (assuming that may have helped).

I am removing the scenes as this is ‘quick and dirty’ to refresh and is no hit on the user response in my app. Also seems a recommended way to keep memory low (http://www.coronalabs.com/blog/coronageek/hangout-highlights-memory-management-tips/) by attaching display objects to the storyboard group (I have noticed some variable still hang around even if local in the ‘top’ section/ part of a coding area of a scene (what is that section called (non-listener area) but I handle that by setting to nil on remove scene…

Thanks again

Alec

 

Hi Alec,

There is an “event.direction” property for both TableView and ScrollView, as shown in the documentation. In a listener function for the widget, you can detect this, along with “event.limitReached” to determine when the view reaches its limit on whatever end.

http://docs.coronalabs.com/api/library/widget/newTableView.html

http://docs.coronalabs.com/api/library/widget/newScrollView.html

Best regards,

Brent

Thanks Brent,

I had read the scrollview section and when I started using tableview (faster in my tests in loading) I just wrote code ‘by experiment’. Tried a listener and in most rows direction reported as nil. However when it reached limits the direction is set either up or down ; isLimitReached still stays as nil.

This is obviously wrong but I am using daily build Version 2013.1138 (2013.6.12) (avoided the 13th ;}…

I can’t believe it is corona (yet), and I checked code so I assumed it was not included. I can see now it is by your response (thanks) so I have a bug in my code I guess that I need to sort…


 

The simple code here shows that output is not as expected.

local function ListMoveDetection(event)
    _G.ui.ListDirection=event.direction
    print( "Event direction ",event.direction )
   print( "Event limit ",event.isLimitReached )
    print ( “Direction”,_G.ui.ListDirection )
end

—output from prints–while scrolling!

Event direction     nil
Event limit     nil
Direction    nil
Event direction     nil
Event limit     nil
Direction    nil

when it hits end limits-------------

Event direction     down
Event limit     nil
Direction    down


Event direction     up
Event limit     nil
Direction    up
 

-------Code for  list definition-----------

 list = widget.newTableView
{
    top = display.statusBarHeight+navBarHeight+SubNavBarHeight+strokeLineHeight*3,
    left=0,
    width = rowWidth,  ----- local variable set elsewhere
    height = listHeight, ---- no mask but is used in code elsewhere and does control the height even doc says it doesnot
    hideBackground = false,
    onRowRender=onRowRender,  — works well
    listener=ListMoveDetection  --code shown above- not giving results as expected

}


Hi dmc,

Thanks for your code example and suggestion.

This has overcome my problem. I  placed this code in all my scenes with a rowrender event (where some action can change scenes)

—WARNING DO NOT REMOVE THIS CODE----==================================
                if row== nil or List ==nil then                          --essential code to avoid crashes due to timing!
                    --print (“Row Nil received”,row.index)
                    return
                end
–=====================================================================

Here is the trace that confirmed the rows being queued to the event after the scene was being removed!!!

Old Scene  - Will exit scene
New  scene - Create scene
Old Scene  - Exit Scene

–here the output from the rowRender event being fired on fast scrolling but see the ROW object has gone!
Row Nil received    1
Row Nil received    2
Row Nil received    3
Row Nil received    4
Row Nil received    5
Row Nil received    6
Row Nil received    7
Row Nil received    8
Row Nil received    9
Row Nil received    10
Row Nil received    11
Row Nil received    12
Row Nil received    13
Row Nil received    14
Row Nil received    15
Row Nil received    16
Old Scene  Destroyed

hey cockle,

fantastic, i’m glad that helped!

i think that this “pattern” is something that is very beneficial when doing asynchronous programming because there’s always a chance that somewhere, at some time, some callback is still waiting to be invoked, but the original view/scene/object which started the flow is no longer available. doing this simple check with a return allows everything to end gracefully.

cheers,
dmc

Ref Statemachine…  it would seem possible to enable and disable widgets (display objects) so the buttons can change state depending on user actions to lock out in-appropriate user action/pressing using the isEnabled property, but this still leaves the question How can I tell if the list is still sr (Rolling)?

hi cockle,

since the widget code is open source, you could always modify it to do what you want. :slight_smile: for example, you could dispatch a new event from the table view for ‘isMoving’ with values true/false and watch for that in your code.

but, without doing that, is there a way in the row render function (or where ever it is that you’re getting nil) that you could check to see if the items are still available, either by setting a property or checking for an existing method/function ? for example:

function myOnRender() -- jump out of render method if image\_object == nil then return end ... render code here end

i did something similar to a recent project, i set a custom property ‘isRendered’ on my rows, for example. after they were destroyed i would get ‘nil’ back from a property lookup. (however, i also modified the table view code a bit to better handle rendering, which helped this issue.)
point is, i focused on whether the objects/methods/table still existed as opposed to whether the table was still moving.

also, do you have to kill/purge the scene ? in the same project, we kept scenes around in case we wanted to show them again. we did this so we didn’t have to incur the penalty of re-rendering the entire scene.

cheers,
dmc

Hi dmc,

Thanks for the suggestions (open source eh!. I did not expect to have to take that route at this (st)age, after paying a subscription to Corona. I left all that under the ‘bonnot/hood’ some time ago…

I like your suggestion on a custom property ‘isRendered’. I will take that path as it is quicker. I just wanted to be sure I had not missed a trick like the event.direction on the scrollview (assuming that may have helped).

I am removing the scenes as this is ‘quick and dirty’ to refresh and is no hit on the user response in my app. Also seems a recommended way to keep memory low (http://www.coronalabs.com/blog/coronageek/hangout-highlights-memory-management-tips/) by attaching display objects to the storyboard group (I have noticed some variable still hang around even if local in the ‘top’ section/ part of a coding area of a scene (what is that section called (non-listener area) but I handle that by setting to nil on remove scene…

Thanks again

Alec

 

Hi Alec,

There is an “event.direction” property for both TableView and ScrollView, as shown in the documentation. In a listener function for the widget, you can detect this, along with “event.limitReached” to determine when the view reaches its limit on whatever end.

http://docs.coronalabs.com/api/library/widget/newTableView.html

http://docs.coronalabs.com/api/library/widget/newScrollView.html

Best regards,

Brent

Thanks Brent,

I had read the scrollview section and when I started using tableview (faster in my tests in loading) I just wrote code ‘by experiment’. Tried a listener and in most rows direction reported as nil. However when it reached limits the direction is set either up or down ; isLimitReached still stays as nil.

This is obviously wrong but I am using daily build Version 2013.1138 (2013.6.12) (avoided the 13th ;}…

I can’t believe it is corona (yet), and I checked code so I assumed it was not included. I can see now it is by your response (thanks) so I have a bug in my code I guess that I need to sort…


 

The simple code here shows that output is not as expected.

local function ListMoveDetection(event)
    _G.ui.ListDirection=event.direction
    print( "Event direction ",event.direction )
   print( "Event limit ",event.isLimitReached )
    print ( “Direction”,_G.ui.ListDirection )
end

—output from prints–while scrolling!

Event direction     nil
Event limit     nil
Direction    nil
Event direction     nil
Event limit     nil
Direction    nil

when it hits end limits-------------

Event direction     down
Event limit     nil
Direction    down


Event direction     up
Event limit     nil
Direction    up
 

-------Code for  list definition-----------

 list = widget.newTableView
{
    top = display.statusBarHeight+navBarHeight+SubNavBarHeight+strokeLineHeight*3,
    left=0,
    width = rowWidth,  ----- local variable set elsewhere
    height = listHeight, ---- no mask but is used in code elsewhere and does control the height even doc says it doesnot
    hideBackground = false,
    onRowRender=onRowRender,  — works well
    listener=ListMoveDetection  --code shown above- not giving results as expected

}


Hi dmc,

Thanks for your code example and suggestion.

This has overcome my problem. I  placed this code in all my scenes with a rowrender event (where some action can change scenes)

—WARNING DO NOT REMOVE THIS CODE----==================================
                if row== nil or List ==nil then                          --essential code to avoid crashes due to timing!
                    --print (“Row Nil received”,row.index)
                    return
                end
–=====================================================================

Here is the trace that confirmed the rows being queued to the event after the scene was being removed!!!

Old Scene  - Will exit scene
New  scene - Create scene
Old Scene  - Exit Scene

–here the output from the rowRender event being fired on fast scrolling but see the ROW object has gone!
Row Nil received    1
Row Nil received    2
Row Nil received    3
Row Nil received    4
Row Nil received    5
Row Nil received    6
Row Nil received    7
Row Nil received    8
Row Nil received    9
Row Nil received    10
Row Nil received    11
Row Nil received    12
Row Nil received    13
Row Nil received    14
Row Nil received    15
Row Nil received    16
Old Scene  Destroyed

hey cockle,

fantastic, i’m glad that helped!

i think that this “pattern” is something that is very beneficial when doing asynchronous programming because there’s always a chance that somewhere, at some time, some callback is still waiting to be invoked, but the original view/scene/object which started the flow is no longer available. doing this simple check with a return allows everything to end gracefully.

cheers,
dmc