Segment Control Propeties & Methods

I am trying to use the segment control and somethings are working fine. However a few comments and posssible bugs.

I have set the id=99, but in the event the id ==nil. {code follows from modified corona sample}

I would also like to be able to access the segmentcontrol table of segments, but this is returned as nil. Likewise I would like to be able to change the segment labels at run time as well as treat the segment table as a normal table determining total number of entries using #target.segments.Maybe also change the number of segments.

Ideally new and additional methods to access the table and make the required changes.

id bug follows


local function segmentedControlListener( event )
        local target = event.target
        print (target.id)—print nil here
        statusText.text = "Segmented Control\nself.segmentNumber = " … target.segmentNumber
    end
    
    – Create a default segmented control (using widget.setTheme)
    local segmentedControl = widget.newSegmentedControl {
        left = 10,
        top = 0,
        segments = { “Corona”, “Widget”, “Demo” },
        defaultSegment = 1,
        id=99, – added a new id value [string I assume]
         segmentWidth = 88,
        onPress = segmentedControlListener
    }

I did a quick test.  In your listener event.id is a type “userdata” but this isn’t your segement’s id.  event.target.id is not being set.  But here is the quandary that I’m not willing to call a bug.   event.target is about the segment that was pressed, not the whole controller.  There is no .id per segment.  I don’t know an easy way to get to the parent object from the listener.

As for new API’s to get / set the label.  They would need to be added.  This would require a feature request to be filed at http://feedback.coronalabs.com or you can get the Open Source Lua code for them and implement your own, which would be the quicker option.

Rob

Got it! as google might say…

I am not into open source changes due to lack of resources here, but thanks [I assume its all C ++ coding etc]. B)

I had thought it was planned to be accessible due to docs stating "


id (optional)

String. An optional identification to assign to the segmented control. Default is widget_segmentedControl.


I have just discovered there are no setEnabled(  ) methods either. I need to disable the whole segmentcontrol while showing an overlay.

Thinking more on this I have put in code to react as if disabled by checking states of the userscreen…

I will add these to feedback however  if you agree ? I still feel access to the internal segment table would be really powerfull. At the moment I am re-creating the control each timeI need a label change, with no real hits in performance.

Thanks Rob for your usual fast responses , even at weekends  :slight_smile: .

Out of interest, and I guess a slight nervousness that I am doing something  that is documented as not feesible…

Docs states the following…


To conserve texture memory, a Segmented Control can only be created from an image sheet.

The Segmented Control does not support scaling nor changing of the width/height via .width or .height.


I am just creating with theme widget_theme_ios7 and not using an image sheet.

I create the control and postion and resize using  .height. to fit toolbar height comfortably

So I am risking this is ok in the future…

Any idea why the clause/restriction since it works on Version 2015.2612 (2015.4.14)

Actually the widget library is pure Corona SDK Lua.  Nothing extremely weird.   You can look at the code here:  https://github.com/coronalabs/framework-widget

As for disabling the segmented controller, if you’re using a composer.showOverlay() just set .isModal = true on it.  We will create an invisible rectangle as the background of the overlay that will consume all touch and tap events which keeps things under the overlay from being interacted with.

The 2nd post about image sheets, this is if you wanted to create your own custom skin for it.  We use image sheets internally for the default theme looks.  You can position the widget using it’s .x and .y properties, but trying to do:   segController.width = 50 is not supported.  You pass those in when you create the widget as parameters.  Afterwords, there is no guarantee that the techniques used to resize display objects will work on the widgets.  The widgets use display objects to construct the widget, but the widget itself is not a display object.

Rob

Another weird segment control situation…

I am loosing divider lines between segments, every alternative click of a segment.

Here is  sample code to recreate the app experience…


local widget = require( “widget” )


local function reFormatScreen(Defaultsegment,PressEvent) --simulate part of reformatting screen


    local Highlightsegment=Defaultsegment
    if segmentedControl~=nil then
        segmentedControl:removeSelf()
        segmentedControl=nil
    end
     segmentedControl = widget.newSegmentedControl {
        left = 10,
        top = 50,
        segments = { “1”, “2”, “3”,“4” },
        defaultSegment = Highlightsegment,
         segmentWidth = 40,
        onPress = PressEvent
    }
 print("reFormat setting\nHighLight segmentNumber = " … Highlightsegment)
end
    ---------------------------------------------------------------------------------------------

    local  function segmentedControlListener( event )


        local target = event.target
        print("Segmented Listener\nsegmentNumber = " … target.segmentNumber)
        reFormatScreen(target.segmentNumber,segmentedControlListener)    
    end


    reFormatScreen(1,segmentedControlListener)


Interesting.  If you just create the segmented controller, and not go through all of this re-create when you’re processing the touch of the segment, it works just fine.  This seems to be an artifact of removing the controller in the middle of handling it’s event.  Again I’m not sure the use case of what you’re doing, but if you must do it this way, perhaps put the function that is recreating the segmented controller inside a timer so that the listener has a chance to complete before you remove it’s parent object.

Rob

The code is a mock up of the app’s complex route.

The app is a storyboard app going from scene to scene.

To keep the same layout of the toolbar for the user on different scenes the whole screen layout is removed and recreated at each scene. So from a user’s view the toolbar is the same one, but, now I started using the segment control [re-coding from newbutton] the user will notice the scene toolbar changing now because the segments border disappears evey other click.

