Button widget : problem with 9-Slice (ImageSheet) method

Hi,

I read this tutorial http://www.coronalabs.com/blog/2013/07/16/tutorial-stylizing-widgets-part-1/

and I tried to use the 9-Slice (ImageSheet) method for stylizing my button.

Results with this method are strange :

I have spaces between the different part of my button.

You can see a screenshot of this result in the attach file below.

Thank you for your help

Best,

Olivier

Hi Olivier,

Can you please post your code for the image sheet setup? Most likely it’s a simple fix.

Thanks,

Brent

Hi Brent

Here is my code :

local widget = require ("widget") local sheetInfo = require("slicesBt") local imageSheet = graphics.newImageSheet( "slicesBt.png", sheetInfo:getSheet() ) local mySliceBt = widget.newButton{ id = "bt", label = "Slice", sheet = imageSheet, font = "Arial", fontSize = 14, emboss = false, topLeftFrame = sheetInfo:getFrameIndex("topLeftFrame"), topMiddleFrame = sheetInfo:getFrameIndex("topMiddleFrame"), topRightFrame = sheetInfo:getFrameIndex("topRightFrame"), middleLeftFrame = sheetInfo:getFrameIndex("middleLeftFrame"), middleFrame = sheetInfo:getFrameIndex("middleFrame"), middleRightFrame = sheetInfo:getFrameIndex("middleRightFrame"), bottomLeftFrame = sheetInfo:getFrameIndex("bottomLeftFrame"), bottomMiddleFrame = sheetInfo:getFrameIndex("bottomMiddleFrame"), bottomRightFrame = sheetInfo:getFrameIndex("bottomRightFrame"), } mySliceBt.x = display.contentCenterX mySliceBt.y = display.contentCenterY

If you want I can post my imageSheet and my png files

I use TexturePacker.

Thanks for your help

best,

Olivier

Hi Olivier,

Thanks for the code. First, try setting a width and height for the button. Also, I notice that you don’t have the frames declared for the “over” state… for testing, you can just use the same frames for “default” like:

[lua]

topLeftOverFrame = sheetInfo:getFrameIndex(“topLeftFrame”),

topMiddleOverFrame = sheetInfo:getFrameIndex(“topMiddleFrame”),

–etc…

[/lua]

(notice that I just added the Over part in each one, but I’m setting the normal frame as “default” uses from the sheet)

Please try this and let me know what happens.

Best regards,

Brent

Hi, I’m having the same problem; space between sliced parts. I think it has to do with the way corona sdk scales the individual parts. I tried to set the sampling filter to either “nearest” or “linear” but problem persists.

Here’s the imagesheet:

Here’s the sheet info: (exported from TexturePacker)

SheetInfo.sheet = { frames = { { -- btn-green-up-1 x=90, y=45, width=8, height=8, }, { -- btn-green-up-2 x=2, y=45, width=76, height=8, }, { -- btn-green-up-3 x=80, y=45, width=8, height=8, }, { -- btn-green-up-4 x=90, y=2, width=8, height=30, }, { -- btn-green-up-5 x=2, y=2, width=76, height=30, }, { -- btn-green-up-6 x=80, y=2, width=8, height=30, }, { -- btn-green-up-7 x=90, y=34, width=8, height=9, }, { -- btn-green-up-8 x=2, y=34, width=76, height=9, }, { -- btn-green-up-9 x=80, y=34, width=8, height=9, }, }, sheetContentWidth = 100, sheetContentHeight = 55 }

And here’s the code:

local btn = widget.newButton{ id = "btn-start", width = 227, height = 44, emboss = false, font = "Arial", fontSize = 18, labelColor = { default = {0, 0, 0}, over = {255, 255, 255} }, labelYOffset = 2, label = "Play", sheet = self.sheet, topLeftFrame = skin:getFrameIndex("btn-green-up-1"), topMiddleFrame = skin:getFrameIndex("btn-green-up-2"), topRightFrame = skin:getFrameIndex("btn-green-up-3"), middleLeftFrame = skin:getFrameIndex("btn-green-up-4"), middleFrame = skin:getFrameIndex("btn-green-up-5"), middleRightFrame = skin:getFrameIndex("btn-green-up-6"), bottomLeftFrame = skin:getFrameIndex("btn-green-up-7"), bottomMiddleFrame = skin:getFrameIndex("btn-green-up-8"), bottomRightFrame = skin:getFrameIndex("btn-green-up-9"), topLeftOverFrame = skin:getFrameIndex("btn-green-up-1"), topMiddleOverFrame = skin:getFrameIndex("btn-green-up-2"), topRightOverFrame = skin:getFrameIndex("btn-green-up-3"), middleLeftOverFrame = skin:getFrameIndex("btn-green-up-4"), middleOverFrame = skin:getFrameIndex("btn-green-up-5"), middleRightOverFrame = skin:getFrameIndex("btn-green-up-6"), bottomLeftOverFrame = skin:getFrameIndex("btn-green-up-7"), bottomMiddleOverFrame = skin:getFrameIndex("btn-green-up-8"), bottomRightOverFrame = skin:getFrameIndex("btn-green-up-9") }

