UI Guidelines
4/21/26About 4 min
These guidelines standardize how to write UIs in Auto.js Pro v8 (Rhino UI module) to reduce layout chaos, inconsistent styling, thread misuse, and performance issues.
0. Prerequisites (must follow)
- UI scripts must start with
"ui";"ui";must be on the first line. No code is allowed before it.
- Layouts must be wrapped by
ui.layout(...) - All UI updates must run on the UI thread
- When a worker thread needs to update the UI, use
$ui.post(...)or$ui.run(...).
- When a worker thread needs to update the UI, use
- Use
#RRGGBBfor colors - Use
alphain the range 0~1: 0 fully transparent, 1 fully opaque<text id="title" text="Title" alpha="0.6"/>$ui.title.setAlpha(0.6)$ui.title.attr('alpha', '0.6')
1. File & structure conventions (recommended)
- Single-file script structure (fixed top-to-bottom order):
"ui";- Constants (colors, spacing, font sizes, strings)
- Layout via
ui.layout(<xml>...</xml>)(or$ui.layout(...)) const view = {...}view references (centralizedui.xxxaccess)- Event bindings (click/input/scroll, etc.)
- Business logic (network/IO/heavy compute on worker threads)
- Complex UIs: split into “components / sub-layouts” (see 3.6) rather than one huge XML.
2. Terminology & naming conventions
2.1 Widget id naming
- Meaningful: describe purpose, not appearance.
- Consistent style:
camelCaseis recommended. - Avoid conflicts: don’t use names that may clash with
uiproperties (e.g.layout,post,run). If it conflicts, use$ui.findView(id).
Examples:
- Good:
titleText,submitBtn,searchInput,list,emptyView - Avoid:
text1,button2,redBtn
2.2 Event handler naming
- Prefer
onXxx/handleXxx:onSubmitClick、handleSearchChange、onItemLongClick
3. XML layout guidelines
3.1 Basic rules
- Keep layout clear: prefer
vertical/horizontal/frame/scrollcombinations and avoid unnecessary nesting. - Be declarative: describe structure and static styles in XML. Only use dynamic
inflate/addViewwhen necessary. - Be explicit: don’t rely on defaults for key UX properties (
padding,margin,textSize,textColor,bg).
3.2 Spacing & sizes (dp/sp)
- Text size: use
sp(e.g.14sp,16sp,20sp). - Spacing/sizes: use
dp(e.g.8dp,12dp,48dp). - Touch targets: clickable widgets should be at least (48dp) in width/height.
3.3 Color & contrast
- Single source of truth: keep common colors in constants to avoid scattered magic values.
- Contrast first: ensure sufficient contrast between text and background (dark text on light backgrounds, light text on dark backgrounds).
- Consistent semantic colors: success/warning/error/disabled colors should keep stable meanings.
3.4 Typography & layout
- Body text:
14sp~16spby default. Keep line height comfortable (if controllable). - Titles:
18sp~22sp, optionally bold (if supported). - Alignment: keep alignment consistent within the same hierarchy; prefer left alignment.
3.5 Scrollable areas
- Only wrap what needs scrolling; avoid multiple nested scroll containers for the whole page.
- For list scenarios, prefer a
listcomponent (if available) instead of dynamically creating many Views to mimic a long list.
3.6 Componentization & reuse (recommended)
- Reusable blocks should be extracted as:
- Custom widget:
$ui.registerWidget(name, widget) - Sub-layout: inject into a container via
$ui.inflate(xml, parent, attachToParent)
- Custom widget:
- When reusing, ensure:
- clear input/output (props/callbacks)
- no hidden global dependencies (or make them explicit)
4. JavaScript & threading guidelines
4.1 UI thread principles
- Do not run the following on the UI thread:
- network requests
- file IO
- heavy loops / computation
- creating/updating many Views in bulk
- After work finishes on a worker thread, use
$ui.post(() => { ... })to update the UI on the UI thread.
4.2 Recommended ways to update UI
- Simple async update:
$ui.post(callback[, delay]) - Need a return value and you can block the current thread:
$ui.run(callback)
5. Interaction guidelines (must be consistent)
5.1 Tap & feedback
- Taps must have feedback (system pressed/ripple state, text change, loading indicator, etc.).
- Submit buttons should enter loading/disabled during requests to prevent duplicate submissions.
5.2 Input & validation
- Input fields should provide:
- clear hint text (placeholder/hint)
- necessary format restrictions and live validation (e.g. phone number, OTP length)
- error messages near the field with actionable wording
5.3 Empty / error / loading states (required)
For every “list/content area”, consider at least:
- Loading: initial loading
- Empty: no data / no permission / filters yield no results
- Error: network failure / API error / parse error (provide a retry entry point)
6. Accessibility (A11y) & usability
- Readable text: avoid low contrast and too-small font sizes.
- Large enough tap areas: small icons should add padding to expand the touch target.
- Don’t rely on color alone: error states should include text/icons, not just red.
7. Performance & stability red lines
- Do not build lists by inflating hundreds of Views in a
forloop. Use a list component or paginate rendering. - Avoid full refreshes: update only what changed (e.g. change only
textorvisibility). - Images:
- for remote images, consider caching and failure placeholders (if applicable)
- if needed, use
$ui.imageCache.clearMemory()/$ui.imageCache.clearDiskCache()(mind their threading behavior)
8. Using variables in XML (important)
In the XML passed to ui.layout(<xml>...</xml>), you can embed JavaScript expressions to reuse constants or do conditional rendering (depending on what the runtime supports). Recommended rules:
- Variables come from “constants”: e.g.
COLORS,SIZES, avoid declaring ad-hoc everywhere. - Keep expressions simple: don’t put complex logic in XML; do complex logic after layout and update attributes with JS.
Example (illustrative only):
"ui";
const COLORS = {
bg: "#FFFFFF",
primary: "#009688",
text: "#222222",
};
$ui.layout(
<vertical bg="{{COLORS.bg}}" padding="16dp">
<text
id="titleText"
text="Example title"
textColor="{{COLORS.text}}"
textSize="20sp"
/>
<button
id="submitBtn"
text="Submit"
style="Widget.AppCompat.Button.Colored"
/>
</vertical>,
);9. Recommended template (copy/paste)
"ui";
const COLORS = {
bg: "#FFFFFF",
text: "#222222",
subText: "#666666",
primary: "#009688",
danger: "#E53935",
};
$ui.layout(
<vertical bg="{{COLORS.bg}}" padding="16dp">
<text
id="titleText"
text="Page title"
textSize="20sp"
textColor="{{COLORS.text}}"
/>
<input id="searchInput" hint="Enter keywords" marginTop="12dp" />
<button id="submitBtn" text="Search" marginTop="12dp" />
<text
id="statusText"
text="Ready"
marginTop="12dp"
textSize="14sp"
textColor="{{COLORS.subText}}"
/>
</vertical>,
);
ui.submitBtn.on("click", () => {
ui.statusText.attr("text", "Loading…");
ui.submitBtn.attr("enabled", false);
// Simulate a long-running task: in real projects, do network/IO/compute on a worker thread
// Start worker thread
threads.start(() => {
// Simulate long-running work
java.lang.Thread.sleep(2500);
// UI updates must use ui.post
ui.post(() => {
ui.statusText.setText("Task completed ✅");
ui.submitBtn.attr("enabled", true);
});
});
});10. Pre-release checklist (recommended)
- Mode: the first line is
"ui";and there is no code before it - Threading: all UI updates run on the UI thread (worker threads come back via
$ui.post/$ui.run) - Three states: main content area has loading/empty/error states
- Responsiveness: on different screen sizes, nothing overlaps/overflows and scroll areas behave correctly
- Usability: primary buttons have touch target (\ge 48dp), and no duplicate submissions
- Consistency: colors/font sizes/spacing are consistent; naming is clear with no conflicts
