Is this possible? Apple’s typical search box has rounded ends but the textfield and textbox both have square ends which can’t have their border color changed. [import]uid: 8271 topic_id: 26905 reply_id: 326905[/import]
Really? No one? [import]uid: 8271 topic_id: 26905 reply_id: 110170[/import]
Will post my solution soon. [import]uid: 8271 topic_id: 26905 reply_id: 111343[/import]
Any luck Matt? [import]uid: 147340 topic_id: 26905 reply_id: 122563[/import]
Yes, sorry - I’ve been posting my solutions in other posts and on the code exchange. Take a look here, where I’ve listed all my work:
http://springboardpillow.blogspot.co.uk/2012/06/building-ios-app-in-corona-labs-sdk.html [import]uid: 8271 topic_id: 26905 reply_id: 122585[/import]
The Search box article is not there. I get this message (Sorry! This page can’t be accessed.)
http://developer.anscamobile.com/forum/2012/06/15/ios-style-search-box
Do you have a working link ?? [import]uid: 147340 topic_id: 26905 reply_id: 122589[/import]
This is really weird, but the original post apparently can’t be viewed by some. It can be by me, however. Here it is as a gratuitous repost:
For this function you will need to take the existing Improved Widget Demo from the code exchange:
http://developer.anscamobile.com/code/improved-widgetdemo-sample
This improvement adds the iOS styled search box and search results to the (improved) Corona sample code WidgetDemo.
To use you need to add the following four images to the WidgetDemo directory and update the menustructure.lua and replace the menu.lua files.
To use in the app simply tap the search bar at the top, after pulling it down in the table view, and you’ll see the search bar. Type in the search bar and you’ll see items randomly generated from the PerformSearch function in menustructure.file. Hitting cancel will return to the previous menu.
You can add a search item row to any menu structure, but of course it looks better if you make it the first row and set the defaultscroll=2, to hide it, initially.
Your function to perform the search will receive three parameters:
parentitem: The menu item from the row which launched the search panel
term: The search term typed into the search box
callback: The function to call with your list of search items. This table is just like any other menu structure table.
The function used to search (below called ‘PerformSearch’) can make network connections and populate the results with the callback function parameter.
Please note: This is not fully tested on device or Apple simulator and the images will need some adjustment, but consider that a developer exercise.
Here’s how it should look:
The files to save into WidgetDemo:
defaultcancel.png: http://content.screencast.com/users/HoraceBury/folders/Default/media/185ebfca-beeb-49e1-83b1-fad26b80162e/defaultcancel.png
overcancel.png: http://content.screencast.com/users/HoraceBury/folders/Default/media/833b2acd-9276-4267-84a1-53f056013397/overcancel.png
searchcancel.png: http://content.screencast.com/users/HoraceBury/folders/Default/media/a0b768d4-f712-42fb-a691-d640f00fab91/searchcancel.png
searchwith.png: http://content.screencast.com/users/HoraceBury/folders/Default/media/c9039574-4ffd-418f-9220-b9eed5d70a54/searchwith.png
Replace the rootmenu table with the following additional function and updated rootmenu…
menustructure.lua:
[lua]function PerformSearch( parentitem, term, callback )
local list = {}
for i=1, math.random(1, 7) do
list[#list+1] = { id="", text=term…’ '…math.random(100,999), iscategory=false, dataitem=nil }
end
callback( list )
end
rootmenu = {
title=“Products”, defaultscroll=2, hasindex=true, hasscrollbar=true, canscrolltotop=true,
{ id="", text=“Search Bar”, issearch=true, dataitem=PerformSearch, },
{ id="", text=“Find”, iscategory=true, dataitem=nil, index=“F” },
{ id="", text=“By Product”, iscategory=false, dataitem=byproduct, candelete=true },
{ id="", text=“By Job”, iscategory=false, dataitem=byjobfunction, candelete=true },
{ id="", text=“By Region”, iscategory=false, dataitem=byregion, candelete=true },
{ id="", text=“Search”, iscategory=true, dataitem=nil, index=“S” },
{ id="", text=“Companies With…”, iscategory=false, dataitem=function(d,f) f(GetTestSubMenu()) end },
{ id="", text=“Info”, iscategory=true, dataitem=nil, index=“I” },
{ id="", text=“About…”, iscategory=false, dataitem=nil },
{ id="", text=“Magazines”, iscategory=true, dataitem=nil, index=“M” },
{ id="", text=“The Times”, iscategory=false, dataitem=nil },
{ id="", text=“The Independent”, iscategory=false, dataitem=nil },
{ id="", text=“The Sun”, iscategory=false, dataitem=nil },
{ id="", text=“News Feeds”, iscategory=true, dataitem=nil, index=“N” },
{ id="", text=“BBC News”, iscategory=false, dataitem=GetBbcNewsRss },
}[/lua]
Replace the whole menu.lua…
menu.lua:
[lua]-- menu
function newMenu( parent, rootdata, x, y, width, height )
– renders a title bar for a submenu
local function newTopBar( parent, title, scrollToBack, scrollToTop )
– local this bar
local group = display.newGroup()
group.widgets = {}
parent:insert( group )
– clean out the widgets
function group:clean()
for i=#group.widgets, 1, -1 do
group.widgets[i]:removeSelf()
group.widgets[i] = nil
end
group:removeSelf()
end
– status bar touch pad
if (scrollToTop) then
local touchbar = display.newRect( group, 0, 0, display.contentWidth, display.statusBarHeight )
function touchbar:touch( event )
if (event.phase == “began” and event.y <= display.statusBarHeight) then
scrollToTop()
end
return true
end
touchbar:addEventListener( “touch”, touchbar )
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, width = 320
}
group:insert( titleBar.view )
group.widgets[#group.widgets+1] = titleBar
– create embossed text to go above toolbar
local titleText = display.newEmbossedText( title, 0, 0, native.systemFontBold, 20, { 255 } )
titleText:setReferencePoint( display.CenterReferencePoint )
titleText.x = display.contentWidth * 0.5 – (display.contentWidth * 0.5) – + x
titleText.y = 44 – + (titleBar.y + titleBar.height * 0.5)
group:insert( titleText )
group.widgets[#group.widgets+1] = titleText
– onRelease listener for back button
local function onBackRelease( event )
if (scrollToBack) then
scrollToBack( group.clean )
end
return true
end
– create ‘back’ button to be placed on toolbar
if (parent.parent.numChildren > 1) then
local backButton = widget.newButton{
label = “Back”,
left = 5, top = 28,
style = “backSmall”,
onRelease = onBackRelease
}
group:insert( backButton.view )
group.widgets[#group.widgets+1] = backButton
end
end – newTopBar
– renders a search input box for a search panel
local function newSearchBox( parent, cancel, scrollToTop, searchCallback )
– local this bar
local group = display.newGroup()
group.widgets = {}
parent:insert( group )
– declare the input text box
local inputbox = nil
– clean out the widgets
function group:clean()
inputbox:removeSelf()
for i=#group.widgets, 1, -1 do
group.widgets[i]:removeSelf()
group.widgets[i] = nil
end
group:removeSelf()
end
– status bar touch pad
if (scrollToTop) then
local touchbar = display.newRect( group, 0, 0, display.contentWidth, display.statusBarHeight )
function touchbar:touch( event )
if (event.phase == “began” and event.y <= display.statusBarHeight) then
scrollToTop()
end
return true
end
touchbar:addEventListener( “touch”, touchbar )
end
– search box image
local searchimg = display.newImage( group, “searchcancel.png” )
searchimg.xScale, searchimg.yScale = .5, .5
searchimg.x, searchimg.y = display.contentCenterX, searchimg.height/2-2
– onRelease listener for back button
local function onCancelRelease( event )
if (cancel) then
cancel( group.clean )
end
return true
end
– create ‘cancel’ button to be placed on toolbar
local cancelButton = widget.newButton{
label = “”,
left = 260, top = 27,
–style = “backSmall”,
default=“defaultcancel.png”,
over=“overcancel.png”,
width=110/2, height=58/2,
onRelease = onCancelRelease
}
group:insert( cancelButton.view )
group.widgets[#group.widgets+1] = cancelButton
– input box listener function
local function textListener( event )
– if (event.phase == “editing” or event.phase == “began” or event.phase == “ended”) then
if (event.phase == “editing”) then
–[[
local list = {
title=“Results”, defaultscroll=1, hasindex=false, hasscrollbar=false, canscrolltotop=true,
{ id="", text=event.text…"_One", iscategory=false, dataitem=nil, index=“F” },
{ id="", text=event.text…"_Two", iscategory=false, dataitem=nil, candelete=true },
{ id="", text=event.text…"_Three", iscategory=false, dataitem=nil, candelete=true },
{ id="", text=event.text…"_Four", iscategory=false, dataitem=nil, candelete=true },
{ id="", text=event.text…"_Five", iscategory=false, dataitem=nil, candelete=true },
}
]]–
searchCallback( event.text )
end
return true
end
– create native text input box
inputbox = native.newTextBox( 30, 30, 200, 25, textListener )
inputbox.isEditable = true
inputbox.align = “left”
inputbox.size = 16
end – newSearchBox
– creates the submenu or search panel
local function newSubMenu( contentdata, issearch )
– container for all submenu components
local submenugroup = display.newGroup()
parent:insert( submenugroup )
– timers etc
local posCheckTimer = nil
local adjustScrollBar = nil
– position the submenugroup
if (issearch == true) then
submenugroup.x, submenugroup.y = parent[parent.numChildren-1].x, parent[parent.numChildren-1].y
else
submenugroup.x, submenugroup.y = (parent.numChildren-1) * display.contentWidth, 0
end
– table view
local list = nil
– create tableView widget
list = widget.newTableView{
top = display.statusBarHeight + 44,
width = display.contentWidth,
height = 366,
maskFile = “assets/mask-320x366.png”
}
– keeps track of the number of rows
list.totalRowCount = 0
– keeps track of the total height of the widget content
list.totalheight = 0
– remove this if using later than build 2012.826
local function deleteAllRows()
while (list.totalRowCount > 0) do
list:deleteRow( 1 )
list.totalRowCount = list.totalRowCount - 1
end
end
– list of scroll index items
local function populateTableView( menudata, isnewdata )
local scroll = {}
– onEvent listener for the tableView
local function onRowTouch( event )
local row = event.target
local rowGroup = event.view
if (not row.isCategory) then
if (event.phase == “swipeLeft” and menudata[event.index].candelete == true) then
transition.to( rowGroup.del, {time=rowGroup.del.transtime,maskX=-(rowGroup.del.width/2+1),onComplete=rowGroup.del.setActive} )
elseif (event.phase == “swipeRight” and menudata[event.index].candelete == true) then
transition.to( rowGroup.del, {time=rowGroup.del.transtime,maskX=rowGroup.del.width/2+1,onComplete=rowGroup.del.setInactive} )
elseif (event.phase == “release” and not row.isCategory) then
row.reRender = true
print( “You touched row #” … event.index…" - ‘"…menudata[event.index].text…"’" )
– do population of submenu
local menuitem = menudata[event.index]
if (menuitem.dataitem ~= nil) then
– get the submenu’s data and add the new sub menu
– this will shift the parent group left to show a deeper submenu
local dataitem = menuitem.dataitem
– populate the submenu
function callback(dataitem)
– create the submenu or search item tableView
newSubMenu( dataitem, menuitem.issearch )
– use animation to show the next tableView
if (menuitem.issearch == true) then
– lay the search panel over the top of the current tableView menu (should be improved later to look like the smooth contacts list animation)
– ie: right now, do nothing (the search will just snap into place over the current tableView widget)
else
– slide the current tableView widget left to show the submenu animating into position
transition.to( parent, {time=300, x=parent.x-display.contentWidth} )
transition.to( topGroup, {time=300, x=parent.x-display.contentWidth} )
end
end
– if dataitem is a function, call it to get the data to put in the submenu, otherwise just populate the submenu
– if the dataitem is a function it must callback the passed in function to populate the submenu, this allows for network traffic delays
– the callback function does not need to be called, if the dataitem function wants to switch to another tab, for example
if (type(dataitem) == “function”) then
– if the item is a search, populate it with the initial search term
if (menuitem.issearch == true) then
– call the client function as an search
– callback( dataitem( {phase=“began”, term=""} ) )
callback( menuitem )
else
– call the client function with the parent item to get the submenu items
dataitem( menuitem, callback )
end
else
– populate directly because the submenu items are known here
callback( dataitem )
end
end
end
end
return true
end – onRowTouch
– 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
if (event.index == 1 and menudata[event.index].issearch == true) then
– is a search bar
row.searchimg = display.newImage( rowGroup, “searchwith.png” )
row.searchimg.xScale, row.searchimg.yScale = .5, .5
row.height = row.searchimg.height/2
row.searchimg.x, row.searchimg.y = display.contentCenterX, row.searchimg.height/4
else
– is regular bar
row.title = textFunction( menudata[event.index].text, 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 )
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+1
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
– must insert everything into event.view:
rowGroup:insert( row.title )
end
end – onRowRender
– assign data to the rows
function createContent()
– Add rows
for i=1, #menudata do
local rowHeight, rowColor, lineColor, isCategory = 64
local menuitem = menudata[i]
if (menuitem.iscategory) 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
list.totalRowCount = list.totalRowCount + 1
– insert the row into the tableView widget
list:insertRow{
onEvent=onRowTouch,
onRender=onRowRender,
height=rowHeight,
isCategory=isCategory,
rowColor=rowColor,
lineColor=lineColor,
issearch=true
}
– index can be a string or a function to return a string - string can be one char
if (menuitem.index ~= nil) then
local scrollitem = menuitem.index
if (type(scrollitem) == “function”) then
scrollitem = scrollitem( menuitem )
end
scroll[#scroll+1] = { index=i, char=scrollitem }
end
end
function addAlphaStrip(parent, callback)
local strip = display.newGroup()
parent:insert( strip )
strip.x, strip.y = display.contentWidth - 15, display.statusBarHeight+50
local alpha = display.newRoundedRect( strip, -10, 0, 20, display.contentHeight - 128, 10 )
alpha:setFillColor( 224, 224, 224 )
local size = 13.3
for i=65, 90 do
local index = i-64
local function touch(event)
for s=1, #scroll do
if (scroll[s].char == string.char(i)) then
list:scrollToIndex( scroll[s].index, 300 )
break
end
end
return true
end
local rect = display.newRect( strip, 0, 0, 40, size )
rect.x, rect.y = 0, 10+(i-65)*size
rect.alpha = 0
rect.isHitTestable = true
local letter = display.newText(strip, string.char(i), 0, 0, native.systemFont, 10)
letter:setTextColor(106, 115, 125)
letter.x, letter.y = 0.5, 10+(i-65)*size
rect:addEventListener( “touch”, touch )
end
end
if (isnewdata and menudata.hasindex) then addAlphaStrip( submenugroup ) end
– auto scroll to initial position
if (menudata.defaultscroll) then list:scrollToIndex( menudata.defaultscroll, 0 ) end
local currentpos = list:getScrollPosition()
list.maxscrolltop = 366-list.totalheight+24
–[[scroll bar handling]]–
local function addScrollBar()
local scrollbar = display.newRoundedRect( submenugroup, display.contentWidth - 5, display.statusBarHeight+50, 2.5, display.contentHeight - 128, 2.5 )
scrollbar:setFillColor( 255,0,0 )
scrollbar.lastchangetime = system.getTimer()
local 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
– 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 – addScrollBar
if (isnewdata and menudata.hasscrollbar) then addScrollBar() end
end – populateTableView
– clear current tableView content
deleteAllRows()
list.totalRowCount = 0
list.totalheight = 0
– create the content
createContent()
end – populateTableView
– scroll to top function
if (contentdata.canscrolltotop) then
submenugroup.scrollToTop = function()
if (contentdata.defaultscroll) then
list:scrollToIndex( contentdata.defaultscroll, 400 )
else
list:scrollToIndex( 1, 400 )
end
end
end
– if this is a search panel provide the search bar at the top, if not provide a title bar
if (issearch == true) then
– is a search panel
– stops the search and removes the search panel
local function cancelSearch( onComplete )
print(‘cancelled’,parent.numChildren)
if (posCheckTimer) then
timer.cancel( posCheckTimer )
posCheckTimer = nil
end
Runtime:removeEventListener( “enterFrame”, adjustScrollBar )
onComplete()
list:removeSelf()
list = nil
submenugroup:removeSelf()
end
– gets the search results from the search callback and populates the tableview
local function searchCallback( searchterm )
– called by the menu’s search function to populate the tableView
function doPopulate( list )
populateTableView( list, false )
end
– call the menu’s search function to get the search results table
contentdata.dataitem( contentdata, tostring(searchterm), doPopulate )
end
– create search bar
newSearchBox( submenugroup, cancelSearch, submenugroup.scrollToTop, searchCallback )
else
– is a regular sub/menu
– scroll to origin - this is actually the back button effect
local function scrollToBack( onComplete )
function clean()
if (posCheckTimer) then
timer.cancel( posCheckTimer )
posCheckTimer = nil
end
Runtime:removeEventListener( “enterFrame”, adjustScrollBar )
onComplete()
list:removeSelf()
list = nil
submenugroup:removeSelf()
end
transition.to( parent, {time=300, x=parent.x+display.contentWidth, onComplete=clean} )
end
– create title bar
newTopBar( submenugroup, contentdata.title, scrollToBack, submenugroup.scrollToTop )
end – (issearch == true)
– insert widget into demoGroup
submenugroup:insert( list.view )
– populate the tableView with initial data
populateTableView( contentdata, true )
end – newSubMenu
newSubMenu( rootdata )
end[/lua]
[import]uid: 8271 topic_id: 26905 reply_id: 122592[/import]
Any luck Matt? [import]uid: 147340 topic_id: 26905 reply_id: 122563[/import]
Yes, sorry - I’ve been posting my solutions in other posts and on the code exchange. Take a look here, where I’ve listed all my work:
http://springboardpillow.blogspot.co.uk/2012/06/building-ios-app-in-corona-labs-sdk.html [import]uid: 8271 topic_id: 26905 reply_id: 122585[/import]
The Search box article is not there. I get this message (Sorry! This page can’t be accessed.)
http://developer.anscamobile.com/forum/2012/06/15/ios-style-search-box
Do you have a working link ?? [import]uid: 147340 topic_id: 26905 reply_id: 122589[/import]
This is really weird, but the original post apparently can’t be viewed by some. It can be by me, however. Here it is as a gratuitous repost:
For this function you will need to take the existing Improved Widget Demo from the code exchange:
http://developer.anscamobile.com/code/improved-widgetdemo-sample
This improvement adds the iOS styled search box and search results to the (improved) Corona sample code WidgetDemo.
To use you need to add the following four images to the WidgetDemo directory and update the menustructure.lua and replace the menu.lua files.
To use in the app simply tap the search bar at the top, after pulling it down in the table view, and you’ll see the search bar. Type in the search bar and you’ll see items randomly generated from the PerformSearch function in menustructure.file. Hitting cancel will return to the previous menu.
You can add a search item row to any menu structure, but of course it looks better if you make it the first row and set the defaultscroll=2, to hide it, initially.
Your function to perform the search will receive three parameters:
parentitem: The menu item from the row which launched the search panel
term: The search term typed into the search box
callback: The function to call with your list of search items. This table is just like any other menu structure table.
The function used to search (below called ‘PerformSearch’) can make network connections and populate the results with the callback function parameter.
Please note: This is not fully tested on device or Apple simulator and the images will need some adjustment, but consider that a developer exercise.
Here’s how it should look:
The files to save into WidgetDemo:
defaultcancel.png: http://content.screencast.com/users/HoraceBury/folders/Default/media/185ebfca-beeb-49e1-83b1-fad26b80162e/defaultcancel.png
overcancel.png: http://content.screencast.com/users/HoraceBury/folders/Default/media/833b2acd-9276-4267-84a1-53f056013397/overcancel.png
searchcancel.png: http://content.screencast.com/users/HoraceBury/folders/Default/media/a0b768d4-f712-42fb-a691-d640f00fab91/searchcancel.png
searchwith.png: http://content.screencast.com/users/HoraceBury/folders/Default/media/c9039574-4ffd-418f-9220-b9eed5d70a54/searchwith.png
Replace the rootmenu table with the following additional function and updated rootmenu…
menustructure.lua:
[lua]function PerformSearch( parentitem, term, callback )
local list = {}
for i=1, math.random(1, 7) do
list[#list+1] = { id="", text=term…’ '…math.random(100,999), iscategory=false, dataitem=nil }
end
callback( list )
end
rootmenu = {
title=“Products”, defaultscroll=2, hasindex=true, hasscrollbar=true, canscrolltotop=true,
{ id="", text=“Search Bar”, issearch=true, dataitem=PerformSearch, },
{ id="", text=“Find”, iscategory=true, dataitem=nil, index=“F” },
{ id="", text=“By Product”, iscategory=false, dataitem=byproduct, candelete=true },
{ id="", text=“By Job”, iscategory=false, dataitem=byjobfunction, candelete=true },
{ id="", text=“By Region”, iscategory=false, dataitem=byregion, candelete=true },
{ id="", text=“Search”, iscategory=true, dataitem=nil, index=“S” },
{ id="", text=“Companies With…”, iscategory=false, dataitem=function(d,f) f(GetTestSubMenu()) end },
{ id="", text=“Info”, iscategory=true, dataitem=nil, index=“I” },
{ id="", text=“About…”, iscategory=false, dataitem=nil },
{ id="", text=“Magazines”, iscategory=true, dataitem=nil, index=“M” },
{ id="", text=“The Times”, iscategory=false, dataitem=nil },
{ id="", text=“The Independent”, iscategory=false, dataitem=nil },
{ id="", text=“The Sun”, iscategory=false, dataitem=nil },
{ id="", text=“News Feeds”, iscategory=true, dataitem=nil, index=“N” },
{ id="", text=“BBC News”, iscategory=false, dataitem=GetBbcNewsRss },
}[/lua]
Replace the whole menu.lua…
menu.lua:
[lua]-- menu
function newMenu( parent, rootdata, x, y, width, height )
– renders a title bar for a submenu
local function newTopBar( parent, title, scrollToBack, scrollToTop )
– local this bar
local group = display.newGroup()
group.widgets = {}
parent:insert( group )
– clean out the widgets
function group:clean()
for i=#group.widgets, 1, -1 do
group.widgets[i]:removeSelf()
group.widgets[i] = nil
end
group:removeSelf()
end
– status bar touch pad
if (scrollToTop) then
local touchbar = display.newRect( group, 0, 0, display.contentWidth, display.statusBarHeight )
function touchbar:touch( event )
if (event.phase == “began” and event.y <= display.statusBarHeight) then
scrollToTop()
end
return true
end
touchbar:addEventListener( “touch”, touchbar )
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, width = 320
}
group:insert( titleBar.view )
group.widgets[#group.widgets+1] = titleBar
– create embossed text to go above toolbar
local titleText = display.newEmbossedText( title, 0, 0, native.systemFontBold, 20, { 255 } )
titleText:setReferencePoint( display.CenterReferencePoint )
titleText.x = display.contentWidth * 0.5 – (display.contentWidth * 0.5) – + x
titleText.y = 44 – + (titleBar.y + titleBar.height * 0.5)
group:insert( titleText )
group.widgets[#group.widgets+1] = titleText
– onRelease listener for back button
local function onBackRelease( event )
if (scrollToBack) then
scrollToBack( group.clean )
end
return true
end
– create ‘back’ button to be placed on toolbar
if (parent.parent.numChildren > 1) then
local backButton = widget.newButton{
label = “Back”,
left = 5, top = 28,
style = “backSmall”,
onRelease = onBackRelease
}
group:insert( backButton.view )
group.widgets[#group.widgets+1] = backButton
end
end – newTopBar
– renders a search input box for a search panel
local function newSearchBox( parent, cancel, scrollToTop, searchCallback )
– local this bar
local group = display.newGroup()
group.widgets = {}
parent:insert( group )
– declare the input text box
local inputbox = nil
– clean out the widgets
function group:clean()
inputbox:removeSelf()
for i=#group.widgets, 1, -1 do
group.widgets[i]:removeSelf()
group.widgets[i] = nil
end
group:removeSelf()
end
– status bar touch pad
if (scrollToTop) then
local touchbar = display.newRect( group, 0, 0, display.contentWidth, display.statusBarHeight )
function touchbar:touch( event )
if (event.phase == “began” and event.y <= display.statusBarHeight) then
scrollToTop()
end
return true
end
touchbar:addEventListener( “touch”, touchbar )
end
– search box image
local searchimg = display.newImage( group, “searchcancel.png” )
searchimg.xScale, searchimg.yScale = .5, .5
searchimg.x, searchimg.y = display.contentCenterX, searchimg.height/2-2
– onRelease listener for back button
local function onCancelRelease( event )
if (cancel) then
cancel( group.clean )
end
return true
end
– create ‘cancel’ button to be placed on toolbar
local cancelButton = widget.newButton{
label = “”,
left = 260, top = 27,
–style = “backSmall”,
default=“defaultcancel.png”,
over=“overcancel.png”,
width=110/2, height=58/2,
onRelease = onCancelRelease
}
group:insert( cancelButton.view )
group.widgets[#group.widgets+1] = cancelButton
– input box listener function
local function textListener( event )
– if (event.phase == “editing” or event.phase == “began” or event.phase == “ended”) then
if (event.phase == “editing”) then
–[[
local list = {
title=“Results”, defaultscroll=1, hasindex=false, hasscrollbar=false, canscrolltotop=true,
{ id="", text=event.text…"_One", iscategory=false, dataitem=nil, index=“F” },
{ id="", text=event.text…"_Two", iscategory=false, dataitem=nil, candelete=true },
{ id="", text=event.text…"_Three", iscategory=false, dataitem=nil, candelete=true },
{ id="", text=event.text…"_Four", iscategory=false, dataitem=nil, candelete=true },
{ id="", text=event.text…"_Five", iscategory=false, dataitem=nil, candelete=true },
}
]]–
searchCallback( event.text )
end
return true
end
– create native text input box
inputbox = native.newTextBox( 30, 30, 200, 25, textListener )
inputbox.isEditable = true
inputbox.align = “left”
inputbox.size = 16
end – newSearchBox
– creates the submenu or search panel
local function newSubMenu( contentdata, issearch )
– container for all submenu components
local submenugroup = display.newGroup()
parent:insert( submenugroup )
– timers etc
local posCheckTimer = nil
local adjustScrollBar = nil
– position the submenugroup
if (issearch == true) then
submenugroup.x, submenugroup.y = parent[parent.numChildren-1].x, parent[parent.numChildren-1].y
else
submenugroup.x, submenugroup.y = (parent.numChildren-1) * display.contentWidth, 0
end
– table view
local list = nil
– create tableView widget
list = widget.newTableView{
top = display.statusBarHeight + 44,
width = display.contentWidth,
height = 366,
maskFile = “assets/mask-320x366.png”
}
– keeps track of the number of rows
list.totalRowCount = 0
– keeps track of the total height of the widget content
list.totalheight = 0
– remove this if using later than build 2012.826
local function deleteAllRows()
while (list.totalRowCount > 0) do
list:deleteRow( 1 )
list.totalRowCount = list.totalRowCount - 1
end
end
– list of scroll index items
local function populateTableView( menudata, isnewdata )
local scroll = {}
– onEvent listener for the tableView
local function onRowTouch( event )
local row = event.target
local rowGroup = event.view
if (not row.isCategory) then
if (event.phase == “swipeLeft” and menudata[event.index].candelete == true) then
transition.to( rowGroup.del, {time=rowGroup.del.transtime,maskX=-(rowGroup.del.width/2+1),onComplete=rowGroup.del.setActive} )
elseif (event.phase == “swipeRight” and menudata[event.index].candelete == true) then
transition.to( rowGroup.del, {time=rowGroup.del.transtime,maskX=rowGroup.del.width/2+1,onComplete=rowGroup.del.setInactive} )
elseif (event.phase == “release” and not row.isCategory) then
row.reRender = true
print( “You touched row #” … event.index…" - ‘"…menudata[event.index].text…"’" )
– do population of submenu
local menuitem = menudata[event.index]
if (menuitem.dataitem ~= nil) then
– get the submenu’s data and add the new sub menu
– this will shift the parent group left to show a deeper submenu
local dataitem = menuitem.dataitem
– populate the submenu
function callback(dataitem)
– create the submenu or search item tableView
newSubMenu( dataitem, menuitem.issearch )
– use animation to show the next tableView
if (menuitem.issearch == true) then
– lay the search panel over the top of the current tableView menu (should be improved later to look like the smooth contacts list animation)
– ie: right now, do nothing (the search will just snap into place over the current tableView widget)
else
– slide the current tableView widget left to show the submenu animating into position
transition.to( parent, {time=300, x=parent.x-display.contentWidth} )
transition.to( topGroup, {time=300, x=parent.x-display.contentWidth} )
end
end
– if dataitem is a function, call it to get the data to put in the submenu, otherwise just populate the submenu
– if the dataitem is a function it must callback the passed in function to populate the submenu, this allows for network traffic delays
– the callback function does not need to be called, if the dataitem function wants to switch to another tab, for example
if (type(dataitem) == “function”) then
– if the item is a search, populate it with the initial search term
if (menuitem.issearch == true) then
– call the client function as an search
– callback( dataitem( {phase=“began”, term=""} ) )
callback( menuitem )
else
– call the client function with the parent item to get the submenu items
dataitem( menuitem, callback )
end
else
– populate directly because the submenu items are known here
callback( dataitem )
end
end
end
end
return true
end – onRowTouch
– 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
if (event.index == 1 and menudata[event.index].issearch == true) then
– is a search bar
row.searchimg = display.newImage( rowGroup, “searchwith.png” )
row.searchimg.xScale, row.searchimg.yScale = .5, .5
row.height = row.searchimg.height/2
row.searchimg.x, row.searchimg.y = display.contentCenterX, row.searchimg.height/4
else
– is regular bar
row.title = textFunction( menudata[event.index].text, 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 )
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+1
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
– must insert everything into event.view:
rowGroup:insert( row.title )
end
end – onRowRender
– assign data to the rows
function createContent()
– Add rows
for i=1, #menudata do
local rowHeight, rowColor, lineColor, isCategory = 64
local menuitem = menudata[i]
if (menuitem.iscategory) 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
list.totalRowCount = list.totalRowCount + 1
– insert the row into the tableView widget
list:insertRow{
onEvent=onRowTouch,
onRender=onRowRender,
height=rowHeight,
isCategory=isCategory,
rowColor=rowColor,
lineColor=lineColor,
issearch=true
}
– index can be a string or a function to return a string - string can be one char
if (menuitem.index ~= nil) then
local scrollitem = menuitem.index
if (type(scrollitem) == “function”) then
scrollitem = scrollitem( menuitem )
end
scroll[#scroll+1] = { index=i, char=scrollitem }
end
end
function addAlphaStrip(parent, callback)
local strip = display.newGroup()
parent:insert( strip )
strip.x, strip.y = display.contentWidth - 15, display.statusBarHeight+50
local alpha = display.newRoundedRect( strip, -10, 0, 20, display.contentHeight - 128, 10 )
alpha:setFillColor( 224, 224, 224 )
local size = 13.3
for i=65, 90 do
local index = i-64
local function touch(event)
for s=1, #scroll do
if (scroll[s].char == string.char(i)) then
list:scrollToIndex( scroll[s].index, 300 )
break
end
end
return true
end
local rect = display.newRect( strip, 0, 0, 40, size )
rect.x, rect.y = 0, 10+(i-65)*size
rect.alpha = 0
rect.isHitTestable = true
local letter = display.newText(strip, string.char(i), 0, 0, native.systemFont, 10)
letter:setTextColor(106, 115, 125)
letter.x, letter.y = 0.5, 10+(i-65)*size
rect:addEventListener( “touch”, touch )
end
end
if (isnewdata and menudata.hasindex) then addAlphaStrip( submenugroup ) end
– auto scroll to initial position
if (menudata.defaultscroll) then list:scrollToIndex( menudata.defaultscroll, 0 ) end
local currentpos = list:getScrollPosition()
list.maxscrolltop = 366-list.totalheight+24
–[[scroll bar handling]]–
local function addScrollBar()
local scrollbar = display.newRoundedRect( submenugroup, display.contentWidth - 5, display.statusBarHeight+50, 2.5, display.contentHeight - 128, 2.5 )
scrollbar:setFillColor( 255,0,0 )
scrollbar.lastchangetime = system.getTimer()
local 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
– 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 – addScrollBar
if (isnewdata and menudata.hasscrollbar) then addScrollBar() end
end – populateTableView
– clear current tableView content
deleteAllRows()
list.totalRowCount = 0
list.totalheight = 0
– create the content
createContent()
end – populateTableView
– scroll to top function
if (contentdata.canscrolltotop) then
submenugroup.scrollToTop = function()
if (contentdata.defaultscroll) then
list:scrollToIndex( contentdata.defaultscroll, 400 )
else
list:scrollToIndex( 1, 400 )
end
end
end
– if this is a search panel provide the search bar at the top, if not provide a title bar
if (issearch == true) then
– is a search panel
– stops the search and removes the search panel
local function cancelSearch( onComplete )
print(‘cancelled’,parent.numChildren)
if (posCheckTimer) then
timer.cancel( posCheckTimer )
posCheckTimer = nil
end
Runtime:removeEventListener( “enterFrame”, adjustScrollBar )
onComplete()
list:removeSelf()
list = nil
submenugroup:removeSelf()
end
– gets the search results from the search callback and populates the tableview
local function searchCallback( searchterm )
– called by the menu’s search function to populate the tableView
function doPopulate( list )
populateTableView( list, false )
end
– call the menu’s search function to get the search results table
contentdata.dataitem( contentdata, tostring(searchterm), doPopulate )
end
– create search bar
newSearchBox( submenugroup, cancelSearch, submenugroup.scrollToTop, searchCallback )
else
– is a regular sub/menu
– scroll to origin - this is actually the back button effect
local function scrollToBack( onComplete )
function clean()
if (posCheckTimer) then
timer.cancel( posCheckTimer )
posCheckTimer = nil
end
Runtime:removeEventListener( “enterFrame”, adjustScrollBar )
onComplete()
list:removeSelf()
list = nil
submenugroup:removeSelf()
end
transition.to( parent, {time=300, x=parent.x+display.contentWidth, onComplete=clean} )
end
– create title bar
newTopBar( submenugroup, contentdata.title, scrollToBack, submenugroup.scrollToTop )
end – (issearch == true)
– insert widget into demoGroup
submenugroup:insert( list.view )
– populate the tableView with initial data
populateTableView( contentdata, true )
end – newSubMenu
newSubMenu( rootdata )
end[/lua]
[import]uid: 8271 topic_id: 26905 reply_id: 122592[/import]
hi horace. i cannot open the following link.
http://developer.anscamobile.com/code/improved-widgetdemo-sample
can you give other link that available?
I hope that this is what you’re looking for:
https://dl.dropboxusercontent.com/u/10254959/WidgetDemo.public.2012-09-06.001.zip
Though it has been a long time since I worked on that and iOS does not work that way any more.
horace. i try to compile the source code of widget demo.
however, the error that i got is :
attempt to index field ‘colours’ (a nil value) stack traceback.
i try to search any solution on Internet, but still i cannot solve the problem.
Yes, I expect there will be problems. I doubt you’ll find solutions to my specific code bugs on the internet because my code is not well known. I think you should simply look at the logic of the code and recreate it in your own code. There are two main problems (aside from it being very old and I’ve forgotten what it does): Gfx2.0 is not compatible with it, some of the libraries (especially the widget.*) will not be compatible with it. Considering all the problems you’ll hit and the fact that iOS no longer works that way, I really would consider using a different UI design and dumping the code. If I have time and you insist in knowing how it works, I’ll see if I can describe it, but I’m afraid I simply don’t have the time to get the demo working because I would have to change almost every line in the project.
hi horace. i cannot open the following link.
http://developer.anscamobile.com/code/improved-widgetdemo-sample
can you give other link that available?
I hope that this is what you’re looking for:
https://dl.dropboxusercontent.com/u/10254959/WidgetDemo.public.2012-09-06.001.zip
Though it has been a long time since I worked on that and iOS does not work that way any more.
horace. i try to compile the source code of widget demo.
however, the error that i got is :
attempt to index field ‘colours’ (a nil value) stack traceback.
i try to search any solution on Internet, but still i cannot solve the problem.
Yes, I expect there will be problems. I doubt you’ll find solutions to my specific code bugs on the internet because my code is not well known. I think you should simply look at the logic of the code and recreate it in your own code. There are two main problems (aside from it being very old and I’ve forgotten what it does): Gfx2.0 is not compatible with it, some of the libraries (especially the widget.*) will not be compatible with it. Considering all the problems you’ll hit and the fact that iOS no longer works that way, I really would consider using a different UI design and dumping the code. If I have time and you insist in knowing how it works, I’ll see if I can describe it, but I’m afraid I simply don’t have the time to get the demo working because I would have to change almost every line in the project.