TableView contents deleting when scroll out of screen

----------------------------------------------------------------------------------------- -- -- club.lua -- ----------------------------------------------------------------------------------------- local globalData = require( "globalData" ) local widget = require( "widget" ) local json = require( "json" ) local composer = require( "composer" ) local scene = composer.newScene() composer.recycleOnSceneChange = true local background -- sfondo scena local sceneGroup -- elementi della scena local elenco --elenco clubs local tableView local index = 0 -- per indicizzare i club ricevuti local swipeSpeed = 10 local club\_id -- id club dalla riga della lista local options = { effect = "fade", time = 400, params = {} } networkListener = function( event ) if ( event.isError ) then print( "Network error - download failed: ", event.response ) elseif ( event.phase == "ended" ) then next() end end onComplete = function() -- Insert clubs for i = 1, #elenco do -- Insert a row into the tableView index = i tableView:insertRow{ rowHeight = 75 } end sceneGroup:insert( tableView ) end next = function() index = index + 1 if index \> #elenco then onComplete() return end local params = {} params.progress = true if elenco[index].logo ~= "" then network.download( "http://codelessfuture9892.cloudapp.net/download/" .. elenco[index].logo, "GET", networkListener, params, elenco[index].logo, system.TemporaryDirectory ) else next() end end local function onRowRender( event ) -- Get reference to the row group local row = event.row -- Cache the row "contentWidth" and "contentHeight" because the row bounds can change as children objects are added local rowHeight = row.contentHeight local rowWidth = row.contentWidth local rowTitle = display.newText( row, elenco[index].nome, 0, 20, native.systemFontBold, 18 ) rowTitle:setFillColor( 0 ) local rowAddress = display.newText( row, elenco[index].indirizzo, 0, 50, native.systemFont, 14 ) rowAddress:setFillColor( 0 ) if elenco[index].logo ~= "" then local rowLogo = display.newImageRect( row, elenco[index].logo, system.TemporaryDirectory, 70, 70 ) rowLogo.anchorX = 0 rowLogo.x = 0 rowLogo.y = 35 end rowTitle.anchorX = 0 rowAddress.anchorX = 0 rowTitle.x = 75 rowAddress.x = 75 end local function handleCouponsResponse( event ) if not event.isError then local response = json.decode( event.response ) if response.status == "OK" then h = #response.data table.insert(options.params, { id = elenco[club\_id].id, nome = elenco[club\_id].nome, descrizione = elenco[club\_id].descrizione, logo = elenco[club\_id].logo, immagine = elenco[club\_id].immagine, telefono = elenco[club\_id].telefono, email = elenco[club\_id].email, indirizzo= elenco[club\_id].indirizzo }) for i=1,h do table.insert(globalData.coupons, { id = response.data[i].id, nome = response.data[i].nome, descrizione = response.data[i].descrizione, condizioni = response.data[i].condizioni, quantita = response.data[i].quantita }) end end else print( "Error!" ) end return end local function goCoupons( event ) composer.gotoScene( "coupons", options ) end local function onRowTouch( event) if ( ("release" == event.phase) or ("tap" == event.phase) ) then local clickChannel = audio.play( globalData.clickSound ) local row = event.row globalData.coupons = {} club\_id = row.id network.request( "http://codelessfuture9892.cloudapp.net/api/coupons\_golfclub/" .. elenco[row.id].id , "GET", handleCouponsResponse ) timer.performWithDelay( 400, goCoupons ) end end function scene:create( event ) sceneGroup = self.view -- Called when the scene's view does not exist. -- -- INSERT code here to initialize the scene -- e.g. add display objects to 'sceneGroup', add touch listeners, etc. elenco = globalData.golfClubs -- Sfondo background = display.newRect( display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight ) background:setFillColor( 1 ) -- white tableView = widget.newTableView( { left = display.screenOriginX, top = display.screenOriginY + 25, height = display.contentHeight - 40, width = display.contentWidth, onRowRender = onRowRender, onRowTouch = onRowTouch, listener = scrollListener }) sceneGroup:insert(background) sceneGroup:insert(tableView) next() end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if phase == "will" then elseif phase == "did" then -- Called when the scene is now on screen -- -- INSERT code here to make the scene come alive -- e.g. start timers, begin animation, play audio, etc. end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if event.phase == "will" then -- Called when the scene is on screen and is about to move off screen -- -- INSERT code here to pause the scene -- e.g. stop timers, stop animation, unload sounds, etc.) elseif phase == "did" then -- Called when the scene is now off screen end end function scene:destroy( event ) local sceneGroup = self.view -- Called prior to the removal of scene's "view" (sceneGroup) -- -- INSERT code here to cleanup the scene -- e.g. remove display objects, remove touch listeners, save state, etc. end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) ----------------------------------------------------------------------------------------- return scene