Here you can see a screengrab of the issue:

try adding 1 to the extrude value in TexturePacker before exporting that should fix your problem

Thanks, that almost did it for me. Testing with the corona simulator, in some resolutions it now looks just right, but in other resolutions (such as iPhone zoomed in) it looks like this:

Notice there are two 1-pixel horizontal gaps there. Can’t figure out how to get rid of them. Any idea?

That would suggest there is something slightly wrong with the images, what happens when you extrude by 2

Also do you have trim on? if so try turning that off. The top parts of the box have a transparent top line I’m wondering if that is causing the problem (top left is at 90x45 and is 8x8).

If all else fails have you tried it on a device, you do get occasionally different results.

Hi

@Brent : thank you for your answer, I tried setting a width and height for the button and I also declared the “over” state with  the same frames. But I still have my problem.

@Cublah : I tried adding 1 to the extrude value in TexturePacker before exporting and … it fixed the problem!!! Thank you Cublah for your help. How do you explain this? What is the role of this “extrude” parameter?

To all, thank you for your time and your help.

Best,

Olivier

@Oliver

It’s an openGL thing, the texture filtering is probably set to GL_LINEAR, setting it to GL_NEAREST fixes the problem but GL_LINEAR looks better. Extrude duplicates the outside of the texture all around by the value indicated (1 in this case)

Thanks Cublah for these explanations :slight_smile:

O.

I too just solved the problem! It appears that the height of the top parts has to be equal to the height of the bottom parts. Seems like an unnecessary constraint but oh well :slight_smile:

Thank you so much cublah

Hi :slight_smile:

another question

the widget button documentation says :

 

width, height (required)

Numbers. This is the width/height of the Button. If you are using Single frame button creation set these to the width/height of your image. If you are using 9-Piece Button Creation (default) you may set these to any width/height and the  button will scale accordingly.

 

I use 9-Pieces Button Creation but my button doesn’t scale accordingly like it says…

Have I miss something?

Thanks for your help!

Olivier

Hi @Olivier,

With 9-slice buttons, the width and height will specify the overall size of your button. This allows you to build buttons of basically any size, while the corner pieces remain smooth (and not stretched).

If this isn’t happening, please post your current code so I can inspect.

Thanks,

Brent

Hi Brent

thanks for your answer  :slight_smile:

when you say_ “the width and height will specify the overall size of your button”,_ I’m not sure to correctly understand.

In my case I have these dimensions for iPad Retina resolution :

  • bottomLeftFrame >  width : 74, height : 74
  • bottomMiddleFrame >  width : 2, height : 74
  • bottomRightFrame >  width : 74, height : 74
  • middleFrame >  width : 2, height : 2
  • middleLeftFrame >  width : 74, height : 2
  • middleRightFrame >  width : 74, height : 2
  • topLeftFrame >  width : 74, height : 74
  • topMiddleFrame >  width : 2, height : 74
  • topRightFrame >  width : 74, height : 74

I’m not sure, sorry, but In that case, I imagine that the overall size of my button may be :

width = bottomLeftFrame + bottomMiddleFrame + bottomRightFrame = 74 + 2 + 74 = 150

height = bottomLeftFrame + middleLeftFrame + topLeftFrame = 74 + 2 + 74 = 150

overall size of my button :

width = 150

height = 150

These are the dimensions I put on my code, but unfortunately, the result is a button of 150*150, regardless the label and font dimensions. No dynamic button size for me  :frowning:

If you want I can post you my imageSheet 

Thank you again

Olivier

