Share Your Code

Table View Library

Posted by Gilbert, Posted on July 16, 2010, Last updated March 30, 2011

This library will allow you to create table views. Tables have rows of items and can scroll up and down.

Download: http://bitbucket.org/gilbert/table-view-library/src
Source files include tableView.lua, ui.lua, main.lua and png graphics. Source files include an assets folder with graphic source files. Graphic source files can be used to create custom backgrounds and buttons.

Tutorial: Create scrolling list views with text and graphics in Corona

Usage

UPDATE! 28 March 2011

I've created a new library file which I'm calling "extended" or "XL" for now. It is a super fast rendering version of the table view. Looks and feels the same, except it's extremely fast!!! It's not quite up to par on the extra features though. If you still want to group items by category with headers or use the scrollTo function, then use the old list view. Otherwise, if you want blazing fast performance with thousands of rows in the list, then use this! To get it just click the bitbucket link above. It's rolled up into the same download as the old list view. Eventually they will be merged. To use the new list view code, just add XL to the require statement:

 local tableView = require("tableViewXL")

To use this library, put this tableView.lua file into a folder with your main.lua file. In your main.lua file, add this to the top of your code:

1
local tableView = require("tableView")

Now you're ready to start building lists.

Show a basic list of items:

myList = tableView.newList{
        data=data, 
        default="listItemBg.png",
        over="listItemBg_over.png",
        onRelease=listButtonRelease,
        top=60,
        bottom=1,
        backgroundColor={ 255, 255, 255 },
        callback=function(item) 
                        local t = display.newText(item.title, 0, 0, native.systemFontBold, textSize)
                        t:setTextColor(0, 0, 0)
                        t.x = math.floor(t.width/2) + 20
                        t.y = 46 
                        return t
                end
}

Add a scroll bar! Use this one line of code right after your list is created.

1
myList:addScrollBar()

Remove the scroll bar when sliding the list out of view because it will persist on the screen.

1
myList:removeScrollBar()

Show a list grouped by optional headers:

data[1].title = "Pizza"
data[1].category = "Dinner"
data[2].title = "Coffee"
data[2].category = "Breakfast"
data[3].title = "Cheese"
data[3].category = "Lunch"
data[4].title = "Chicken Pot Pie"
data[4].category = "Dinner"
data[4].title = "Bagel"
data[4].category = "Breakfast"
data[5].title = "Apple Pie"
data[5].category = "Dinner"
 
local headers = { "Breakfast", "Lunch", "Dinner" }
 
myList = tableView.newList{
        data=data, 
        default="listItemBg.png",
        over="listItemBg_over.png",
        onRelease=listButtonRelease,
        top=60,
        bottom=1,
        cat="category",
        order=headers,
        categoryBackground="catBg.png",
        backgroundColor={ 255, 255, 255 },
        callback=function(item) 
                        local t = display.newText(item.title, 0, 0, native.systemFontBold, textSize)
                        t:setTextColor(0, 0, 0)
                        t.x = math.floor(t.width/2) + 20
                        t.y = 46 
                        return t
                end
}

Show a list with a background image showing through:

background = display.newImage("bg.png", true)
 
myList = tableView.newList{
        data=data,
        default="listItemBg_whitePointer.png",
        over="listItemBg_over.png",
        onRelease=listButtonRelease,
        top=60,
        bottom=1,
        callback=function(item) 
                        local t = display.newText(item.title, 0, 0, native.systemFontBold, textSize)
                        t:setTextColor(255, 255, 255)
                        t.x = math.floor(t.width/2) + 20
                        t.y = 46 
                        return t
                end
}

Arguments

The newList method accepts these arguments:

data
A table containing elements that the list can iterate through to display in each row.

default
An image for the row background. Defines the hit area for the touch.

over
An image that will show on touch.

onRelease (optional)
A function name that defines the action to take after a row is tapped.

top
The upper boundary of the list. The list will start and snap back to this position.

bottom
The bottom boundary of the list. The list will snap back to this position when scrolled upward.

cat
Specify the table key name used to store the category value for each item. Example: myData[1]["category"] = "Fruit" and myData[1]["text"] = "Banana". Requires using a multi-dimensional table where each row in the table stores different values for each item.

order
Optional modifier for cat that will allow you to specify an arbitrary order for headers. Specify order as a table containing the header names in the order you would like them to appear.

callback
A function that defines how to display the data in each row. Each element in the data table will be used in place of the argument ("item") assigned to the callback function.

Other Methods

* myList:addScrollBar() and myList:removeScrollBar()
Adds a scroll bar to the screen and removes scroll bar from the screen. No parameters.

