Inline Gradient Chips in HarmonyOS: CustomSpan, Text Wrapper, and ImageSpan Approaches
Requirement Description
Render inline text where a specific “span” segment has a gradient background. Direct linearGradient on Span doesn’t work, so we provide three working approaches.
Background Knowledge
-
Span: child ofText/ContainerSpan; does not support universal attributes, solinearGradientis ignored. UseTextfor universal styling or custom-draw withCustomSpan.
Docs: Span, Text, ContainerSpan
-
Universal gradient attribute:
linearGradientworks on components that support universal attributes (e.g.,Text).
Docs: linearGradient
- Styled strings & CustomSpan: draw your own background/text for inline segments.
Docs: CustomSpan (Styled String), Example – Span
- Graphics API for gradients: set a shader on the brush.
Docs (search please): Brush.setShaderEffect, ShaderEffect.createLinearGradient
Implementation Steps
1.Choose an approach
A) CustomSpan (recommended): Draw rounded-rect gradient + text via drawing APIs.
B) Text wrapper gradient: Wrap the small label as a separate Text (supports linearGradient), keep the rest as normal spans.
C) Image-based: Draw gradient + text to a PixelMap and embed inline via ImageSpan/ImageAttachment.
2.Mind inline layout: baseline alignment and width/height so the “chip” sits naturally within the line.
3.Wearable tips: maintain contrast; avoid tiny corners that clip on round screens; ≥ 44 vp if tappable.
Code Snippet / Configuration
A) CustomSpan — gradient background (recommended)
// In your CustomSpan onDraw(...)
onDraw(context: DrawContext, options: CustomSpanDrawInfo) {
const canvas = context.canvas;
// Gradient brush
const bg = new drawing.Brush();
const w = this.getUIContext().vp2px(this.width);
const h = this.getUIContext().vp2px(this.height);
const start: common2D.Point = { x: 0, y: 0 };
const end: common2D.Point = { x: w, y: h };
const shader = drawing.ShaderEffect.createLinearGradient(
start, end, [0xFFE574FF, 0xFFC906FF], drawing.TileMode.CLAMP
);
bg.setShaderEffect(shader);
// Rounded background behind the span segment
const rect: common2D.Rect = { left: options.x, top: options.lineTop, right: options.x + w, bottom: options.lineBottom };
const path = new drawing.Path();
path.addRoundRect(new drawing.RoundRect(rect, 4, 4), drawing.PathDirection.CLOCKWISE);
canvas.attachBrush(bg);
canvas.drawPath(path);
canvas.detachBrush();
// Foreground text
const fg = new drawing.Brush();
fg.setColor({ alpha: 255, red: 255, green: 255, blue: 255 });
const font = new drawing.Font();
font.setSize(25);
const blob = drawing.TextBlob.makeFromString(this.word, font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
canvas.attachBrush(fg);
canvas.drawTextBlob(blob, options.x + this.getUIContext().vp2px(8), options.lineBottom - this.getUIContext().vp2px(6));
canvas.detachBrush();
}
B) Text wrapper gradient — use Text for the chip
@Entry
@Component
export struct RichEditorStatus {
build() {
Row() {
Text() {
Span('Hello').fontSize(30)
}
.linearGradient({ direction: GradientDirection.Right, colors: [['#ff46f6f6', 0], ['#ff46a4f6', 1]] })
.padding({ left: 6, right: 6 })
.borderRadius(6)
Text() { Span(' World!').fontSize(30) }
}.height('100%')
}
}
C) Image-based — draw to PixelMap and embed inline
// After drawing gradient+text to PixelMap:
Text() {
ImageSpan(this.pixelMap).width(40).height(16)
Span(' World!').baselineOffset(new LengthMetrics(0)).fontSize(16)
}
Test Results
- CustomSpan correctly renders a gradient chip inline.
- Text wrapper approach works when the chip can be a separate node.
- Image-based matches complex visuals; cache the PixelMap for performance.
Limitations or Considerations
-
Spancan’t takelinearGradient; universal attributes are ignored. - Wrapping: long text may reveal seams with A/B/C approaches—plan layout accordingly.
- Performance: image rendering is heavier; cache and redraw only on change.
Related Documents or Links
- Span: https://developer.huawei.com/consumer/en/doc/harmonyos-references/ts-basic-components-span
- Text: https://developer.huawei.com/consumer/en/doc/harmonyos-references/ts-basic-components-text
- ContainerSpan: https://developer.huawei.com/consumer/en/doc/harmonyos-references/ts-basic-components-containerspan
- Styled String & CustomSpan: https://developer.huawei.com/consumer/en/doc/harmonyos-references/ts-universal-styled-string#customspan
- Example 6 (Span): https://developer.huawei.com/consumer/en/doc/harmonyos-references/ts-universal-styled-string#%E7%A4%BA%E4%BE%8B6%E8%AE%BE%E7%BD%AE%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%98%E5%88%B6span
-
linearGradientuniversal attribute: https://developer.huawei.com/consumer/en/doc/harmonyos-references/ts-universal-attributes-gradient-color#lineargradient - ImageSpan: https://developer.huawei.com/consumer/en/doc/harmonyos-references/ts-basic-components-imagespan
- ImageAttachment (Styled String): https://developer.huawei.com/consumer/en/doc/harmonyos-references/ts-universal-styled-string#imageattachment

Top comments (0)