newSwitch strange behaviour

Radio buttons with and without an image sheet work properly - including changing state with setState()

Checkbox with and without in image sheet work properly - including changing state with setState()

The issue is with the onOff.  Standard configuration works as expected - including setting initial state and changing it with setState.

Adding in an image sheet, the control is drawn properly, and tapping on the control moves properly back and forth, transitioning properly, between on and off.  Initial state setting is held ok, but the control is opposite.  ie: set to false (off) - control shows true (on).  calling setState with the opposite state, moves the control to the other side, and isOn is changed to the new state.  It appears that the first tap on the control does not transition the control - though we do get the onPress event, but does change the isOn variable which brings things back into sync. Subsequent presses switch back and forth properly.  It also appears that the  offDirection option has no affect on this.

Dave

  1. Can you make a small sample, zip it up, and share it with us so we can see what you’re doing?  This is the easiest way to get a fix/help.

(Use the full editor when posting and you’ll have the option to attach a zip file.)

2.  Your post is a bit hard to read.  I’m seeing what looks like at least two questions in there.  You might want to consider bullet lists and clear numbered questions in the future.  (Lazy folk like myself give up when the post starts to wander or look like a run-on.)

A great format for posts like this is:

  • What I did.
  • What I saw.
  • What I expected to see.
  • Why I think it is wrong.
  • What I did to debug it.

( Tip: Provide links; Don’t assume we know what features you’re talking about)

  1. My interpretation of your post:
  • What you did - You made toggle and radio buttons using image sheets and the widget.* newSwitch() function (always provide links so we can be sure we understand what you mean and are referring to).
    • You then tried to pre-toggle the state using the setState() function. 
  • What you saw - The state toggled when you called setState(), but when you later clicked the button… something went wrong.  This is where I’m unclear.
  • … 

attached is the sample.

it has 2 toggles.  1 std, 1 with image sheet.

both have initialSwitchState set to false.

starting app - std shows false (off) state, imageSheet shows true (on)

after 5 secs, timer calls a routine to change state to true in both.