* myList:addOnTop(object, xVal, yVal)
Allows you to append an object to the top of your list, like a search bar or a text object.

* myList:addOnBottom(object, xVal, yVal)
Allows you to append an object at the end of your list.

* myList:scrollTo(yVal, timeVal)
Allows you to move the list dynamically. It'll scroll right before the user's eyes. This is helpful if the user touches your nav bar at the top of the screen. Most apps will scroll a long list back to the top.

* myList:cleanUp()
Use this to destroy you list, clear it out of memory, and stop all event listeners.

Changes

Update 1.8
* Some performance improvements
* Added scrollbar! Use myList:addScrollBar() and myList:removeScrollBar()

Update 1.7
* Skipped over 1.4, 1.5, 1.6 and jumped right to 1.7.
* Added myListView:addOnTop(object, xVal, yVal)
Allows you to append an object to the top of your list, like a search bar or a text object.
* Added myListView:addOnBottom(object, xVal, yVal)
Allows you to append an object at the end of your list.
* Added myListView:scrollTo(yVal, timeVal)
Allows you to move the list dynamically. It'll scroll right before the user's eyes. This is helpful if the user touches your nav bar at the top of the screen. Most apps will scroll a long list back to the top.
* Added myListView:cleanUp()
Use this to destroy you list, clear it out of memory, and stop all event listeners.
* Cleaned up the code a little

Update 1.3
* Shipped with Corona SDK

Update 1.1
* Fixed an issue with using non-transparent row background images

Update 1.0
* Shipped with Corona 2.0 Beta 8

Update 0.9
* Improved support for Android

Update 0.8:
* Improved scrolling using time-based animation

Update 0.7:
* Added headers for grouped items

Update 0.6:
* Fixed bug with scrolling a short list such as a list with two items
* Removed background argument. No longer available. Backgrounds should be placed in a object behind the list object. See code under "Usage" below.
* Fixed bad table listener code (thanks, @dgaedcke)

Compatibility: 
Corona 2.0

Replies

dgaedcke
User offline. Last seen 18 hours 48 min ago. Offline
Joined: 17 Apr 2010

Gilbert.....I don't know if i'm missing some corona docs, but it seems you are using attributes (or creating your own) that are not documented. Specifically, I'm talking about "top" and "bottom" for your newListItem objects. Can you post some information about what these are used for and/or why you deviate from just using x, y, h, w? It seems you're doing so to track touch-coordinates but I'm having trouble tracking it.

Finally, I think around line 137 (look for "touch") you've mixed two different event handling scenarios...table vs function. I believe you meant to replace "touch" with the handler function and then pass the table to the Runtime object?

Thanks very much for posting these excellent examples...

Gilbert
User offline. Last seen 2 years 27 weeks ago. Offline
Alumni
Joined: 5 Apr 2010

Thanks for taking a look at my code. I added some info about the parameters for the newList method. The "top" and "bottom" parameters are a way to define where the list view should snap back to when its pulled beyond its upper and lower boundaries. "top" also defines the initial y value for the list, so there's no need to define "myList.y" after the list is created.

Thanks for spotting that error around line 137. I didn't realize I'd made that mistake. It caused me a headache a while back. "self" wasn't being passed properly to the listener. Now it's all fixed!

TheGiant
User offline. Last seen 13 weeks 4 days ago. Offline
Joined: 31 May 2010

Gilbert,

Very nice code!
Is it possible to set the height of a TableViewItem or the number of visible TableViewItems?

Miro
User offline. Last seen 2 years 18 weeks ago. Offline
Joined: 17 Sep 2009

Is there a way to have two titles in a cell?

Beezle
User offline. Last seen 2 years 5 weeks ago. Offline
Joined: 28 Aug 2010

Is it possible to set the height of a TableViewItem or the number of visible TableViewItems?

I second this. On iPad the items are too big.

Multimedia-Engi...
User offline. Last seen 19 hours 34 min ago. Offline
Joined: 22 Jun 2010

Is there a way to insert images beside the titles in the table view?

All the other features of the table view library are really great work!

Gilbert
User offline. Last seen 2 years 27 weeks ago. Offline
Alumni
Joined: 5 Apr 2010

The "callback" parameter is your best friend when you want to display something more complex than a single line of text in each row.

Basically, start by setting up your data to store multiple things in each row of the table.

1
2
3
4
5
6
7
8
9
10
11
12
13
--setup the table
local data = {}
 
--setup each row as a new table
data[1] = {}
data[1].title = "The first title"
data[1].subtitle = "The first subtitle"
data[1].image = "firstImage.png"
 
