widget.newTableView: insertRow() does not lead to a onRowRender()

I have two lists (widget.newTableView). When an item is selected in one list, the other is to b repopulated by the proper sub items.

This works well except for one case. When entering the screen with the two lists they should be populated with default stores values and selections. I’ll leave the selection part out now, because the problems start before that.

In the attached example I have two simple lists; one is filled at creation time. The other is to be dynamically filled as the selection changes in the first list so it cannot be filled at creation time.

Thus at scene:show I fill the sub table with the proper set of items.

In the real app I do this with real data, but in the attached example I’ve made it as simplified as possible while the problem still arises, so I just fill the sub table with the same 5 items nomatter what appens to the “supe” table.

The problem is that at scene:show, the insertRow() does NOT lead to a onRowRender for the tableView and consequently it’s not being visible populated.

Meanwhile, if I press an item in the “super” table I, the subTable populates perfectly. I call the exact same function fillSubListTable() in both scene:show and in the onRowTouch for the “super” table.

Why doesn’t the insertRow() lead to a call to onRowRender() when called from scene:show?

The followin is the complete code. I would have attached it along with the main.lua file, but I cannot attach anything anymore to this forum it seems.

local composer = require("composer") local widget = require("widget") local scene = composer.newScene() local sceneGroup = nil local listTable = nil local subListTable = nil local function fillSubListTable() subListTable:deleteAllRows() for i = 1, 5 do print("Adding row to subListTable") subListTable:insertRow{rowHeight=60} end end local function listOnRowRender( event ) local row = event.row local rowHeight = row.contentHeight local rowWidth = row.contentWidth local rowText = display.newText(row, row.index, 0, 0, nil, 36) rowText:setFillColor( 0 ) rowText.anchorX = 0 rowText.x = rowWidth \* 0.02 rowText.y = rowHeight \* 0.5 end local function listOnRowTouch( event ) if (event.phase == "release") then fillSubListTable() end end local function subListOnRowRender( event ) print("subListOnRowRender") local row = event.row local rowHeight = row.contentHeight local rowWidth = row.contentWidth local rowText = display.newText(row, row.index, 0, 0, nil, 36 ) rowText:setFillColor( 0 ) rowText.anchorX = 0 rowText.x = 0 rowText.y = rowHeight \* 0.5 end local function subListOnRowTouch(event) end function scene:create( event ) sceneGroup = self.view -- List TableView listTable = widget.newTableView { x = \_W\*0.05, y = \_H\*0.5, height = \_H\*0.28, width = \_W\*0.43, onRowRender = listOnRowRender, onRowTouch = listOnRowTouch, } listTable.anchorX = 0.0 listTable.busy = false for i = 1, 5 do listTable:insertRow{rowHeight=60} end sceneGroup:insert(listTable) -- Sub List TableView subListTable = widget.newTableView { x = \_W\*0.95, y = \_H\*0.5, height = \_H\*0.28, width = \_W\*0.43, onRowRender = subListOnRowRender, onRowTouch = subListOnRowTouch, } subListTable.anchorX = 1.0 sceneGroup:insert(subListTable) end -- "scene:show()" function scene:show( event ) sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then fillSubListTable() elseif ( phase == "did" ) then end end -- "scene:hide()" function scene:hide( event ) sceneGroup = self.view local phase = event.phase end -- "scene:destroy()" function scene:destroy( event ) sceneGroup = self.view end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) return scene

You will only get onRowRender() events for rows that are on screen.  If your table shows 10 rows, you should get onRowRender() calls for rows 1-10 but 11 being off screen won’t be rendered yet (well we may rendered a couple of off screen rows for performance reasons).

Rob

Hmm… yes, this I know already. But it suddenly occured to me that I’ve been trying to add the rows in the “will” phase of scene:show. This is before anything is drawn, right?

So that moving the code to the “did” phase might fix things then? I’ll try as soon as I get to my computer.

Given that one would expect you to do this in the create event and the objects can be created off screen, I don’t think that will matter.

Rob

Well, moving fillSubListTable() to the “did” phase did make wonders and now things work at expected!

So thanks!


There’s another thing, though, with widget.newTableView() that I do not understand and that is the behaviour of scrollToIndex().

I have a tableView that is 5 rows high. The content is dynamic (the sub table from above). The table could hold 2 items, or 20.

To show a selection, I write the row text in a different color, and to make sure the selected row is visible by calling scrollToIndex() with the index of the row as the parameter.

But if the number of rows is 2 and the selected item is the last (index=2) a call to scrollToIndex(2) results in the two rows being drawn at the bottom of the tableView. A tuch (anywhere) in the tableView moves the two rows to the top where they belong.

  1. Is this a bug in scrollToIndex() ?

  2. Is there a way to call scrollToIndex() to avoid this strange behaviour ?

Do I have to find out if the number of rows is larger than the visible area and only then call scrollToIndex()? Isn’t this something that scrollToIndex() should fix internally?

  

You will only get onRowRender() events for rows that are on screen.  If your table shows 10 rows, you should get onRowRender() calls for rows 1-10 but 11 being off screen won’t be rendered yet (well we may rendered a couple of off screen rows for performance reasons).

Rob

Hmm… yes, this I know already. But it suddenly occured to me that I’ve been trying to add the rows in the “will” phase of scene:show. This is before anything is drawn, right?

So that moving the code to the “did” phase might fix things then? I’ll try as soon as I get to my computer.

Given that one would expect you to do this in the create event and the objects can be created off screen, I don’t think that will matter.

Rob

Well, moving fillSubListTable() to the “did” phase did make wonders and now things work at expected!

So thanks!


There’s another thing, though, with widget.newTableView() that I do not understand and that is the behaviour of scrollToIndex().

I have a tableView that is 5 rows high. The content is dynamic (the sub table from above). The table could hold 2 items, or 20.

To show a selection, I write the row text in a different color, and to make sure the selected row is visible by calling scrollToIndex() with the index of the row as the parameter.

But if the number of rows is 2 and the selected item is the last (index=2) a call to scrollToIndex(2) results in the two rows being drawn at the bottom of the tableView. A tuch (anywhere) in the tableView moves the two rows to the top where they belong.

  1. Is this a bug in scrollToIndex() ?

  2. Is there a way to call scrollToIndex() to avoid this strange behaviour ?

Do I have to find out if the number of rows is larger than the visible area and only then call scrollToIndex()? Isn’t this something that scrollToIndex() should fix internally?