[EDIT: Cleaned up onRowTouch to remove my nasty debug code]
I wanted to build a full iOS native style application. This has quite a few hurdles to overcome when using Corona (but not as many as Obj-C does!) so here is the code for a native-style scrollbar.
Obviously, you can’t grab it - it is just a visual aid memoir, but if adjusted to the sizes and positions relative to your table view on screen it should be good for at least a 320 phone screen.
I intend to build a number of these components just as I intend to build a full iOS style app for both iPhone and iPad.
The code below is a modified main.lua from the WidgetDemo and includes the code I posted recently for swipe-reveal Delete buttons. You will need the images from this post to make those work:
https://developer.anscamobile.com/forum/2012/05/21/swipe-delete-tableview
Oh, also the scrollbar is red, not the customary grey. Please feel free to change it to your liking.
Btw, I should note that it will not automatically adjust the scrollbar height when you add or remove rows, so you would need to update list.totalheight yourself if you do that.
[lua]–*********************************************************************************************
– ====================================================================
– Corona SDK “Widget” Sample Code
– ====================================================================
– File: main.lua
– Version 1.5
– Copyright © 2011 ANSCA Inc. All Rights Reserved.
– Permission is hereby granted, free of charge, to any person obtaining a copy of
– this software and associated documentation files (the “Software”), to deal in the
– Software without restriction, including without limitation the rights to use, copy,
– modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
– and to permit persons to whom the Software is furnished to do so, subject to the
– following conditions:
– The above copyright notice and this permission notice shall be included in all copies
– or substantial portions of the Software.
– THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
– INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
– PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
– FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
– OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
– DEALINGS IN THE SOFTWARE.
– Published changes made to this software and associated documentation and module files (the
– “Software”) may be used and distributed by ANSCA, Inc. without notification. Modifications
– made to this software and associated documentation and module files may or may not become
– part of an official software release. All modifications made to the software will be
– licensed under these same terms and conditions.
–*********************************************************************************************
display.setStatusBar( display.DefaultStatusBar )
local widget = require “widget”
widget.setTheme( “theme_ios” )
– create display groups
local demoGroup = display.newGroup()
local tabBarGroup = display.newGroup()
– forward declarations for widgets (so they can be removed manually)
local list, scrollBox, backButton, doneButton, pickerButton, picker
– private functions
local function clearGroup( g )
– remove all widgets (they must be removed manually)
if list then list:removeSelf(); list = nil; end
if scrollBox then scrollBox:removeSelf(); scrollBox = nil; end
if backButton then backButton:removeSelf(); backButton = nil; end
if doneButton then doneButton:removeSelf(); doneButon = nil; end
if pickerButton then pickerButton:removeSelf(); pickerButton = nil; end
if picker then picker:removeSelf(); picker = nil; end
– clear the contents of a group, but don’t delete the group
for i=g.numChildren,1,-1 do
display.remove( g[i] )
end
end
– create a gradient for the top-half of the toolbar
local toolbarGradient = graphics.newGradient( {168, 181, 198, 255 }, {139, 157, 180, 255}, “down” )
– create toolbar to go at the top of the screen
local titleBar = widget.newTabBar{
top = display.statusBarHeight,
topGradient = toolbarGradient,
bottomFill = { 117, 139, 168, 255 },
height = 44
}
– position the demo group underneath the toolbar
demoGroup.y = display.statusBarHeight + titleBar.height + 1
– create embossed text to go above toolbar
local titleText = display.newEmbossedText( “Widget Demo”, 0, 0, native.systemFontBold, 20, { 255 } )
titleText:setReferencePoint( display.CenterReferencePoint )
titleText.x = display.contentWidth * 0.5
titleText.y = titleBar.y + titleBar.height * 0.5
– tab button listeners
local function showTableView( event )
clearGroup( demoGroup )
– create tableView widget
list = widget.newTableView{
width = 320,
height = 366,
maskFile = “assets/mask-320x366.png”
}
– insert widget into demoGroup
demoGroup:insert( list.view )
– onEvent listener for the tableView
local function onRowTouch( event )
local row = event.target
local rowGroup = event.view
if event.phase == “press” then
if not row.isCategory and row.title then
row.title.text = “Pressed…”
row.title:setReferencePoint( display.CenterLeftReferencePoint )
row.title.x = 15
end
elseif event.phase == “release” then
if not row.isCategory then
row.reRender = true
print( “You touched row #” … event.index )
end
end
–[[This part handles the swipe left and right to show and hide the delete button]]–
if (event.phase == “swipeLeft”) then
transition.to( rowGroup.del, {time=rowGroup.del.transtime,maskX=-rowGroup.del.width/2,onComplete=rowGroup.del.setActive} )
elseif (event.phase == “swipeRight”) then
transition.to( rowGroup.del, {time=rowGroup.del.transtime,maskX=rowGroup.del.width/2,onComplete=rowGroup.del.setInactive} )
end
–[[End of delete handling]]–
return true
end
– onRender listener for the tableView
local function onRowRender( event )
local row = event.target
local rowGroup = event.view
local textFunction = display.newRetinaText
if row.isCategory then textFunction = display.newEmbossedText; end
row.title = textFunction( “Row #” … event.index, 12, 0, native.systemFontBold, 16 )
row.title:setReferencePoint( display.CenterLeftReferencePoint )
row.title.y = row.height * 0.5
if not row.isCategory then
row.title.x = 15
row.title:setTextColor( 0 )
–[[This part adds the swiped delete button and hides it with a mask…]]–
local del = nil – the image sitting over the top of the button widget
local onButtonEvent = function (event )
print(‘del.isactive’,del.isactive)
if (not del.isactive) then
return false
end
if (event.phase == “release”) then
print( “You pressed and released a button!” )
end
return true
end
local myButton = widget.newButton{
id = “btn001”,
left = 225,
top = 9,
label = “”,
width = 90, height = 46,
cornerRadius = 8,
onEvent = onButtonEvent,
default=“deleteback.png”,
over=“deleteback.png”,
}
rowGroup:insert(myButton.view)
del = display.newImage(rowGroup,“deletebtn.png”)
del.x, del.y = 270, 32
del.xScale, del.yScale = .7, .7
del.isactive = false
rowGroup.del = del
local mask = graphics.newMask(“slidemask.png”)
del:setMask( mask )
del.maskScaleX, del.maskScaleY = -1, 1
del.maskX = del.width/2
del.maskY = 100
del.transtime = 300
function del:setActive()
print(‘active’,deletetap)
del.isactive = true
end
function del:setInactive()
print(‘inactive’)
del.isactive = false
end
–[[End of new delete button]]–
end
– must insert everything into event.view:
rowGroup:insert( row.title )
end
– total height of rows in the content
list.totalheight = 0
– Add 100 rows, and two categories to the tableView:
for i=1,100 do
local rowHeight, rowColor, lineColor, isCategory = 64 – assign default row height for non-category rows
– make the 25th item a category
if i == 25 then
isCategory = true; rowHeight = 24; rowColor={ 174, 183, 190, 255 }; lineColor={0,0,0,255}
end
– make the 50th item a category as well
if i == 50 then
isCategory = true; rowHeight = 24; rowColor={ 174, 183, 190, 255 }; lineColor={0,0,0,255}
end
– accumulate the total height of the content rows
list.totalheight = list.totalheight + rowHeight
– insert the row into the tableView widget
list:insertRow{
onEvent=onRowTouch,
onRender=onRowRender,
height=rowHeight,
isCategory=isCategory,
rowColor=rowColor,
lineColor=lineColor
}
end
local currentpos = list:getScrollPosition()
list.maxscrolltop = 366-list.totalheight+24
–[[scroll bar handling]]–
local scrollbar = display.newRoundedRect( demoGroup, display.contentWidth - 5, display.statusBarHeight+50, 2.5, display.contentHeight - 128, 2.5 )
scrollbar:setFillColor( 255,0,0 )
scrollbar.lastchangetime = system.getTimer()
adjustScrollBar = function( event )
if (list.totalheight < 366) then
scrollbar.alpha = 0
else
local starty = scrollbar.y
– check scroll position and adjust
local scrollpos = list:getScrollPosition()
if (scrollpos <= 0 and scrollpos >= list.maxscrolltop) then
local heightperc = (346 / list.totalheight) * 100
local scrollperc = (math.abs(scrollpos / math.abs(list.maxscrolltop))) * 100
scrollbar.height = 346/100*heightperc
scrollbar.y = 10 + display.statusBarHeight + 44 + (scrollbar.height/2)+((346-scrollbar.height)/100*scrollperc)
elseif (scrollpos > 0) then
local scrollperc = (scrollpos / 366) * 100
local heightperc = (346 / list.totalheight) * 100
heightperc = heightperc - scrollperc
scrollbar.height = 346/100*heightperc
scrollbar.y = 10 + display.statusBarHeight + 44 + (scrollbar.height/2)
elseif (scrollpos < list.maxscrolltop) then
local scrollperc = ((list.maxscrolltop - scrollpos) / 366) * 100
local heightperc = (346 / list.totalheight) * 100
heightperc = heightperc - scrollperc
scrollbar.height = 346/100*heightperc
scrollbar.y = 10 + display.statusBarHeight + 44 + (346 - (scrollbar.height/2))
end
scrollbar.y = scrollbar.y - (display.statusBarHeight + titleBar.height + 1)
– fade out the scrollbar
if (starty ~= scrollbar.y) then
scrollbar.lastchangetime = system.getTimer()
end
if (system.getTimer() - scrollbar.lastchangetime > 500) then
if (scrollbar.fadeintrans ~= nil) then
transition.cancel( scrollbar.fadeintrans )
scrollbar.fadeintrans = nil
end
if (scrollbar.fadeouttrans == nil) then
scrollbar.fadeouttrans = transition.to( scrollbar, { time=250, alpha=0 } )
end
else
if (scrollbar.fadeouttrans ~= nil) then
transition.cancel( scrollbar.fadeouttrans )
scrollbar.fadeouttrans = nil
end
if (scrollbar.fadeintrans == nil) then
scrollbar.fadeintrans = transition.to( scrollbar, { time=150, alpha=1 } )
end
end
end
end
Runtime:addEventListener( “enterFrame”, adjustScrollBar )
–[[end of scroll bar handling]]–
end
local function showScrollView( event )
clearGroup( demoGroup )
– create scrollView widget
scrollBox = widget.newScrollView{
–top = display.statusBarHeight + titleBar.height,
width = 320,
height = 366,
maskFile = “assets/mask-320x366.png”
}
– insert widget into demoGroup
demoGroup:insert( scrollBox.view )
local longImage = display.newImageRect( “assets/scrollimage.png”, 320, 1024 )
longImage:setReferencePoint( display.TopLeftReferencePoint )
longImage.x, longImage.y = 0, 0
– insert image into scrollView
scrollBox:insert( longImage )
end
local function showButtons( event )
clearGroup( demoGroup )
– set starting indexes for picker columns
local monthIndex, dayIndex, yearIndex = 10, 5, 21
– create grey background
local bg = display.newRect( 0, 0, display.contentWidth, display.contentHeight-demoGroup.y )
bg:setFillColor( 152, 152, 156, 255 )
demoGroup:insert( bg )
– create a label to show selected date
local dateText = display.newRetinaText( “No date selected.”, 0, 0, native.systemFontBold, 22 )
dateText:setTextColor( 0 )
dateText:setReferencePoint( display.CenterReferencePoint )
dateText.x = display.contentWidth * 0.5
dateText.y = 100
demoGroup:insert( dateText )
– onRelease listener for pickerButton
local function onButtonRelease( event )
– onRelease listener for back button
local function onBackRelease( event )
– remove the picker, the done button, and the back button (event.target)
if picker then picker:removeSelf(); picker = nil; end
if doneButton then doneButton:removeSelf(); doneButton = nil; end
if backButton then backButton:removeSelf(); backButton = nil; end
return true
end
– onRelease listener for the done button
local function onDoneRelease( event )
– extract pickerwheel column values
local dateColumns = picker:getValues()
local month, day, year = dateColumns[1].value, dateColumns[2].value, dateColumns[3].value
– mark column index so we can start in same position next time
monthIndex = dateColumns[1].index
dayIndex = dateColumns[2].index
yearIndex = dateColumns[3].index
– change the dateText’s label
dateText.text = month … " " … day … ", " … year
– remove the picker, the done button, and the back button (event.target)
if picker then picker:removeSelf(); picker = nil; end
if doneButton then doneButton:removeSelf(); doneButton = nil; end
if backButton then backButton:removeSelf(); backButton = nil; end
return true
end
– create ‘back’ button to be placed on toolbar
backButton = widget.newButton{
label = “Back”,
left = 5, top = 28,
style = “backSmall”,
onRelease = onBackRelease
}
– create ‘done’ button to be placed on toolbar
doneButton = widget.newButton{
label = “Done”,
left = 255, top = 28,
style = “blue2Small”,
onRelease = onDoneRelease
}
– set up the pickerWheel’s columns
local columnData = {}
columnData[1] = { “January”, “February”, “March”, “April”, “May”, “June”, “July”, “August”, “September”, “October”, “November”, “December” }
columnData[1].alignment = “right”
columnData[1].width = 150
columnData[1].startIndex = monthIndex
columnData[2] = {}
for i=1,31 do
columnData[2][i] = i
end
columnData[2].alignment = “center”
columnData[2].width = 60
columnData[2].startIndex = dayIndex
columnData[3] = {}
for i=1,25 do
columnData[3][i] = i+1990
end
columnData[3].startIndex = yearIndex
– create pickerWheel widget
picker = widget.newPickerWheel{
id=“pickerWheel”,
top=480, --258,
font=native.systemFontBold,
columns=columnData,
}
– slide the picker-wheel up
transition.to( picker, { time=250, y=258, transition=easing.outQuad } )
end
– create button to show pickerWheel
pickerButton = widget.newButton{
label = “Show Picker”,
left = 22, top = 285,
onRelease = onButtonRelease
}
– insert picker button into demoGroup
demoGroup:insert( pickerButton.view )
end
– create buttons table for the tab bar
local tabButtons = {
{
label=“tableView”,
up=“assets/tabIcon.png”,
down=“assets/tabIcon-down.png”,
width=32, height=32,
onPress=showTableView,
selected=true
},
{
label=“scrollView”,
up=“assets/tabIcon.png”,
down=“assets/tabIcon-down.png”,
width=32, height=32,
onPress=showScrollView,
},
{
label=“button”,
up=“assets/tabIcon.png”,
down=“assets/tabIcon-down.png”,
width=32, height=32,
onPress=showButtons,
}
}
– create a tab-bar and place it at the bottom of the screen
local demoTabs = widget.newTabBar{
top=display.contentHeight-50,
buttons=tabButtons
}
– insert tab bar into display group
tabBarGroup:insert( demoTabs.view )
– start off in the tableView tab
showTableView()[/lua]
[import]uid: 8271 topic_id: 27206 reply_id: 327206[/import]