data[2] = {}
data[2].title = "The second title"
data[2].subtitle = "The second subtitle"
data[2].image = "secondImage.png"

Of course, you'll want to setup your data in a more automated fashion using a for loop. Each row should be a table with title, subtitle, image, and whatever else you need to display in each row of the list.

Then start by creating a group in your callback function:

1
2
3
callback = function(row)
              local g = display.newGroup()
           end

The "row" argument of the callback function is important. The tableView.lua library passes each row of your data table as the row parameter to your callback function.

Then display your text and images:

1
2
3
4
5
6
callback = function(row)
              local g = display.newGroup()
              local img = display.newImage(row.image)
              local title =  display.newText( row.title, 0, 0, native.systemFontBold, 14 )
              local subtitle =  display.newText( row.subtitle, 0, 0, native.systemFontBold, 14 )
           end

Then insert your text and images into the group and position them where they should be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
callback = function(row)
              local g = display.newGroup()
 
              local img = display.newImage(row.image)
              g:insert(img)
              img.x = 24
              img.y = 24
 
              local title =  display.newText( row.title, 0, 0, native.systemFontBold, 14 )
              g:insert(title)
              title.x = img.width + 12
              title.y = img.y
              
              local subtitle =  display.newText( row.subtitle, 0, 0, native.systemFontBold, 14 )
              g:insert(subtitle)
              subtitle.x = title.x
              subtitle.y = title.y + title.height + 12
           end

Finally, return the group at the end of the callback function. This is what gets displayed in each row:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
callback = function(row)
              local g = display.newGroup()
 
              local img = display.newImage(row.image)
              g:insert(img)
              img.x = 24
              img.y = 24
 
              local title =  display.newText( row.title, 0, 0, native.systemFontBold, 14 )
              g:insert(title)
              title.x = img.width + 12
              title.y = img.y
              
              local subtitle =  display.newText( row.subtitle, 0, 0, native.systemFontBold, 14 )
              g:insert(subtitle)
              subtitle.x = title.x
              subtitle.y = title.y + title.height + 12
 
              return g
           end

You can also add if-then statements to the callback function code to make rows display different things depending on the data. You can add any other display objects to the group, like buttons using ui.newButton{}

Check out the ATA app, which uses the table view and is on the App Store. Lines 135 through 159 show a complex example of the callback function used to display multiple lines of text and images. It parses some xml. The parsed xml is stored in a table. And then it reorganizes the table in the same way shown above into rows that have title, subtitle, images, etc. Then the callback function uses these things to display text and images in each row:

http://github.com/gg-ansca/ATA/blob/master/Calendar.lua#L135

Gilbert
User offline. Last seen 2 years 27 weeks ago. Offline
Alumni
Joined: 5 Apr 2010

The height of the table cell is determined by the height of the "default" and "over" images that you provide:

1
2
default="listItemBg.png",
over="listItemBg_over.png"

Make them more narrow to have skinny rows, or make them larger to have fat rows.

-Gilbert

Multimedia-Engi...
User offline. Last seen 19 hours 34 min ago. Offline
Joined: 22 Jun 2010

Thanks Gilbert,
you saved my day.
I was digging trough the code of tableView.lua and just didn't recognized this simple callback function. I should have read the manual first ;)

Alex

Gilbert
User offline. Last seen 2 years 27 weeks ago. Offline
Alumni
Joined: 5 Apr 2010

For the iPad, you might want to remove the height, width, and scale options in config.lua. This is what causes everything to grow to fill the screen.

After doing this, I'd recommend having the list sit at the left of the screen and the content on the right of the screen. This would create something like the Split View that you see in the Mail app.

I'm hoping to get a sample together soon that demonstrates this...

-Gilbert

LiveToCollect
User offline. Last seen 1 year 44 weeks ago. Offline
Joined: 3 Feb 2010

I loaded 525 total items (from sqlite) into 25 different categories tonight and it lags pretty bad. Any idea how to improve the performance? Thanks

Gilbert
User offline. Last seen 2 years 27 weeks ago. Offline
Alumni
Joined: 5 Apr 2010

Hey @LiveToCollect,

I am also working on a version of the list view that creates and destroys rows as they scroll by, kind of virtualizing the list.

I'm testing a prototype with lots of data that I know is slow in the basic list view and it's amazingly fast in the new virtualized list view. However, there are limitations as to what you can store in each row. Right now it's limited to one or two lines of text and some icons... It's fast because it can re-use rows by swapping out the contents. Custom content in display groups are not as easy to swap out. But we'll see, I may find a way to make it work.