both switch state  (from code, both go from false to true - but std goes to visual true, imageSheet goes from visual true to false.

isOn on both read as true

tapping std, changes state back to false, and control transitions properly.

tapping imageSheet changes state back to false, control does not transition.  now imageSheet shows visual false, and isOn is false.

tapping imageSheet again changes state to true and control transitions to visual true.  control is now in sync.

Simulator look ok.  You need to run this on a device.

Thanks.

Dave

I will look after I finish eating

Note: That last note about needing to run on device is suspect to me.  It should behave exactly the same on device or in the simulator.

Usually, when I see variances between simulator and device (regarding touch based code) there is a coding issue.

I’m still looking at this, but I’m pretty sure you’re checking the state of the button too soon.  

One thing I’m seeing is that sometimes the switch made with your custom art sometimes becomes hard to tap/touch after you force-set the state.

This behavior is NOT consistent.

Yea, I thought so too. However, the sample code is so small, I see nothing that’s out of line. It is literally a side-by-side.  It’s easy to see the image sheet one not move on the first tap, while the onRelease function reporting the event. 

 

Also on startup, you easily see the std shows false, and the image sheet shows on. 

 

Thanks for looking at it.

I’m having trouble getting this to show up consistently.

Note: I further reduced and modified your code (not a fan of introducing extra elements like composer.* and more code; Also like to be able to see all code in one place for debug.)

main.lua

local widget = require("widget") -- local w = display.contentWidth;local h = display.contentHeight local fullW = display.actualContentWidth;local fullH = display.actualContentHeight local unusedWidth = fullW - w;local unusedHeight = fullH - h \_L = math.floor(0 - (unusedWidth \* 0.5));\_T = math.floor(0 - (unusedHeight \* 0.5)) \_R = math.floor(w + (unusedWidth \* 0.5));\_B = math.floor(h + (unusedHeight \* 0.5)) \_CW = \_R;\_CH = \_B;\_FullHeight = \_B;\_CX = math.floor(\_CW \* 0.5);\_CY = math.floor(\_CH \* 0.5) -- local widgetTheme = require("widgetTheme\_green\_sheet") local sdzImageSheet = graphics.newImageSheet( "images/widgetTheme.png", widgetTheme:getSheet() ) -- ============================================================== -- local function onSwitchPress(event) local switch = event.target local id = switch.id local onState = (switch.isOn) and "ON" or "OFF" -- print( "\nSwitch with ID '" .. id .. "' is: " .. onState .. " @ " .. system.getTimer() ) end -- local function dummySetState( button, on ) local switch = button local id = switch.id local onState0 = (switch.isOn) and "ON" or "OFF" local function onComplete() local onState1 = (switch.isOn) and "ON" or "OFF" -- print( "\nBefore - Switch with ID '" .. id .. "' is: " .. onState0 .. " @ " .. system.getTimer() ) print( "After - Switch with ID '" .. id .. "' is: " .. onState1 .. " @ " .. system.getTimer() ) end -- switch:setState( { isOn = on, isAnimated = true, onComplete = onComplete } ) end -- ============================================================== local switch1 = widget.newSwitch( { x = 100, y = 100, style = "onOff", id = "switch1", onRelease = onSwitchPress, initialSwitchState = false, }) -- local switch2 = widget.newSwitch( { x = 200, y = 100, style = "onOff", id = "switch2", onRelease = onSwitchPress, initialSwitchState = false, sheet = sdzImageSheet, onOffBackgroundFrame = 60, onOffBackgroundWidth = 165, onOffBackgroundHeight = 30, onOffMask = "images/widgetTheme\_onOff\_mask.png", onOffHandleDefaultFrame = 63, -- 63, onOffHandleOverFrame = 63, --64, onOffOverlayFrame = 65, onOffOverlayWidth = 84, onOffOverlayHeight = 32, --offDirection = "left" }) -- timer.performWithDelay(1500, function() dummySetState( switch1, true ) end, 1) timer.performWithDelay(1500, function() dummySetState( switch2, true ) end, 1)

Sorry. 

I can’t see a issue that I can point to and I can’t reproduce the issue I saw with toggling the second switch after setState() was called.

Dang.  As soon as I said that, I reproduced it consistently in the simulator by using

View As -> Borderless -> IPhone @2x (640 x 960)

I suspect an issue with your art, otherwise the issue would show up with both buttons.

I have taken this as far as I can.  I’m attaching my modified version of your app.

I added a folder called more with additional art (standard art) for you in case you want to experiment.

I’m using the onRelease method, which means that I’m supposed to be getting the isOn value after it has been changed.

the best thing to do is to actually watch the control move, via the timer, and then tap the control.  Have adb running and it reports what the sample app is doing - and you can see the event generated without the tab moving. 

Also on startup, you can see how the control doesnt show the initial state correctly.  The std does, the imageSheet doesnt.  When the timer fires, both controls switch - std reporting correctly, imageSheet incorrectly.  Tap the std and it moves, and reports the change correctlty.  Tap the imageSheet and it reports the change, but doesnt move.  tap it a second time and it reports the change and moves - now matching the proper state.

again, thanks.

Dave

OK.  The answer came to me.  It is your mask.

DO NOT ever make size variant masks.  Delete the @2x and @3x masks and the button will start behaving properly.

Thanks,

All of your posts came in while I was typing the other.

I’ll take a look at your art and see what the differences could be.  Thanks for the attempt.

Dave

Here is a super-minimal example that works perfectly.

Post back if you don’t think so, but I don’t see any errors in behavior.

**UPDATED** Attached minimal2.zip

Your mask was still wrong.  I fixed it.  Gotta be super careful about following masking rules.

Thank.  I appreciate your looking at it.  It works perfectly in the simulator.  I built it and pushed it to a device.  Same problem as before.

I also tried it with the halo dark theme and got exactly the same results.  Fine in the simulator and broken on the device.  I know it’s crazy because I suspect that corona uses the halo theme as a default for android.

What was wrong with the mask?  This was from a pack purchased from the marketplace.

You need to make sure all masks follow the mask guidelines.

w and h - divisible by 4

at least three pixels of opaque black on all edges.

Your 1x mask has translucent pixels on the 3rd pixel from top and bottom

Sorry to correct you but masks do not need to be divisible by 4 anymore.

I create all my masks at 1x size and with 4px of solid black around.  I reduce these to 2 bit but you can use 8 bit if you want semi-transparent masking.

So for a 100x100px image (200x200px @2x and 400x400px @4x) I will create a single mask of 104x104px.

@sgs - Don’t be sorry.  Has the guideline changed? 

https://docs.coronalabs.com/api/library/graphics/newMask.html#image-mask-requirements

If so, one of us should ask that the docs be updated.

I don’t know if you intended to, but you example is divisible by 4 :wink:

So it is!  I think it all changed when “power of 2” image requirements stopped being a thing.

In DC I have over 700 masks and they are just asset size + 4px each edge.

To be honest, with a base tile size of 72x36px my width is always dividable by 4, but height is only occasionally.