The scene to scene at the moment has no delay and just looks like card flipping.If I put it in a timer for the segmentControl  delaying for the segmentControl the card flipping effect slows down.

A better design[now knowing this hic-up] would have had the toolbar stay and just change internal list. I dont want to recode all that at this point. It willl be quicker to fall back to a set of newbuttons. Unfortunaly I was trying to keep up with Apple’s modernisations at each release of IOS.

What are my chances of getting this accepted as a bug,or, can you give me a clue where in the https://github.com/coronalabs/framework-widget the artifact but be addressed. Is it due to pixels of the image sheet [where is that?]? Or calculation in the dividerFrame or…

Alec

Thinking more on this I cannot do anything different with my app as the segmentComponent is ‘supplied’. SoI have to fix the artifact problem, some how, or fall back.


Reasons [unless you educate me otherwise…]

  1. Unable to change the number of segments once the control is created.

  2. Unable to change the labels  once the control is created.

  3. To have different segments per scene with different labels I would need to create as many controls as scenes ahead of the scenes and ‘hide’ them off the display and move them in as required to avoid recreating each time [all/each controls are created in one main routine called when a scene is created]

------

I have done a mock up test case for your interest [and bug fix ;) ].

I can send it to you if you let me know how, or where and when.

The test case shows three scenes across the app, white [main.lua], yellow and blue.

White has 4 segments/tabs - 3 tabs run within the white scene, a fourth starts a new scens Yellow.

Yellow scene has only 3 tabs. 2 run within the yellow scene, a third tab starts a new scene Blue.

Blue scene has 6 tabs. 4 run within blue scene, another tab recreates  scene Yellow, while another tab recreates Blue scene.

So this allows us to test the borders missing [under several sequences-not scene dependant] by using different tabs the borders disappear on blue or yellow etc depending on  the sequence of the tabs clicked. Basically the tab borders dissapear every other new scene creation … very odd and unrelated I would think!

Each scene requests a  new and  its own control.

 Each scene calls a common global scope routine in main.lua to create a new control for that scene

Phew. :wacko:…

Alec

PS This is storyboard, not composer!

In the app you’re trying to build (not a test app), does the labels and number of segments change from scene to scene?  Is there a reason to not use a tabBar for this?

Yes to your first question.

I guess the only reason is that the tabbar looked like an overkill, with icons and, specing each tab etc, compared to the simple segmentControl.  Examples I have tried make the tabbar look  a bit oold  IOS 5/6  with black fill.

But you are probably right in asking the question, I’ll go look and try that and see if I can customise to look like the segmentControl.

Alec

Is my experience with segment control relatd to this post in the forum?

https://forums.coronalabs.com/topic/55976-segmented-control-with-custom-image-sheet-does-not-render-dividers-correctly/

I’m going to call this a bug.  I’ll file the bug report since I have a good example that demos the issue.

I looked at the code and I couldn’t see a quick fix for this.

Edit: Case 40571

Rob

Very much appreciated…

I do have my latest demo, more realistic, within storyboard as well. if you need it …shout.

I found if you recreated the segmentControl in one scene [Blue scene] at the createscene event it is ok for that scene, but if done later the same odd divider missing actions. The other scene [yellow] missed dividers if recreated in  any startup event, so this may be an indication there is some cause/ link between number of segements and a timing issue.

Thanks

Alec

It seems to me that the odd numbered created works as expected, and the even creates do not.

Rob

Yes the first test case makes that as stated.

I have sent you another test by email that shows the same as above, unless you do another change in the newly sent test Blue Scene. Recreating in CreateScene in blue blue works ok. Do the same in Yellow , it doesnt.

Its driving me made…

Alec

I haven’t received anything.  Did you email it to me or support AT?

Looks like it went to support@coronalabs.com with case number. 40571.

Apologies

I have bypassed the problem using this code

I recreate the segmentControl each scene to change labels and number of segments by have a global segment lis

e.g. #_G.ui.segmentedControlsegments={“label1”,“label2”, …}

This is then used at create time of segement control. After that I run the following code

–=== mock up set of dividers to over come  the bug
        local dloop
        local lines={}
        local linesGroup = display.newGroup()
        for dloop =1,#_G.ui.segmentedControlsegments-1 do  --get label list size from global list

–_G.ui.segmentedControlsegments is assigned to segmentcontrols segments option at segmentControl creation
          local x=segmentedControl.x -
                    (math.floor(#_G.ui.segmentedControlsegments*0.5)*segmentWidth) +
                    segmentWidth*dloop                                                            --ok for my case  only?
            local y1=segmentedControl.y-segmentedControl.height*0.5
            local y2=segmentedControl.y+segmentedControl.height*0.5
            local divider=display.newLine( x,y1 ,x,y2)
            divider:setStrokeColor(R,G,B,255)-- R,G,B set  to color required
            linesGroup:insert(divider)
            lines[#lines]= divider  --not sure this does what I think --i.e. addresablity to each line if required
        end
        group:insert(linesGroup)
        --=======================

I did a quick test.  In your listener event.id is a type “userdata” but this isn’t your segement’s id.  event.target.id is not being set.  But here is the quandary that I’m not willing to call a bug.   event.target is about the segment that was pressed, not the whole controller.  There is no .id per segment.  I don’t know an easy way to get to the parent object from the listener.

As for new API’s to get / set the label.  They would need to be added.  This would require a feature request to be filed at http://feedback.coronalabs.com or you can get the Open Source Lua code for them and implement your own, which would be the quicker option.

Rob