Fancier Scrolling List

Download the source code.
Play the video
Back








 10









 20









 30









 40









 50









 60









 70









 80









 90









100









110









120









130









140



#!/usr/bin/env lua5.1

-- A script to create a scrollable area in an interesting way
-- with kinetics and a fading scrollbar

-- FancyPants Lua includes
require [[fp]]
require [[fptheme]]
require [[fpwidgets]]

-- Width and height of scrollbar area.
SWIDTH = 200
SHIGHT = 400

-- Height of each entry line in the scrollbar
EHEIGHT = 56

-- Start x and y coordinates for each entry in the list
STARTX = 100
STARTY = 20

-- Add a background from the theme.  This looks into the theme and get the
-- background property.
bg = fp.image{ style = "background" }

-- The Lua dofile function imports another file and executes it as Lua.
dofile("data/sblist_data");

-- Create the scrollbar, set kinetic and fading
scroller = fp.scrollbar{ x = STARTX, y = STARTY, w = SWIDTH, h = SHIGHT, 
			 kinetic = 1, fading = 1 }

-- Create a vertical layout to put the entries into.  The layout 
-- will automatically place the entries one after the other.
layout = fp.layout{ dir = "vertical", x = STARTX, y = STARTY, 
		    w = SWIDTH, h = SHIGHT }

-- Declare the table of entries and clips.
entry = {}
clip  = {}
t  = {}

-- We need to keep track of the total height manually so that we can 
-- resize the clip at the end.
totalheight = 0

-- We iterate over the list of contacts.
for i, v in ipairs(Contacts) do

   even = ((i % 2) == 0)

   -- Create a container for grouping the elements within each entry.
   entry[i] = fp.container{}

   if (even) then
      -- Every second line is to have a different background colour.  
      -- This is achieved by creating a coloured rectangle and putting
      -- it behind the other elements in the entry.
      entry[i]:add(fp.rectangle{ x = EHEIGHT, y = 0,
				 w = SWIDTH, h = EHEIGHT, 
				 r = 5, g = 5, b = 5, a = 50 })
   end

   -- The elements in an entry are:
   --	checkbox
   --	name, we use a "strong" text style for this
   --	location, we use a "small" text style for this
   --	image, the image has special handing to resize it and
   --	centre it
   entry[i]:add(fp.checkbox{})
   entry[i]:add(fp.text{ text = v[1], style ="strong" }, 50, 10)
   entry[i]:add(fp.text{ text = v[2], style ="small" }, 50, 30)

   -- Align the image in the vertical middle of the list item.
   img = fp.image{ file = v[3] }
   g = img:geometry_get()
   entry[i]:add(img, 130, (EHEIGHT - g.h) / 2 )

   -- Create a clip as a dummy child of scrollbar.
   -- Each entry has its own clip as a clip can only be associated with
   -- one object at a time.  The clip is at the correct offset from the 
   -- top for the entry and the width of the scrollbar and height of
   -- an entry.
   -- This is necessary as the scrollbar only displays shows to the extent
   -- of something being in the scrollable area.
   y_offset = STARTY + ((i - 1) * EHEIGHT)
   clip[i] = fp.clip{ w = SWIDTH, h = EHEIGHT }

   -- We move the clip into position after we add it to the scrollbar
   -- as the scrollbar moves everything to its (0, 0) upon adding.
   scroller:add(clip[i])
   clip[i]:move(STARTX, y_offset)

   -- Setting the clip on the entry makes it only visible within the 
   -- shape / size of the scrollbar area
   entry[i]:clip_set(clip[i])	

   -- We are going to move the entries into position with a
   -- transform effect.  This will give them a nice slide-in.
   -- To do this we need the start and end coordinates of each entry.
   -- The start and end y coordinates are the same for this effect
   -- as the elements slide from left to right and left only.
   y = STARTY + ((i - 1) * EHEIGHT)

   -- We set up the transform by moving even elements to the right
   -- and odd elements to the left to start with.  The transform
   -- effect will slide them in.
   if (even) then
      entry[i]:move(STARTX + (3 * SWIDTH), y)
   else
      entry[i]:move(STARTX - (3 * SWIDTH), y)
   end

   -- We keep a count of the entries as the transform finishes as the 
   -- order of them completing is not guaranteed.
   count = 0

   -- Transform the entries to the final location.
   -- The anonymous function is called when the transform is complete.
   g = { x = STARTX, y = y, w = SWIDTH, h = EHEIGHT }

   entry[i]:transform(g, function()
			    count = count + 1

			    -- Unset the clip from the entry and hide the 
			    -- clip 
			    entry[i]:clip_set()
			    clip[i]:hide()

			    -- Add the entry to the entry layout once 
			    -- the transform is complete.
			    layout:child_add(entry[i])

			    -- Once all the entries have completed their
			    -- transform add the layout to the scrollable
			    -- area and hide the clip
			    if (count == #Contacts) then
			       scroller:add(layout)
			    end
			 end)
end

-- Finally, begin the main loop.
fp.begin()