cd /news/developer-tools/a-lightweight-rich-text-component-wi… · home topics developer-tools article
[ARTICLE · art-86312] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

A Lightweight Rich Text Component Without a Web View

Codename One's PR #5421 introduces RichTextComponent, a lightweight read-only component for formatted text that supports headings, inline styles, lists, links, and images without embedding a web view. The component measures wrapped runs to fit naturally in Codename One layouts, and RichTextArea now imports and exports HTML, Markdown, AsciiDoc, and RTF through direct model adapters.

read4 min views1 publishedAug 4, 2026

PR #5421 adds RichTextComponent

, a read-only component for formatted application text. It supports headings, inline styles, lists, links, and images without embedding a web view.

What is Codename One? Codename One is an open-source framework for building native iOS, Android, desktop, and web apps from a single Java or Kotlin codebase. Learn more at codenameone.com.

A SpanLabel

applies one style to wrapped text. A BrowserComponent

renders a complete web page. RichTextComponent

covers formatted document content between those two cases and participates in ordinary Codename One layout.

A common screen mixes formatted text with buttons, images, forms, and other Codename One components inside one scrollable container. A BrowserComponent

is a poor fit for that layout because it owns a rectangular native surface and its own page viewport. The browser's document height does not naturally become the height of a child inside the parent Codename One layout.

RichTextComponent

measures wrapped runs for the width it receives and reports the corresponding height. In the default SizeMode.SHRINK

, it behaves like a SpanLabel

: the parent container scrolls the rich text together with the surrounding components. SizeMode.SCROLL

is available when the rich text should keep an assigned height and scroll its own content.

The read-only view and editor agree on paragraph attributes, inline styles, links, image runs, and wrapping because they do not maintain competing renderers.

HTML is not the only input:

RichTextComponent view = new RichTextComponent();

view.setMarkdown("# Trip summary\n\n"
        + "Departs **09:40**, arrives *11:15*. "
        + "See the [itinerary](app://itinerary).\n\n"
        + "- Window seat\n"
        + "- Carry-on only");

form.add(view);

setContent(...)

accepts RichTextFormat.HTML

, MARKDOWN

, ASCIIDOC

, or RTF

. The model covers headings, emphasis, inline code, links, images, lists, quotes, literal blocks, paragraph alignment, indentation, foreground colors, and highlights.

You can also assemble content without markup:

RichTextComponent status = new RichTextComponent();
status.append("Status: ", TextStyle.DEFAULT)
      .append("confirmed",
              TextStyle.DEFAULT
                      .withBold(true)
                      .withForeColor(0x1a7f37));

This path is useful when the content already arrives as structured application data. It avoids generating markup only to parse it again.

A link target does not automatically leave the application:

view.addLinkListener(e ->
        Display.getInstance().execute((String) e.getSource()));

The event source is the target string. An https:

URL can open a browser. An app:

target can navigate to another form. The application owns the policy.

Images follow the same rule:

view.setImageResolver(src -> imageCache.get(src));

The component does not create a second network stack or choose a cache lifetime. The resolver returns the image for a source string, or null

for a placeholder. That keeps , authentication, and caching in application code.

RichTextArea

now imports and exports HTML, Markdown, AsciiDoc, and a practical RTF subset through direct model adapters. Markdown and AsciiDoc do not convert through HTML first.

RichTextArea editor = new RichTextArea();
editor.setContent(
        "# Release notes\n\nThis is **ready**.",
        RichTextFormat.MARKDOWN);
editor.insertContent(
        "{\\rtf1\\ansi {\\i pasted notes}}",
        RichTextFormat.RTF);
editor.insertContent(
        "== Details\n\n* Portable\n* Lightweight",
        RichTextFormat.ASCIIDOC);

Editing and reading the same format returns canonical output for that format. It preserves supported meaning, not the original whitespace, tag aliases, or attribute order.

Rich clipboard data uses the same negotiation. A copy can publish plain text, HTML, RTF, Markdown, and AsciiDoc together. The receiving component chooses the richest format it understands. Ports with only a plain-text system clipboard still keep the richer payload for transfers inside the application.

The HTML importer does not execute scripts. It supports the markup that maps to the lightweight document model. It does not implement a CSS cascade, arbitrary DOM layout, forms, video, or embedded JavaScript.

| Content and layout | Label / SpanLabel | RichTextComponent | BrowserComponent | |---|---|---|---| | Simple text | ✓ Best fit | Works, but unnecessary | Works, but adds a browser | | Mixed with other Codename One content | ✓ | ✓ | Separate browser surface | | Child of a scrollable Codename One container | ✓ Participates in parent layout | ✓ Measures its content and participates in parent layout | Owns a separate viewport and scrolling surface | | Simple HTML or formatted document content | Convert to plain or uniformly styled text | ✓ HTML, Markdown, AsciiDoc, and RTF | ✓ HTML | | Complex HTML, CSS, forms, video, or JavaScript | ✓ |

Use RichTextArea

instead when the formatted document must be editable.

Validate link targets and image sources as application data. A script-free importer prevents script execution; it does not make an untrusted URL safe to open.

The June editor implementation used a web view by default. The editor and a read-only Codename One rendering could therefore disagree on wrapping, font metrics, or supported markup.

The new path keeps editing and display on the same model and RichRunPainter

. A note can move from RichTextArea

to RichTextComponent

without crossing a browser serialization and rendering boundary.

Yesterday's post described the operating system sending text operations into a portable document. RichTextComponent

displays the same document model with the same painter and no editing session.

Try it where you currently use a BrowserComponent

only to show formatted application text. Keep the browser for pages that are actually web content.

The last post in this week's series covers compact strings in ParparVM. You can also start with free and local JavaScript builds, calendar synchronization, Bluetooth support, or pure Codename One text editing.

── more in #developer-tools 4 stories · sorted by recency
── more on @codename one 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/a-lightweight-rich-t…] indexed:0 read:4min 2026-08-04 ·