I'll post more information here when it's ready.

-Gilbert

Gilbert
User offline. Last seen 2 years 27 weeks ago. Offline
Alumni
Joined: 5 Apr 2010

Hey Everyone!

Take a look at the tutorial posted on our blog today:

Create scrolling list views with text and graphics in Corona
http://blog.anscamobile.com/2010/09/create-scrolling-list-views-with-text-and-graphics-in-coronasdk-ios-android-tutorial/

LiveToCollect
User offline. Last seen 1 year 44 weeks ago. Offline
Joined: 3 Feb 2010

Thanks, Gilbert!

My categories were alphabet letters to break up the 525 items I was listing, so as a temporary fix (and probably a better user experience anyway) I've broken the process up into two steps. First you select the letter you would like to view, and then it only lists the items for that letter. 525 Items in one list is a little overkill anyway.

I am most interested in your SlideView gallery code being able to support a bulk of images. :)

Sunny
User offline. Last seen 7 hours 56 min ago. Offline
Joined: 20 Oct 2009

Hello and Thanks a lot for your works Gilbert,

It seems that there an issue with tableview 1.3 : specially in moveCat function.

Terminal Shows

1
2
3
4
5
6
Runtime error
        ...project/tableView.lua:364: attempt to compare number with nil
stack traceback:
        [C]: ?
        .../tableView.lua:364: in function <.../project/tableView.lua:360>
        ?: in function <?:186>

the problem appears when i'm removing the list and switching to another screen,
I think that the problem comes from a missing "removeEventListener".

The problem disapear when i don't use categories.

Does anyone have the same problem ?

Miro
User offline. Last seen 2 years 18 weeks ago. Offline
Joined: 17 Sep 2009

I'm trying to have two nested lists one which links to the next but when I create the second, it will not scroll but remains static even though the buttons work. Is there a way to have two lists? Thanks

Sunny
User offline. Last seen 7 hours 56 min ago. Offline
Joined: 20 Oct 2009

Hello All,

I found the issue with tableview when using categories.

How to see the problem :

- Build a list with categories
- when you're at the top of the list scroll down
- remove the group that contains the list view

How to solve

- line 363, 348, 353

instead of :

1
 Runtime:addEventListener("enterFrame", moveCat )

replace with
1
 Runtime:removeEventListener("enterFrame", moveCat )

Tell me if i'm wrong, maybe i'm missing something :)

Thanks,

tokyodan
User offline. Last seen 2 years 2 weeks ago. Offline
Joined: 24 Jun 2009

I’m trying to clip the scrolling list to an arbitrary window.

I created a screen-sized foreground image with a transparent portion representing the window through which the scrolling list items can be viewed. If 0,0 is the top left corner of the screen, the y coordinate of the top of the transparent portion is 100 and the y coordinate of the bottom of the transparent portion is 380.

How do I setup this example to do what it already does, but do it within the confines of my window?

ashleebeggs
User offline. Last seen 3 years 29 weeks ago. Offline
Joined: 22 Dec 2010

Hi I am also interested in how to contain the whole scrolling list to a rectangle...
How could I do this?

ashleebeggs
User offline. Last seen 3 years 29 weeks ago. Offline
Joined: 22 Dec 2010

Also where can I alter the code, so that when clicked each button goes to specific page and does not generate a unique page? Ive been trying to figure this out for days and I have narrowed it down to somewhere in the detailScreen area....

Gamexcb
User offline. Last seen 2 years 48 weeks ago. Offline
Joined: 28 Aug 2010

How do I remove the list?

stuville
User offline. Last seen 5 weeks 6 days ago. Offline
Joined: 11 Sep 2010

If you have the list as part of a display group (ie: display.newGroup) you should be able to just remove the display group.

stuville
User offline. Last seen 5 weeks 6 days ago. Offline
Joined: 11 Sep 2010

Note: There is a slight oversight within the tableview.lua. If you use categories, the list will not scroll when the beginning touch is on the category image or rect. I am looking into modifying the tableview.lua as it can be a frustrating user experience in this event. Unless someone else has already modified the code. In which case...please let me know. :)

stuville
User offline. Last seen 5 weeks 6 days ago. Offline
Joined: 11 Sep 2010

I modified version 1.4 of the TableView.Lua to allow scrolling when a user touches on a category. PM me if you need help in modifying and I will send you the code. Basically I set up a categoryHandler much like the newListItemHandler and added a touch listener to the category backgrounds. A more elegant approach would have been to just modify the newListItemHandler instead of creating a new Handler, but I wanted to keep the code separate for now.