Also here

local globalData = require( "globalData" ) local widget = require( "widget" ) local json = require( "json" ) local composer = require( "composer" ) local scene = composer.newScene() composer.recycleOnSceneChange = true local sceneGroup -- elementi della scena local elenco --elenco clubs local index = 0 local indice = 0 -- per TableView row local righe = {} -- per TableView row local background -- sfondo scena local golfClub -- nome club local summary -- descrizione local telefono local email local indirizzo local immagine local tableView local riga = {} -- per comporre TableView complessa itinerari / coupon local position = 15 -- posizione Y per elementi in TableView elenco = globalData.coupons handleItinerariResponse = function( event ) if not event.isError then local response = json.decode( event.response ) if response.status == "OK" then h = #response.data elenco[index].itinerari = {} for i=1,h do table.insert(elenco[index].itinerari, { id = response.data[i].itinerari.id, nome = response.data[i].itinerari.nome, descrizione = response.data[i].itinerari.descrizione, listino = response.data[i].itinerari.listino, validita = response.data[i].itinerari.validita }) -- print( elenco[index].nome .. " \> " .. elenco[index].itinerari[i].nome ) end next() end else print( "Error!" ) end return end local function networkListener( event ) if ( event.isError ) then print( "Network error - download failed: ", event.response ) elseif ( event.phase == "began" ) then print( "Progress Phase: began" ) elseif ( event.phase == "ended" ) then immagine = display.newImageRect( event.response.filename, event.response.baseDirectory, display.actualContentWidth, 150 ) immagine.x = display.contentCenterX immagine.y = 170 immagine.alpha = 0 transition.to( immagine, { alpha=1.0 } ) sceneGroup:insert( immagine ) end end function scene:create( event ) sceneGroup = self.view -- Sfondo background = display.newRect( display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight ) background:setFillColor( 1 ) -- white local club = event.params[1] -- create some text local carattere if string.len(club.nome) \> 20 then carattere = 24 else carattere = 32 end golfClub = display.newText(club.nome, display.contentCenterX, 25, native.systemFontBold, carattere ) golfClub:setFillColor( 0 ) -- black local newTextParams = { text = club.descrizione, x = display.contentCenterX, y = 80, width = 300, height = 50, font = native.systemFont, fontSize = 14, align = "center" } summary = display.newText( newTextParams ) summary:setFillColor( 0 ) -- black -- campo indirizzo if string.len(club.indirizzo) \> 40 then carattere = 12 else carattere = 14 end indirizzo = display.newText( "Indirizzo: " .. club.indirizzo, display.contentCenterX, 260, native.systemFont, carattere ) indirizzo:setFillColor( 0.3 ) -- grey -- campo telefono if club.telefono == nil then club.telefono = "" end telefono = display.newText( "Telefono: " .. club.telefono, display.contentCenterX, 280, native.systemFont, 14 ) telefono:setFillColor( 0.3 ) -- grey -- campo email if club.email == nil then club.email = "" end email = display.newText( "Email: " .. club.email, display.contentCenterX, 300, native.systemFont, 14 ) email:setFillColor( 0.3 ) -- grey -- Immagine del Club if club.immagine ~= "" then network.download( "http://codelessfuture9892.cloudapp.net/download/" .. club.immagine, "GET", networkListener, params, club.immagine, system.TemporaryDirectory ) end -- all objects must be added to group (e.g. self.view) sceneGroup:insert( background ) sceneGroup:insert( golfClub ) sceneGroup:insert( summary ) sceneGroup:insert( indirizzo ) sceneGroup:insert( telefono ) sceneGroup:insert( email ) onComplete = function() local function onRowRender( event ) print("Entro") -- Get reference to the row group local row = event.row -- Cache the row "contentWidth" and "contentHeight" because the row bounds can change as children objects are added local rowHeight = row.contentHeight local rowWidth = row.contentWidth if riga.tipo == "coupon" then position = position + 15 righe[indice] = display.newText(row, elenco[riga.i].nome, 0, position, native.systemFontBold, 18 ) righe[indice]:setFillColor( 0 ) -- black -- Align the label left and vertically centered righe[indice].anchorX = 0 righe[indice].x = 0 righe[indice].y = rowHeight \* 0.5 print(riga.tipo .. "\> " .. elenco[riga.i].nome .. " (" .. #elenco[riga.i].itinerari .. ")") elseif riga.tipo == "itinerario" then position = position + 10 righe[indice] = display.newText(row, elenco[riga.i].itinerari[riga.j].nome, 0, position, native.systemFont, 16 ) righe[indice]:setFillColor( 0 ) -- black -- Align the label left and vertically centered righe[indice].anchorX = 0 righe[indice].x = 0 righe[indice].y = rowHeight \* 0.5 print(riga.tipo .. " - " .. elenco[riga.i].itinerari[riga.j].nome) end -- sceneGroup:insert(riga[indice]) end -- Create the widget tableView = widget.newTableView( { left = 0, top = 320, height = 118, width = display.contentWidth, onRowRender = onRowRender, onRowTouch = onRowTouch, listener = scrollListener } ) sceneGroup:insert(tableView) for i = 1, #elenco do indice = indice + 1 riga = {tipo = "coupon", i = i} --print(riga.tipo .. "\> " .. elenco[i].nome .. " (" .. #elenco[i].itinerari .. ")") tableView:insertRow({ isCategory = false, rowHeight = 50 }) for j = 1, #elenco[i].itinerari do indice = indice + 1 riga = {tipo = "itinerario", i = i, j = j, itinumber = itinumber} --print(riga.tipo .. " - " .. elenco[i].itinerari[j].nome) tableView:insertRow({ isCategory = false, rowHeight = 40 }) end end end -- sceneGroup:insert( tableView ) next = function() index = index + 1 if index \> #elenco then onComplete() return end network.request( "http://codelessfuture9892.cloudapp.net/api/itinerari\_coupon/" .. elenco[index].id , "GET", handleItinerariResponse ) end next() end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if phase == "will" then -- elseif phase == "did" then -- Called when the scene is now on screen -- -- INSERT code here to make the scene come alive -- e.g. start timers, begin animation, play audio, etc. end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if event.phase == "will" then -- Called when the scene is on screen and is about to move off screen -- -- INSERT code here to pause the scene -- e.g. stop timers, stop animation, unload sounds, etc.) elseif phase == "did" then -- Called when the scene is now off screen end end function scene:destroy( event ) local sceneGroup = self.view -- Called prior to the removal of scene's "view" (sceneGroup) -- -- INSERT code here to cleanup the scene -- e.g. remove display objects, remove touch listeners, save state, etc. end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) ----------------------------------------------------------------------------------------- return scene

