For what it is worth, here is the code I came up with to replace the segmented code.
It uses exactly the same syntax as the widgets segmented controls.
In fact, as I have it in my own library, all I have to do to convert old segmented controls to my one is:
- Change the library name (IE instead of local blah = widget.newSegmentedControl{} I do local blah = myLibrary.newSegmentedControl{} ).
- Add a ‘themeFile’ parameter to the parameter table you pass. This must be the lua path to the themefile exactly as you would set it up calling widget:setTheme(). Identical. Easy-peasy!
Important notes:
-
Use entirely at your own risk etc. etc. I have no error checking because I never ever make mistakes in my code. Errr… ;) Also, I can not be sure I’ve replicated all of the functionality because I’ve only done what I needed.
-
It does not have any clearing up. I will sort out an over-ride on the removeSelf() when I errr… know how to do it
-
Width and height NOW WORK! Height is exact to the pixel, width may have a few pixels difference (what it does is takes the total width, subtracts the left and right edges and uses the remainder divided by the number of segments, rounding down to the nearest integer). As such it will never be wider than what you specify, but might be 1 or 2 pixels thinner. Width overrides segmentWidth, by the way.
-
LabelColor works. Like buttons it is a table containing default and over values. Note I don’t bother with alpha, so it only looks at RGB values that you pass.
-
You can still call obj:setSegmentActive( integer ) to activate whichever segment you want.
-
You can also call obj:getSegmentActive() to return which is active. Duh!
-
The graphics can all be different sizes. I do assume that the sizes are the same for the active and inactive versions, and it makes more sense that they all have the same height too, but widths for left, right and middle can be whatever you want. Left and right never get stretched, just the middle does.
-
Any time you try to use silly values, the result is undefined but most likely won’t be pretty. One big no-no - don’t make the segments thinner than the text in them or things will look weird, but that should be obvious!
Enjoy, or not. You have the power!
[lua]function class.newSegmentedControl( params )
– Set up (reuse) image sheet
local theme = require( params.themeFile )
local sheet = require( theme._sheetData )
local sheetData = sheet:getSheet()
local sheetFrames = sheetData.frames
local imageSheet = graphics.newImageSheet( theme._sheetFile, sheetData )
– Create the control
local self = display.newGroup()
self.onPress = params.onPress or false
self.labelColor = params.labelColor
self.id = params.id or “better_segmentedControl”
local height = params.height
local width = params.width or false
– Create the press function
function self.onPressListener( event )
– Only process ‘began’ events
if event.phase ~= “began” then return false ; end
– Select the segment
self:setSegmentActive( event.target.segmentNumber )
– Call the onPress
if type( self.onPress ) == “function” then self.onPress( event ) ; end
end
– Calculate size
local frame = sheet:getFrameIndex( “segmentedControl_left” )
local leftSize = sheetFrames[frame].width
local frame = sheet:getFrameIndex( “segmentedControl_right” )
local rightSize = sheetFrames[frame].width
local offsetX = math.floor( ( rightSize - leftSize ) / 2 )
local totalSegments = #params.segments
local segmentWidth
if width == false then segmentWidth = params.segmentWidth or 90
else segmentWidth = math.max( math.floor( ( width - leftSize - rightSize ) / totalSegments ), 10 ) ; end
local segmentHalfWidth = math.floor( segmentWidth / 2 )
– Display the various controls
self.segments = {}
local dividerGroup = display.newGroup()
self:insert( dividerGroup )
for i = 1, totalSegments do
local segment = { inactive = {}, active = {}, label = false }
self.segments[i] = segment
local x = math.floor( ( ( i - 1 ) - totalSegments / 2 ) * segmentWidth ) + offsetX
– Create on and off versions
for k, v in pairs( { inactive = “”, active = “On” } ) do
– Create center
local frame = sheet:getFrameIndex( “segmentedControl_middle” … v )
local size = sheetFrames[frame]
local image = display.newImageRect( self, imageSheet, frame, segmentWidth, height or size.height )
image:setReferencePoint( display.CenterLeftReferencePoint )
image.x = x
segment[k][#segment[ k] + 1 ] = image
– Create left or right if needed
if i == 1 then
local frame = sheet:getFrameIndex( “segmentedControl_left” … v )
local size = sheetFrames[frame]
local image = display.newImageRect( self, imageSheet, frame, size.width, height or size.height )
image:setReferencePoint( display.CenterRightReferencePoint )
image.x = x
segment[k][#segment[ k] + 1 ] = image
end
if i == totalSegments then
local frame = sheet:getFrameIndex( “segmentedControl_right” … v )
local size = sheetFrames[frame]
local image = display.newImageRect( self, imageSheet, frame, size.width, height or size.height )
image:setReferencePoint( display.CenterLeftReferencePoint )
image.x = x + segmentWidth
segment[k][#segment[ k] + 1 ] = image
end
end
– Create the label
local label = display.newText( self, params.segments[i], 0, 0, params.labelFont or native.systemFont, params.labelSize or 12 )
label.x = x + segmentHalfWidth + ( params.labelXOffset or 0 )
label.y = ( params.labelYOffset or 0 )
segment.label = label
if self.labelColor then
label:setTextColor( self.labelColor.default[1], self.labelColor.default[2], self.labelColor.default[3] )
end
– Create the divider
if i > 1 then
local frame = sheet:getFrameIndex( “segmentedControl_divider” )
local size = sheetFrames[frame]
local image = display.newImageRect( dividerGroup, imageSheet, frame, size.width, height or size.height )
image:setReferencePoint( display.CenterLeftReferencePoint )
image.x = x - math.floor( size.width / 2 )
end
– Add in the event listener
for j = 1, #segment.inactive do
segment.inactive[j].segmentNumber = i
segment.inactive[j]:addEventListener( “touch”, self.onPressListener )
end
end
dividerGroup:toFront()
– Return the current segment
function self:getSegmentActive()
return self.currentItem
end
– Deselect the segment
function self:setSegmentInactive( item )
item = item or self.currentItem
local segment = self.segments[item]
for i = 1, #segment.active do
segment.active[i].isVisible = false
segment.inactive[i].isVisible = true
end
if self.labelColor then
segment.label:setTextColor( self.labelColor.default[1], self.labelColor.default[2], self.labelColor.default[3] )
end
end
function self:setSegmentActive( item )
– Deselect the current selection
self:setSegmentInactive()
– Set and then select the current one
self.currentItem = item
local segment = self.segments[item]
for i = 1, #segment.active do
segment.active[i].isVisible = true
segment.inactive[i].isVisible = false
end
if self.labelColor then
segment.label:setTextColor( self.labelColor.over[1], self.labelColor.over[2], self.labelColor.over[3] )
end
end
– Set up (hide all deselected, then select the required)
self.currentItem = 1
for i = 1, totalSegments do
self:setSegmentInactive( i )
end
self:setSegmentActive( params.defaultSegment or 1 )
– Position the group
self.x = params.left or 0
self.y = params.top or 0
if params.group then params.group:insert( self ) ; end
– Return the object
return self
end[/lua]