Make a button¶
Buttons in Tick UI use an invisible-widget idiom. You draw the
visual, then call ui.Button("id") over the same rect. Button
claims hit-testing and returns whether the user clicked. This page
covers the pattern, including hover state and animation hooks.
To make a button¶
- Push a layout rect for the button.
Use
ui.Auto()to scope the rect: - Draw the visual first.
FillRounded,Text, and any decorations render in the rect: - Call
Buttonover the same rect.
Button is invisible. It does not draw anything; it only claims
hit-testing for the current rect and returns true on the frame
the user presses inside it.
Read hover state¶
ui.IsHovered() returns whether the current rect is the hovered
widget. Read it before drawing the visual to pick a colour or
scale.
IsHovered reads state computed in BeginFrame. The state is
constant for the duration of the frame, so calls before and after
Button return the same answer. For the model behind hover
resolution, refer to
Input and focus.
Buttons in a list¶
Repeated buttons need unique IDs. Wrap each iteration in PushID
so the inner Button("save") calls do not collide:
for (int i = 0; i < items.Count; i++)
{
ui.PushID(items[i].Id);
using (ui.Auto().PushRelativeRect(rowRect))
{
ui.FillRounded(ui.IsHovered() ? hoverColor : restColor, 5);
ui.Text(items[i].Name, "roboto_mono", 14, textColor, TextAlign.MiddleCenter);
if (ui.Button("row"))
Open(items[i]);
}
ui.PopID();
}
Without PushID, every row's Button("row") produces the same ID
hash and only one row responds. For the identity model, refer to
IDs.
Add an animation¶
Wrap the button in a PushAnimate scope to animate hover, press,
or appearance. Read animated values from the returned context and
pass them to the draw calls for colours and sizes.
var ctx = ui.PushAnimate("save_button")
.Init().Color().Set(restColor).Done()
.Enter().Color().Blend(restColor, hoverColor, 0.2f).Done()
.Leave().Color().Blend(hoverColor, restColor, 0.2f).Done()
.BoolWhileTrue("hover", ui.IsHovered())
.Apply();
ui.FillRounded(ctx.GetColor(), 5);
ui.Text("Save", "roboto_mono", 14, textColor, TextAlign.MiddleCenter);
if (ui.Button("save"))
SaveDocument();
ui.PopAnimate();
For the full animation API, refer to Add an animation. For the model behind animation contexts, refer to Animation.
Pitfalls¶
Calling Button before drawing the visual.
: IsHovered returns the previous frame's state when read before
Button claims the current rect. Draw first, then call
Button.
Forgetting PushID inside a loop.
: Every iteration produces the same ID. Only one row responds to
clicks. Pair PushID(item.Id) and PopID() around each
iteration.
Drawing outside the rect.
: Button hit-tests against the current rect, not against where
you drew the visual. If the visual extends past the rect (a
drop shadow, for example), the rect needs to grow or the
decoration needs to render outside the hit area.
The button never registers a click. : Another panel is hovered. Buttons inside non-hovered panels do not respond. Refer to Input and focus for the priority order.
Additional resources¶
- Make a textbox: the same invisible-widget idiom for text input.
- Add an animation: the full procedure for hover and press animations.
- State: why widget state is keyed by ID.
- IDs: the identity model used here.