Skip to content

Mobile control API

nexus.ui is a Lua library built into the Nexus mobile engine. The Windows, Linux, Android and Apple engine build descriptions include its modules. The supplied artwork is packaged with the engine's system resources. Applications use the same import in the simulator and on the device:

local ui = require("nexus.ui")

local panel = ui.newPanel {parent = scene.view, width = 320, height = 480}
local name = ui.newEdit {parent = panel, y = -40, placeholder = "Your name"}
local save = ui.newButton {
    parent = panel, y = 40, text = "Save",
    onClick = function() saveCustomer(name.text) end
}
save.text = "Save changes"
save.enabled = false

Controls are engine display groups. parent, x and y place them in an existing scene; coordinates are relative to the parent. Control rectangles are centered on their local origin. Use the engine's normal transforms, visibility, ordering and removal operations. width and height change the control's arrangement and artwork without scaling its text. xScale and yScale retain their normal engine meaning.

parent = anotherControl inserts into that control's public content group. Use control.content:insert(object) for ordinary display objects. Removing a scene or containing group disposes the controls through engine finalization; applications do not maintain a second ownership tree. Disable a containing control to prevent interaction with its descendants.

Controls

All constructors accept parent, x, y, width, height, id, enabled and an optional control-specific skin table. Text uses Lua UTF-8 strings.

Constructor Additional options/properties Events/methods
newPanel — content for children
newLabel text, align —
newButton text onClick
newCheckbox text, checked onChange, event.checked
newToggle text, checked onChange, event.checked
newRadioGroup items, selectedIndex, constructor rowHeight onChange, getItem()
newEdit text, placeholder, readOnly, secure; constructor multiline, inputType, returnKey focus(), blur(), onFocus, onBlur, onChange, onSubmit
newScrollView contentHeight, scrollY scrollTo(y), reveal(child, margin), onScroll
newList items, selectedIndex, constructor rowHeight getItem(), refresh(), onChange, onClick; scroll methods
newSlider value; constructor minimum, maximum, step onChange, event.value
newProgress value; constructor minimum, maximum —

Items are strings or application tables containing text. Selection events provide selectedIndex and the original item; zero means no selection. Replace a list's items property to rebuild its rows, or call refresh() after modifying its existing item tables. Radio items are specified at construction. Lists are ordinary scrollable rows, intended for mobile-sized collections; this implementation does not virtualize very large datasets.

Callbacks receive event.target, the control itself. The same events are available through the engine's control:addEventListener("change", listener) mechanism. Use either form, or intentionally register both. Programmatic property assignments update the display without reporting a user change.

Buttons activate on release inside their bounds. Cancelled or outside releases do not activate them. A vertical drag on a control inside a scroll view transfers the gesture to that viewport. Sliders retain horizontal drags. Scrolling uses the engine's container clipping, touch focus and transitions for deceleration. onScroll reports touch-drag movement; programmatic positioning and subsequent deceleration do not generate additional callbacks.

Scroll content has its origin at the viewport's upper-left corner. Specify its contentHeight after placing children. Panels retain ordinary centered local coordinates and do not clip children automatically.

Text editing

An unfocused edit is drawn by the engine, including its frame and text. While focused it uses a borderless native text field or multiline text box inside the skinned frame. This preserves the phone's keyboard, text composition, selection and clipboard behavior. No additional native input bridge is used.

onChange supplies text and oldText; onSubmit reports a submitted single-line edit. Multiline return inserts a newline. Use a Done/Save button or ui.blur() to finish multiline editing. Text values are kept in Lua and updated from the native input events, avoiding immediate Android readback after asynchronous native writes.

Native editors render above the canvas. Scrolling their container ends editing; another control's interaction also ends it. Call ui.blur() before presenting custom overlays that cover an active edit. The enclosing scroll view reveals an edit before focusing it. Native engine keyboard accommodation remains in effect. The examples enable CoronaWindowMovesWhenKeyboardAppears in their Android settings and iPhone plist, so the engine can move the window to keep the focused editor above the keyboard. Mobile appearance and keyboard behavior must be checked on a device; desktop execution is not evidence of mobile validation.

Desktop native editing follows the engine's platform implementation. Windows does not support hasBackground, so an active editor retains its native background. The Linux native text implementation has incomplete text-property, styling and edit-notification support; its active editor is not yet equivalent to the phone implementations.

Skins

Choose the default neutral appearance or the supplied nine-slice artwork:

ui.setSkin({})
ui.setSkin(require("nexus.ui.skins.artwork"))

setSkin affects subsequently constructed controls. Each control captures its resolved skin. Assign control.skin = {...} to restyle an existing control. Skin tables contain common settings and entries named panel, label, button, checkbox, radio, toggle, edit, scroll, list, slider and progress. Per-control overrides use just that control's style table.

Settings include font, fontSize, textColor, mutedColor, accentColor, padding, gap, opacity and background. State tables selected, focused, pressed and disabled override the base appearance in that order. Nested fields merge; background = false removes a background.

Shape backgrounds accept color, radius, borderColor and borderWidth. Nine-slice backgrounds accept an image and source-pixel borders:

local buttonSkin = {
    textColor = {1, 1, 1},
    background = {
        type = "nineSlice", image = "art/button.png",
        borders = {left = 12, top = 12, right = 12, bottom = 12}
    },
    pressed = {background = {image = "art/button-down.png"}},
    disabled = {opacity = .45}
}

Alternatively provide sheet and nine frames indexes ordered left-to-right, top-to-bottom. baseDir defaults to system.ResourceDirectory; tint colors the slices. Borders remain fixed while the center and edges stretch. Controls smaller than their border pairs shrink the borders together. A skin describes appearance; input and state transitions remain in the control.

The supplied nexus_ui_frame.svg is the editable source of the original nexus_ui_frame.png artwork. Custom image assets travel with the application's normal resource files. Nine-slice drawing does not impose a mask on children.

Initial arrangement

ui.split(rect, ratio, gap, vertical) returns two center-based rectangles. The ratio divides the usable extent after subtracting the gap. It performs one calculation; call it again when the application wants another arrangement.

local left, right = ui.split({parent = scene.view, x = 200, y = 400,
    width = 368, height = 600}, .35, 8)
local navigation = ui.newPanel(left)
local details = ui.newPanel(right)

Working examples are in nexus-lab/examples/mobile/controls: a control gallery with both skins and a customer form with local persistence.