andrea.leoncini
User offline. Last seen 2 years 31 weeks ago. Offline
Joined: 15 Nov 2010

HI Gilbert and all
I'm in trouble using top and bottom params, my list is the body of a screen which has an header and a bottom bar. Suppose to use an iPhone 3g 320x480 resolution and let's say the header has an height of 60px and the bottom bar an height of 40. So my list should scroll between these two values. In my code I have used top=60 and bottom=440 but unfortunately the list scroll up and down over these limits and cover both the header and footer graphics. Any suggestion on this issue?

stuville
User offline. Last seen 5 weeks 6 days ago. Offline
Joined: 11 Sep 2010

Andrea, I had the same problem, and due to my laziness, I just created a function that creates the table and another function to creates the upper navBar/Header. Then in the code, I call

createTable()
createNavBar()

This is effect places the header object on top of the table so the table really scrolls underneath the header. The table still bounces back to the top and bottom params.

Stu

andrea.leoncini
User offline. Last seen 2 years 31 weeks ago. Offline
Joined: 15 Nov 2010

Good point Stu
I also made something like your workaround creating the header and the navBar on top of the table.
Unfortunately I'm experiencing right now that clicking on navBar actually fire events to the table listener, even if the graphic is covered by the nav or header objects.
I'm investigating on this other issue

Sunny
User offline. Last seen 7 hours 56 min ago. Offline
Joined: 20 Oct 2009

hello andrea,

in your event listener for your button you need to add "return true" in the end in order to make it work properly over your tableview...

1
2
3
4
5
6
7
local function eventListener (event)
    your code..
 
    return true
end
 
local button:addEvenListener("touch", eventListener)

stuville
User offline. Last seen 5 weeks 6 days ago. Offline
Joined: 11 Sep 2010

Andrea,

If you look at the Coffee demo, there is the following code segment that should take a touch on the navBar and scroll your list...well...the top of your list and not to the detail screen. Without seeing your code, I am just taking stabs. If you want/can email me your code block for the table and screen, I'd be willing to look at it. :)

1
2
3
4
5
6
7
8
9
10
11
local function scrollToTop()
        myList:scrollTo(topBoundary-1)
end
 
--Setup the nav bar 
local navBar = ui.newButton{
        default = "navBar.png",
        onRelease = scrollToTop
}
navBar.x = display.contentWidth*.5
navBar.y = math.floor(display.screenOriginY + navBar.height*0.5)

andrea.leoncini
User offline. Last seen 2 years 31 weeks ago. Offline
Joined: 15 Nov 2010

thanks a lot Stu
here it is the code that creates the screen, in the meanwhile I have tried some little trick but with no success.

for your information: the back button in the header works fine, the problem occurs with the three image buttons in the bottom bar

any kind of help will be appreciated

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
function getDownldCoursesScreen( params )
        local scrn = display.newGroup()
        scrn.alpha = 0
        
        local header = display.newImageRect("img/topBar.png", 320, 40)
        header.x = display.contentWidth / 2
        header.y = top() + header.height / 2
        
        local topText1 = display.newText("Courses", 0, 0, native.systemFontBold, 16)
        topText1:setTextColor(255, 255, 255)
        topText1.x = display.contentWidth / 2
        topText1.y = top() + header.height / 2
        
        local bg1 = display.newRect(0, 0, display.contentWidth, top() + header.height )
        bg1:setFillColor(255,255,255)
 
        local bg2 = display.newRect(0, display.contentHeight - rowHeight(), display.contentWidth, display.contentWidth, display.contentHeight )
        bg2:setFillColor(0,0,0)
 
        local backButton = ui.newButton {
        default = "backButton.png",
        over = "backButton_over.png",
        onRelease = params.backHandler,
        id = "backButton",
        }
        backButton.x = 5 + backButton.width / 2
        backButton.y = top() + header.height / 2
        
        local listButton = display.newImageRect("img/bbc_list.png", 90, 40)
        listButton.x = 60
        listButton.y = display.contentHeight - rowHeight() / 2
 
        function listButton:tap(e)
                params.barHandler(1)
        end
        listButton:addEventListener("tap", listButton)  
                
        local downldButton = display.newImageRect("img/bbc_downld_hi.png", 90, 40)
        downldButton.x = 160
        downldButton.y = display.contentHeight - rowHeight() / 2
 
        function downldButton:tap(e)
                params.barHandler(2)
        end
        downldButton:addEventListener("tap", downldButton)      
                
        local editButton = display.newImageRect("img/bbc_edit.png", 90, 40)
        editButton.x = 260
        editButton.y = display.contentHeight - rowHeight() / 2
 
        function editButton:tap(e)
                params.barHandler(3)
        end
        editButton:addEventListener("tap", editButton)  
 
        local list = tv.newList{
                data=params.courses, 
                default="listBG.png",
                over="listBG_over.png",
                onRelease=params.linkHandler,
                top = top() + header.height,
                bottom = 440,
                backgroundColor={ 255, 255, 255 },
                callback=function(row)
                        local lrow = display.newGroup()
                        local t1 = display.newText(row.name, 5, 5, native.systemFontBold, 14)
                        t1:setTextColor(0, 0, 0)
                        local t2 = display.newText(row.address, 5, 25, nil, 12)
                        t2:setTextColor(50, 50, 50)
                        lrow:insert(t1)
                        lrow:insert(t2)
                        return lrow
                end
        }
                
        scrn:insert(list)
        scrn:insert(bg1)
        scrn:insert(header)
        scrn:insert(topText1)
        scrn:insert(backButton)
        scrn:insert(bg2)
        scrn:insert(listButton)
        scrn:insert(downldButton)
        scrn:insert(editButton)
 
        return scrn     