Hi,

I’m sorry but I’m not gonna read all that code to figure out what your problem is.

You have not written anything in addition to posting your code.

You want help, you need to do better than that.

I’ll say this though, tableView does not work as scrollView in the way that where scrollView will keep the entire view and its objects intact, tableView will destroy rows that are off screen AKA culling. This is normal, by design and the best way to handle large listings, which is ultimately what tableView is deigned for.

Thank you! Also if you don’t read I gave me the answare I need! Since is only a week I’m programming with Corona I simply used the wrong functions!

Glad you figured it out mate,

and welcome to the world of Corona  :smiley:

After other try I find the correct way to use TableView as I need, because it is the right widget for the work.

I have to simply formulate outside the onRowRender function an array with the sequence of row (2 nested for) and use the row.id as the id for the array rendering function. 

Yes thats true, one of the easiest ways is to get your data from an array outside the onRowRender loop, and use the same index for the array as for the rows.

Also here

local globalData = require( "globalData" ) local widget = require( "widget" ) local json = require( "json" ) local composer = require( "composer" ) local scene = composer.newScene() composer.recycleOnSceneChange = true local sceneGroup -- elementi della scena local elenco --elenco clubs local index = 0 local indice = 0 -- per TableView row local righe = {} -- per TableView row local background -- sfondo scena local golfClub -- nome club local summary -- descrizione local telefono local email local indirizzo local immagine local tableView local riga = {} -- per comporre TableView complessa itinerari / coupon local position = 15 -- posizione Y per elementi in TableView elenco = globalData.coupons handleItinerariResponse = function( event ) if not event.isError then local response = json.decode( event.response ) if response.status == "OK" then h = #response.data elenco[index].itinerari = {} for i=1,h do table.insert(elenco[index].itinerari, { id = response.data[i].itinerari.id, nome = response.data[i].itinerari.nome, descrizione = response.data[i].itinerari.descrizione, listino = response.data[i].itinerari.listino, validita = response.data[i].itinerari.validita }) -- print( elenco[index].nome .. " \> " .. elenco[index].itinerari[i].nome ) end next() end else print( "Error!" ) end return end local function networkListener( event ) if ( event.isError ) then print( "Network error - download failed: ", event.response ) elseif ( event.phase == "began" ) then print( "Progress Phase: began" ) elseif ( event.phase == "ended" ) then immagine = display.newImageRect( event.response.filename, event.response.baseDirectory, display.actualContentWidth, 150 ) immagine.x = display.contentCenterX immagine.y = 170 immagine.alpha = 0 transition.to( immagine, { alpha=1.0 } ) sceneGroup:insert( immagine ) end end function scene:create( event ) sceneGroup = self.view -- Sfondo background = display.newRect( display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight ) background:setFillColor( 1 ) -- white local club = event.params[1] -- create some text local carattere if string.len(club.nome) \> 20 then carattere = 24 else carattere = 32 end golfClub = display.newText(club.nome, display.contentCenterX, 25, native.systemFontBold, carattere ) golfClub:setFillColor( 0 ) -- black local newTextParams = { text = club.descrizione, x = display.contentCenterX, y = 80, width = 300, height = 50, font = native.systemFont, fontSize = 14, align = "center" } summary = display.newText( newTextParams ) summary:setFillColor( 0 ) -- black -- campo indirizzo if string.len(club.indirizzo) \> 40 then carattere = 12 else carattere = 14 end indirizzo = display.newText( "Indirizzo: " .. club.indirizzo, display.contentCenterX, 260, native.systemFont, carattere ) indirizzo:setFillColor( 0.3 ) -- grey -- campo telefono if club.telefono == nil then club.telefono = "" end telefono = display.newText( "Telefono: " .. club.telefono, display.contentCenterX, 280, native.systemFont, 14 ) telefono:setFillColor( 0.3 ) -- grey -- campo email if club.email == nil then club.email = "" end email = display.newText( "Email: " .. club.email, display.contentCenterX, 300, native.systemFont, 14 ) email:setFillColor( 0.3 ) -- grey -- Immagine del Club if club.immagine ~= "" then network.download( "http://codelessfuture9892.cloudapp.net/download/" .. club.immagine, "GET", networkListener, params, club.immagine, system.TemporaryDirectory ) end -- all objects must be added to group (e.g. self.view) sceneGroup:insert( background ) sceneGroup:insert( golfClub ) sceneGroup:insert( summary ) sceneGroup:insert( indirizzo ) sceneGroup:insert( telefono ) sceneGroup:insert( email ) onComplete = function() local function onRowRender( event ) print("Entro") -- Get reference to the row group local row = event.row -- Cache the row "contentWidth" and "contentHeight" because the row bounds can change as children objects are added local rowHeight = row.contentHeight local rowWidth = row.contentWidth if riga.tipo == "coupon" then position = position + 15 righe[indice] = display.newText(row, elenco[riga.i].nome, 0, position, native.systemFontBold, 18 ) righe[indice]:setFillColor( 0 ) -- black -- Align the label left and vertically centered righe[indice].anchorX = 0 righe[indice].x = 0 righe[indice].y = rowHeight \* 0.5 print(riga.tipo .. "\> " .. elenco[riga.i].nome .. " (" .. #elenco[riga.i].itinerari .. ")") elseif riga.tipo == "itinerario" then position = position + 10 righe[indice] = display.newText(row, elenco[riga.i].itinerari[riga.j].nome, 0, position, native.systemFont, 16 ) righe[indice]:setFillColor( 0 ) -- black -- Align the label left and vertically centered righe[indice].anchorX = 0 righe[indice].x = 0 righe[indice].y = rowHeight \* 0.5 print(riga.tipo .. " - " .. elenco[riga.i].itinerari[riga.j].nome) end -- sceneGroup:insert(riga[indice]) end -- Create the widget tableView = widget.newTableView( { left = 0, top = 320, height = 118, width = display.contentWidth, onRowRender = onRowRender, onRowTouch = onRowTouch, listener = scrollListener } ) sceneGroup:insert(tableView) for i = 1, #elenco do indice = indice + 1 riga = {tipo = "coupon", i = i} --print(riga.tipo .. "\> " .. elenco[i].nome .. " (" .. #elenco[i].itinerari .. ")") tableView:insertRow({ isCategory = false, rowHeight = 50 }) for j = 1, #elenco[i].itinerari do indice = indice + 1 riga = {tipo = "itinerario", i = i, j = j, itinumber = itinumber} --print(riga.tipo .. " - " .. elenco[i].itinerari[j].nome) tableView:insertRow({ isCategory = false, rowHeight = 40 }) end end end -- sceneGroup:insert( tableView ) next = function() index = index + 1 if index \> #elenco then onComplete() return end network.request( "http://codelessfuture9892.cloudapp.net/api/itinerari\_coupon/" .. elenco[index].id , "GET", handleItinerariResponse ) end next() end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if phase == "will" then -- elseif phase == "did" then -- Called when the scene is now on screen -- -- INSERT code here to make the scene come alive -- e.g. start timers, begin animation, play audio, etc. end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if event.phase == "will" then -- Called when the scene is on screen and is about to move off screen -- -- INSERT code here to pause the scene -- e.g. stop timers, stop animation, unload sounds, etc.) elseif phase == "did" then -- Called when the scene is now off screen end end function scene:destroy( event ) local sceneGroup = self.view -- Called prior to the removal of scene's "view" (sceneGroup) -- -- INSERT code here to cleanup the scene -- e.g. remove display objects, remove touch listeners, save state, etc. end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) ----------------------------------------------------------------------------------------- return scene

Hi,

I’m sorry but I’m not gonna read all that code to figure out what your problem is.

You have not written anything in addition to posting your code.

You want help, you need to do better than that.

I’ll say this though, tableView does not work as scrollView in the way that where scrollView will keep the entire view and its objects intact, tableView will destroy rows that are off screen AKA culling. This is normal, by design and the best way to handle large listings, which is ultimately what tableView is deigned for.

Thank you! Also if you don’t read I gave me the answare I need! Since is only a week I’m programming with Corona I simply used the wrong functions!

Glad you figured it out mate,

and welcome to the world of Corona  :smiley:

After other try I find the correct way to use TableView as I need, because it is the right widget for the work.

I have to simply formulate outside the onRowRender function an array with the sequence of row (2 nested for) and use the row.id as the id for the array rendering function. 

Yes thats true, one of the easiest ways is to get your data from an array outside the onRowRender loop, and use the same index for the array as for the rows.