NewProgressView not completely filled

I created a progress bar using NewProgressView but setting a progress value to 1 does not completely fill the bar. I suspect it is something to do with my image sheet and any insight would be appreciated.

Code:

local options = {           width = 83,           height = 45,           numFrames = 6,           sheetContentWidth = 500,           sheetContentHeight = 45       }       local progressSheet = graphics.newImageSheet( "images/widget-progress-view3.png", options )         local bar = widget.newProgressView(           {             sheet = progressSheet,             fillOuterLeftFrame = 1,             fillOuterMiddleFrame = 2,             fillOuterRightFrame = 3,             fillOuterWidth = 83,             fillOuterHeight = 45,             fillInnerLeftFrame = 4,             fillInnerMiddleFrame = 5,             fillInnerRightFrame = 6,             fillWidth = 12,             fillHeight = 45,             left = someValue,             top = someValue,             width = 230,             isAnimated = true           }         )                local progressValue = quantity / 100         bar:setProgress( progressValue )

Prints:

0.75 0.5 0.05 0.5 1

Attached what is displayed and the image sheet.

Can you make a quick sample project that includes a main.lua, build.settings, config.lua, your code and your artwork and put it in a zip file and share the link here. I think it will be easier if we can see the whole package.

Rob

Thanks Rob, I will get that for you asap.

Hi Rob,

Here comes an extract of the project I am working on.

The progress bars are first initialized (with value 0) and then updated with some progress (some at 5%, others at 50% and 100%).

Let me know if you need more details.

Cheers 

Hi @J@V0. Skinning a progressView probably has to be one of the more complex concepts that is really hard to describe how to make it work.

The color blocks in our diagram are to show you the frame shapes, but the actual usable parts are the two outer end caps and are basically drawn at the size they are. The middle block is stretched to fill the gap between to the two end caps.  These are the first three frames in the image sheet. You need to pretend the color blocks are not there and just focus on the pink frame outline.  These just draw the outer border.  It would be near impossible to use a gradient for this.

Next, frames 4-6 are designed to be the fill inside the pink frame outlines. Frame 4 and 6 are the end-caps that fill the space inside the end caps in frames 1 and 3. Frame 5, like frame 2 is stretched/scaled to show the actual progress. I don’t think you can make this work with arrows like you’re trying to do.

Finally, each frame must be the exact same width with no gaps. If you have 75px frames, the overall sheet must therefore equal 300px (75*6). Your image sheets don’t add up correctly.  83px frames = 498px total sheet width.

If you give up on the diamond, you probably could draw a gradient underneath, with mask to make it match the shape of the outer frame, but you’re going to have to a solid bar for the actual progress.

Rob

Thank it’s clearer now, I have to say that I was really confused by the color blocks!

I have a few follow-up questions.

Does it matter how width I draw the right and left caps of the fill area? In your doc they are pretty narrow in the orange and purple areas.

I gave up on the diamond and drew the gradient underneath, and the result is what I would have expected but it doesn’t look as a player would expect:

The other option was to use the gradient as the fill area, but again, it always goes all the way from red to green:

What I would like to achieve is that the gradient is cropped at the progress value (e.g. yellow for 55% progress). Can you think of any way to do that? Can we draw the “missing progress” instead? So I could put a mask on the 45% of the right side (taking a 55% progress as an example). Something like:

The only way I can think of is to use my own rounded rectangles and position them so they cover the gradient background, not using ProgressViews…

It does matter how deep you put the end caps. I’ve not looked at the code for that widget in a long time, but doing so will cause some of the area inside the frame to never really represent 0% and 100%. It may give it the visual idea that the progress bar may be going from 10% to 90%.

The reason your gradient doesn’t work is because we scale the middle frame of the inner block. So if your progress is low, the gradient will be compressed into a narrow block like you’re seeing. If you’re near 100% it will be stretched out.

If I’m being 100% honest here, the widget.* library was designed to behave like native looking widgets would look. They really were not designed to be skinned. Some things skin easier, others not so much or it takes a large amount of parameters to make something work when taking a more low-level approach will actually be easier to implement.

This is a great example. Create an image with your gradient and rounded corners and draw it with display.newImageRect() then create a display.newRect() will the blue fill color you want and draw it on top of the gradient image in a way that the blue rect fits inside the window, then anchor it to the right side and use the .width parameter to set the width of the top rectangle to the width you need.

I’ve not tested this code, but perhaps something like this:

local gradiant1 = display.newImageRect("gradient,png", 110, 50); gradiant1.x = 110 gradiant1.y = 50 gradiant1.anchorX = 1.0 local colorBlock = display.newRect(0, 0, 100, 45) colorBlock:setFillColor(0,0.2,0.4); colorBlock.anchorX = 1.0 colorBlock.x = 105 colorBlock.width = 100 - progressPercentage

That would in theory keep the rectangle anchored to the right side while you size the rectangle to block out the inverse of the percentage. By making the rectangle 100px, it makes it easy to convert to a percentage. 

You get the effect you want without jumping through hoops to make a widget behave your own way.

You could even take this concept, drop it in a function named “myProgressView” (or whatever works for you), pass in the X, Y, and width (so you could even scale the images as needed). Of if you’re creative, you could make it a little more object like by using a table and having a .init() or .new() function, and a .setProgressAmount() function. You’re really only limited by your own creativity here.

Rob

Rob

I went for my own function as you suggested in the last paragraph and my code is pretty similar to your sample. Thanks for the help!