end
 
 
</code

Sunny
User offline. Last seen 7 hours 56 min ago. Offline
Joined: 20 Oct 2009

for each of your buttons event listener add return true...

ex :

1
2
3
4
function editButton:tap(e)
                params.barHandler(3)
               return true
end

andrea.leoncini
User offline. Last seen 2 years 31 weeks ago. Offline
Joined: 15 Nov 2010

Hi all
the problem is in the event, replacing "tap" with "touch" now it works properly. I have attached an example.
I don't know exactly why that solves the problem, may be someone else can explain it?

1
2
3
4
5
6
7
8
        local editButton = display.newImageRect("img/bbc_edit.png", 90, 40)
        editButton.x = 260
        editButton.y = display.contentHeight - rowHeight() / 2
 
        function editButton:touch(e)
                params.barHandler(3)
        end
        editButton:addEventListener("touch", editButton)        

stuville
User offline. Last seen 5 weeks 6 days ago. Offline
Joined: 11 Sep 2010

Hmmm....not sure why the "tap" wasn't firing correctly. Although keep in mind that if you use "touch" you should check the event (e) as it will fire twice without some checking. Once in event.phase = "began" and then again on event.phase = "ended"

ie:

1
2
3
4
5
6
function editButton:touch(e)
               -- execute when the finger is lifted from the screen
                if e.phase = "ended" then
                        params.barHandler(3)
                end
        end

stuville
User offline. Last seen 5 weeks 6 days ago. Offline
Joined: 11 Sep 2010

As for the topBoundary and bottomBoundary for a tableView. As best that I can tell, (correct me if I am wrong) they are just used for the scrolling bounce back effect. Top is equal to your navBar height and Bottom is equal to the height of any image or buttons on the bottom.

For example. If I have a navBar (image) with a height of 40

topBoundary = 40

and if I have a tab bar or image alone the bottom with a height of say 60 then

bottomBoundary = 60

Did that make any sense at all?

Stu

Gilbert
User offline. Last seen 2 years 27 weeks ago. Offline
Alumni
Joined: 5 Apr 2010

That's correct! @stuville has got it right about the top and bottom parameters.

Gilbert
User offline. Last seen 2 years 27 weeks ago. Offline
Alumni
Joined: 5 Apr 2010

Hey all,

I just posted an update for the Table View Library!

Go to bitbucket to get it!

http://bitbucket.org/gilbert/table-view-library/src
(click download source to get all the files.)

The new version has four new listview methods:

* myListView:addOnTop(object, xVal, yVal)
Allows you to append an object to the top of your list, like a search bar or a text object.

* myListView:addOnBottom(object, xVal, yVal)
Allows you to append an object at the end of your list.

* myListView:scrollTo(yVal, timeVal)
Allows you to move the list dynamically. It'll scroll right before the user's eyes. This is helpful if the user touches your nav bar at the top of the screen. Most apps will scroll a long list back to the top.

* myListView:cleanUp()
This has been in the code for a while, but I don't think it was clear. Use this to destroy you list, clear it out of memory, and stop all event listeners.

I also fixed the bug where if you touch the category header between list items, the list did not scroll. It now scrolls if you touch these! Thanks to @stuville for pushing me to get this done.

We're up to version 1.7 now.

Thanks!
Gilbert

stuville
User offline. Last seen 5 weeks 6 days ago. Offline
Joined: 11 Sep 2010

Thanks Gilbert! I was able to plop the new tableView version (1.7) into my project and run it with no problems. I love how Corona Project Manager allows me to do this easily. The added methods are a bonus too.