----------------------------------------------------------------------------------------- -- -- main.lua -- ----------------------------------------------------------------------------------------- -- Your code here local widget = require ("widget") local sheetInfo = require("slicesBt") local imageSheet = graphics.newImageSheet( "slicesBt.png", sheetInfo:getSheet() ) local mySliceBt = widget.newButton{ id = "mySliceBt", label = "Slice button is there!", sheet = imageSheet, width = 150, height = 150, font = "Arial", fontSize = 14, emboss = false, labelColor = { default = { 0, 0, 0, 255 }, over = { 0, 0, 0, 150 }, }, topLeftFrame = sheetInfo:getFrameIndex("topLeftFrame"), topMiddleFrame = sheetInfo:getFrameIndex("topMiddleFrame"), topRightFrame = sheetInfo:getFrameIndex("topRightFrame"), middleLeftFrame = sheetInfo:getFrameIndex("middleLeftFrame"), middleFrame = sheetInfo:getFrameIndex("middleFrame"), middleRightFrame = sheetInfo:getFrameIndex("middleRightFrame"), bottomLeftFrame = sheetInfo:getFrameIndex("bottomLeftFrame"), bottomMiddleFrame = sheetInfo:getFrameIndex("bottomMiddleFrame"), bottomRightFrame = sheetInfo:getFrameIndex("bottomRightFrame"), topLeftOverFrame = sheetInfo:getFrameIndex("topLeftFrame"), topMiddleOverFrame = sheetInfo:getFrameIndex("topMiddleFrame"), topRightOverFrame = sheetInfo:getFrameIndex("topRightFrame"), middleLeftOverFrame = sheetInfo:getFrameIndex("middleLeftFrame"), middleOverFrame = sheetInfo:getFrameIndex("middleFrame"), middleRightOverFrame = sheetInfo:getFrameIndex("middleRightFrame"), bottomLeftOverFrame = sheetInfo:getFrameIndex("bottomLeftFrame"), bottomMiddleOverFrame = sheetInfo:getFrameIndex("bottomMiddleFrame"), bottomRightOverFrame = sheetInfo:getFrameIndex("bottomRightFrame"), } mySliceBt.x = display.contentCenterX mySliceBt.y = display.contentCenterY

Simply set the width and height to whatever size you want. It doesn’t need to be 150.

Thanks Wenzil for your answer.

But in my app, I have 11 different languages.

And labels have very different sizes from one language to another, for naming the same concept.

For example 

     [“en”] = “Try again”,

     [“fr”] = “Recommencer le défi”,

     [“es”] = “Volver a empezar el reto”,

     [“de”] = “Aufgabe neu beginnen”,

     [“pt”] = “Recomeçar o desafio”,

     [“it”] = “Ricomincia la sfida”,

     [“nl”] = “De opdracht opnieuw beginnen”,

     [“ru”] = “Выполнить задание еще раз”,

     [“ja”] = “チャレンジに再挑戦”,

     [“ko”] = " 문제 다시 풀기",

     [“zh”] = “重新开始”,

As you can see, “Try again” in English, and "“De opdracht opnieuw beginnen” in Netherlands, are quite different…

So I need something which is dynamic, accordingly to the label size.

I think slice button can do that, but I still haven’t found how to do it.

But I will find a solution soon I hope  :wink:

Olivier

Ah I see. I don’t think Corona’s widget 2.0 library supports auto-sized buttons. They have made it open-source though, so you could try adding that feature in. Alternatively you could try to find a 3rd-party ui library that supports that feature. WidgetCandy for example. (though it’s not free)

Of course the simplest solution would be to use a one-size-fits-all button. 

Cheers

I would like to point out that I see gaps in the default theme settings as supplied in the github version.

I believe pretty much all the widgets that use slices are prone to an error that can produce gaps: Rounding errors.

I have noticed a complete dearth of math.floor() etc for placing image slices on pixel boundaries, and I am fairly certain that this is the cause of gaps in between the slices.

Why am I fairly certain? Because due to bugs and lack of features I’ve had to write my own versions of pretty much all of the widgets, and I *always* math.floor() or math.ceil() my x, y, width and height values as appropriate, and I have yet to see a single gap between my pieces, even when using the same sprite sheet and images as the default widgets theme.

Gaps can happen between images in a sprite sheet if the relevant graphics don’t reach the edge of the tile (due to scaling up - I was the one who posted the solution to gaps between sprites in the various tile-based engine threads here), but this normally isn’t an issue here. For example, if someone creates a button using the default widget theme, they’ll notice that the button image is a single button. The slices are made in the spritesheet, but the important thing is that each button slice butts up against the correct other slices necessary - IE there is no gap in the image source at all. Hence the gaps can only come from badly positioned slices*.

* If you created your own sprite sheets for the widgets and you DO have the various slice parts with gaps between them, that is an ADDITIONAL potential source of gaps. Try using the default github theme and see if that still gives you gaps.

Hi @rakoonic,

Thanks for bringing up this observation. I’ve mentioned it to the engineers to investigate.

Brent