Hi,
I am considering to create a reusable custom widget for display of a value next to a symbol.
Something that can be used for scores, counts of diamonds/stars/… , a time counter.
Representing what this looks like in ASCII art:
(S) 12345 or (S 13456) = (S) is the symbol, (—) maybe a bounding box
Questions:
Is there something that already exists (with 1 creation function) that I should use?
Solar2D Group objects don’t have a width/height by default, but widget.Button does.
Can simply set/maintain a width/height property manually for my group, or is something more sophisticated needed?
I appreciate your help for getting me on the right path (I’m new to Solar2D).
Thanks! -ivec
I’m not aware of something that already does this, but it should be pretty simple. If I understand you right, you want something that can work like this:
local scoreWidgetMaker = require "scoreWidgetMaker"
local scoreWidget = scoreWidgetMaker.new({image = "symbol.png", defaultScore = 0})
scoreWidget.setScore(10)
If so, then make a file called scoreWidgetMaker.lua (or whatever you want to call it), and put this in it:
local scoreWidgetMaker = {}
function scoreWidgetMaker.new(params)
local group = display.newGroup()
local symbol = display.newImage(params.image)
local text = display.newText({text = params.defaultScore})
group:insert(symbol)
group:insert(text)
-- set sizes and positions of symbol and text, etc
function group.getScore()
return text.text
end
function group.setScore(newScore)
text.text = newScore
-- since score can be string of varyiable length, you'll need to reposition things here.
end
return group
end
return scoreWidgetMaker
I haven’t tested but it looks ok. Obviously, it’s not finished, you’ll have to put in the details yourself to get it to work the way you want.
A key question I had is: how can I manage (make available) a width and height for my group-based widget? To support screen rotation/orientation, I have a layout function that positions a collection of widgets (e.g. even spacing …). It works smoothly with the provided widget.button, button.width and button.height return expected values. But a Group does not have a width or height.
When I set-up the elements of my widget-group, can I just manually set values group.width and group.height to make these attributes available to users of my widget? Or is something more complex needed?
Display Groups do have width and height, but they are basically reflecting what’s inside the group. If you have a single rectangle of 50 for its width and height, then that’ll be the same values when you access these properties for the group. You can change these properties of the group but it will change the way the objects look.
A good usage for groups is to have all its children sit at 0,0 or an offset of these, and then position/rotate the group as needed.
--[[
display.newImageText({
img="",
imgDir="",
text="",
textFont="",
textSize=
}, x, y, w, h)
]]--
display.newImageText = function(ImageTextOptions, x, y, w, h)
local Options = ImageTextOptions or {}
local Image = Options.img or "Icon.png"
local ImageDir = Options.imgDir or system.ResourceDirectory
local Text = Options.text or "Test"
local TextFont = Options.textFont or native.systemFont
local TextSize = Options.textSize or 18
local newGroup = display.newGroup()
newGroup.anchorChildren = true
newGroup.x = x
newGroup.y = y
newGroup.img = display.newImage(newGroup, Image, ImageDir, 0, 0 )
newGroup.img.width = w
newGroup.img.height = h
local TextSettings = {
text = Text,
x = 0,
y = 0,
font = TextFont,
fontSize = TextSize,
align = "center"
}
newGroup.text = display.newText(TextSettings)
newGroup:insert(newGroup.text)
newGroup.text:setFillColor(0,0,0)
return newGroup
end
local MyButton = display.newImageText({
text="my Button",
}, _W*0.5, _H*0.5, 35, 25) -- set there **width or height** manually
MyButton.text.size = 28
MyButton.img.width = 200 -- set there **width** manually
MyButton.img.height = 200 -- set there **height** manually
--MyButton:removeSelf() -- or remove Group of objs
--MyButton=nil
Thank you Juni, Redbol,
It looks like all should be easier than I though: the width and height of a group automatically reflect the contained items - which might just work for me.
At the level above the widgets, when the screen is resized (rotated or other), I now use the function below to help reposition my widgets dynamically across the top of the screen.
Great people and support in this forum - thank you for your time ! -ivec
function M.screenBox()
local scrL = display.safeScreenOriginX;
local scrT = display.safeScreenOriginY;
return {
L = scrL,
T = scrT,
R = scrL + display.safeActualContentWidth,
B = scrT + display.safeActualContentHeight,
}
end
-- Utility to reposition widgets at the top of a screen/box, e.g. when screen is resized:
-- layoutItems( nil, box, widget1, 5, widget2, nil, widget3, nil )
-- A "number" value indicates a fixed spacing between two items; the 'extra' space is shared across the "nil" entries
-- Note: it seems wiser to use e.g. -1 as a value, instead of nil, for "variable spacing"
function M.layoutItems(box,...)
local defSpc = 10
local refW = box.R-box.L
local totW = 0
local maxH = 1
local nilCnt = 0
local altSpc=nil
-- scan through the provided elements to compute total width
for i=1,#arg do local v = arg[i] --i,v in ipairs(arg) do
--for i,v in ipairs(arg) do -- the "iterator" version seems to stop at the first 'nil' element...
local t = type(v) -- string number table nil
if t=="table" then
totW = totW + (altSpc or defSpc) + v.width
altSpc=nil
maxH = math.max(maxH,v.height)
elseif t=="nil" then
nilCnt = nilCnt+1
elseif t=="number" then
altSpc=v
end
end
totW = totW + (altSpc or defSpc)
local scal = (totW>refW) and (refW/totW) or nil -- scaling if exceeded length
local nilSpc = (totW<refW) and (refW-totW)/nilCnt or 0 -- note: at least one "nil" is required
local xPos = box.L
local yPos = box.T + 0.5*maxH
altSpc=nil
-- position the widgets
for i=1,#arg do local v = arg[i] --i,v in ipairs(arg) do
local t = type(v) -- string number table nil
if t=="table" then
local w = v.width
xPos = xPos + (altSpc or defSpc) + w
altSpc=nil
v.x = xPos-0.5*w -- could test 'anchor' to position accordingly
v.y = yPos
elseif t=="nil" then
xPos = xPos+nilSpc
elseif t=="number" then
altSpc=v
end
end
box.T = box.T + maxH
end