andrea.leoncini
User offline. Last seen 2 years 31 weeks ago. Offline
Joined: 15 Nov 2010

Gilbert and Stu
I have investigated a bit more on my trouble with event management, and I think that the problem was that the touch event is notified to the nav bar button but also to the table view. it seemed to solve only because the event is intercepted first by the button and then by the list. (I suppose this is due to the order of creation).
so, thanks to your both suggestions the right code to manage correctly the event is

1
2
3
4
5
6
        function editButton:touch(e)
                if e.phase == "ended" then
                        params.barHandler(3)
                end
                return true
        end

in this way I can call the handler only once and with the statement return true the event is not propagated to the underlying list.

thanks a lot for your valuable suggestions

andrea.leoncini
User offline. Last seen 2 years 31 weeks ago. Offline
Joined: 15 Nov 2010

...and of course I'm using version 1.7 ;)

sabee
User offline. Last seen 5 weeks 4 days ago. Offline
Joined: 27 Jan 2011

Thanks for this great code Gilbert. I would like to know if there is a way to remove items from the list dynamically.

I'm trying to do a to-Do type of list, and once checked (clicked), I would like to remove the item from the list.

Any idea how to do this?
Thanks for any help.
seb

EDIT: I wrote a function to do that and add it to the library:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function listView:removeItem(object, doTrans)
                local h=object.height
                local posY = object.y
                
                object:removeSelf()
                for i = listView.numChildren, 2, -1 do
                        if(listView[i].y > posY) then
                                local posY = listView[i].y - h
                                if(doTrans) then
                                        transition.to( listView[i], { y=posY, time=500, transition=easing.inOutQuad } )
                                else
                                        listView[i].y = posY
                                end
                        end
                end
                
 
-- Repos de listContainer
                local posYlist
                if(currentTarget.y + h < currentTarget.top) then
                        posYlist = currentTarget.y + h
                elseif(currentTarget.top + currentTarget.y < h) then
                        posYlist = currentTarget.top
                end
                
                if(posYlist ~= nil) then
                        if(doTrans) then
                                transition.to( currentTarget, { y=posYlist, time=500, transition=easing.inOutQuad } )
                        else
                                currentTarget = posYlist
                        end
                end
        end

Then I simply call it like that
myList:removeItem(objRef, true) -- true for a transition
(I put a bit of delay for the fx)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
local function clickBtnList(event)
        if(event.phase == "release") then
                local btn = event.target.parent  -- this might be different for you
                
                function btn:timer( event )
                        myList:removeItem(self, true)
                        if(myList.numChildren -1 == 0) then
                                print("No more btn in the list")
                        end
                end
                        
                timer.performWithDelay(300, btn, 1 )
                        
        end
end

sabee
User offline. Last seen 5 weeks 4 days ago. Offline
Joined: 27 Jan 2011

Hello Gilbert,
Thank you very much for your library. I wanted to know if what you mention here about destroying and building the rows dynamically is on the new version 1.7 now, or if not do know if it will be available any time soon?
I will need to create a very long list of people, and so I know if I will have to split by letter or something, or if your script will handle them. (its basically a list with text, so I guess it could be swaped on the flight)
Thanks again!
seb

mickeyben
User offline. Last seen 3 years 19 weeks ago. Offline
Joined: 10 Feb 2011

Hi,
Nice library !!
is there a way to use it with the director lib ? so I can handle the transitions with director.

s.heinisch
User offline. Last seen 3 years 17 weeks ago. Offline
Joined: 4 Mar 2011

Hello,

i try to insert a group with an textfield. But when i insert the textField, the textfiel is shown in the top left corner and not in the tableview.

Is there a solution for this problem or am i'm just stupid?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
callback=function(item) 
                
                                if (item.title ~= nil) then
                                        local t = display.newText(item.title, 0, 0, native.systemFontBold, textSize)
                                        t:setTextColor(0, 0, 0)
                                        t.x = math.floor(t.width/2) + 12
                                        t.y = 46 
                                        return t
                                end
                                
                                if (item.inputItem ~= nil) then
                                
                                
                                        local g = display.newGroup()
                                        local captionField = native.newTextField( 0, 0, (display.contentWidth - 20), 20 + 10 )
                                        captionField.font = native.newFont(native.systemFontBold, 10 )
        
                                        g:insert(captionField)
                                
                                        return g
                                end
                                
                        end

