new segmentedControl replacement code here.

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:

  1. Change the library name (IE instead of local blah = widget.newSegmentedControl{} I do local blah = myLibrary.newSegmentedControl{} ).
  2. 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:

  1. 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.

  2. 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  :slight_smile:

  3. 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.

  4. 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.

  5. You can still call obj:setSegmentActive( integer ) to activate whichever segment you want.

  6. You can also call obj:getSegmentActive() to return which is active. Duh!

  7. 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.

  8. 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]

Har, this is what I get for copy and pasting without checking:

Line 3 should be:

   local theme       = require( params.themeFile )

Har, this is what I get for copy and pasting without checking:

Line 3 should be:

   local theme       = require( params.themeFile )

Hi @rakoonic, thanks for your contribution. Your comment : 

  1. You can still call obj:setSegmentActive( integer ) to activate whichever segment you want.

made me wonder. Is obj:setSegmentActive( integer ) available in the CL supplied segmentedControl widget? I was trying to see how to programmatically set the segment chosen and could not find how and then I came across your post. 

Would you consider pushing your version in GitHub so that CL staff can consider making use of your improvements? Many many thanks!!!

Hi @rakoonic, thanks for your contribution. Your comment : 

  1. You can still call obj:setSegmentActive( integer ) to activate whichever segment you want.

made me wonder. Is obj:setSegmentActive( integer ) available in the CL supplied segmentedControl widget? I was trying to see how to programmatically set the segment chosen and could not find how and then I came across your post. 

Would you consider pushing your version in GitHub so that CL staff can consider making use of your improvements? Many many thanks!!!