(I know the type of insert the input field is not clean - but it's just a test)

info158
User offline. Last seen 2 years 2 days ago. Offline
Joined: 14 Mar 2011

I have the same problem that Miro had...

I'm creating more than 1 list (2 for the moment), but when I have more than list I cannot scroll anymore. I can only scroll the latest list...

I tried myListView[2]:cleanUp() from version 1.7
but doesn't work..

Clement
User offline. Last seen 1 year 47 weeks ago. Offline
Joined: 29 Nov 2010

Is there a way to add a scrolling side bar to the right hand side for the user to see when scrolling down the table view?

knightenator
User offline. Last seen 2 years 30 weeks ago. Offline
Joined: 26 Mar 2011

Great job with this library, it is very easy to work with.

I am developing a reading app, and I want to display a list of chapters, and indicate the current chapter by changing the background image for that row(with a checkmark instead of a right arrow), and also scrolling the list to bring the current chapter into view.

The problem I am seeing is is that scrollTo() with y values other than 0 is moving the whole list down the screen.

Also, I have to handle the checkmark in the callback - it would be slicker to have a selected image property to use and then use a boolean in the callback to indicate you are at the selected row.

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
local chapTableView = nil
 
function OnChapterListSelect( event )
        chap = event.target.id
        chapTableView:cleanUp()
        chapTableView = nil
        LoadAndDisplayChapter()
end
 
local function DisplayChapterList()
        if (chapTableView) then
                return
        end
        local headers = { "Chapter" }
        local scrollto = nil
        chapTableView = tableView.newList{
                data=ftdata:GetChapterList(),
                default="listItemBg.png",
                over="listItemBg_over.png",
                onRelease=OnChapterListSelect,
                top=display.screenOriginY,
                bottom=display.screenOriginY,
                cat="category",
        order=headers,
        categoryBackground="catBg.png",
                backgroundColor={255,255,255},
                callback = function( row )
                        local g = display.newGroup()
                        local t =  display.newText( row.heading, 0, 0, native.systemFontBold, 14 )
                        t:setTextColor(0,0,0)
                        t.x = math.floor(t.width/2) + 20
                        t.y = 50
                        g:insert(t)
                        if(row.chid == chap) then
                                drawCheckmark(g)
                                scrollto = g
                        end
                        return g
                end
        }
        return scrollto
end
 
local function DisplayChapterListAndScroll()
         local stgrp = DisplayChapterList()
         if (stgrp) then
                local x_content, y_content = stgrp:localToContent(0,0)
                -- Problem - scrolls whole list down the screen
                chapTableView:scrollTo(y_content, 200)
         end
end

Gilbert
User offline. Last seen 2 years 27 weeks ago. Offline
Alumni
Joined: 5 Apr 2010

Hey @knightenator,

You might be having an issue with scrollTo if it's not receiving negative values. The top of the list is at y = 0. As soon as the list moves up, the y value crosses the zero mark and starts becoming negative.

-Gilbert

Gilbert
User offline. Last seen 2 years 27 weeks ago. Offline
Alumni
Joined: 5 Apr 2010

Hi all,

I've rewritten the table view library to improve performance. It's now super fast!!! With 1200 items which I loaded from an xml file in some of my tests it moves as thought there's only 6 items! And that's because there is! What I mean is that it's only generating what needs to be shown on screen and dynamically loading new rows as the list scrolls. This greatly improves performance because all those items don't have to be stored in memory.

Get the new list view code a the same bitbucket url above. I wanted to get an early release in your hands so I've left the old one up there and the new one is called tableViewXL.lua. You don't have to change anything in your existing code to make it work except add "XL" to the require statement to refer to the new file name. See note above...

Thanks!
Gilbert

knightenator
User offline. Last seen 2 years 30 weeks ago. Offline
Joined: 26 Mar 2011

Thanks Gilbert, scrollTo() works with a negative y.

I did find that now the category disappears when using scrollTo, adding moveCat() in the finished case of onScrollTo() fixes it for me:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function onScrollTo(event)
        local timePassed = event.time - lastTime
        lastTime = lastTime + timePassed  
        
    velocity = 2
        if currentTarget.y <= currentTarget.yVal then
                currentTarget.y = math.floor(currentTarget.y + velocity*timePassed)  
                moveCat()   
        else 
        currentTarget.y = currentTarget.yVal
        Runtime:removeEventListener("enterFrame", onScrollTo )
                -- added moveCat call to fix losing the category heading
                moveCat()        
        end
end

Gilbert
User offline. Last seen 2 years 27 weeks ago. Offline
Alumni
Joined: 5 Apr 2010

Interesting. I haven't noticed that behavior, but I'll add it to my code to make sure no one else runs into the same issue.

Thanks!
Gilbert