• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Styled String (StyledString/MutableStyledString)
2
3Styled strings, implemented by **StyledString** or **MutableStyledString** (collectively referred to as **StyledString**, with **MutableStyledString** inheriting from **StyledString**), are powerful markup objects designed to set text styles at the character or paragraph level. By binding a **StyledString** object to a text component, you can modify the text in various ways, including changing the font size, adding font colors, making the text clickable, and customizing the drawing of text, among others. For details, see [Styled String](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md).
4
5Styled strings provide a variety of style objects that cover various common text formatting styles, such as text decorative lines, line height, and text shadows. You can also create **CustomSpan** objects to apply custom styles.
6
7## Creating and Applying a StyledString Object
8
9  You can bind a **StyledString** object to a text component using the [setStyledString](../reference/apis-arkui/arkui-ts/ts-basic-components-text.md#setstyledstring12) API provided by **TextController**. You are advised to call the API in the [onPageShow](../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#onpageshow) callback for immediate display of the styled string text content.
10  > **NOTE**
11  >
12  > Avoid calling the **setStyledString** API in **aboutToAppear**, as the component may have not yet been mounted to the node tree at the time **aboutToAppear** is executed, preventing the styled string text content from appearing upon page load.
13
14  ```ts
15  @Entry
16  @Component
17  struct styled_string_demo1 {
18    styledString1: StyledString = new StyledString("45-minute workout");
19    mutableStyledString1: MutableStyledString = new MutableStyledString("35-minute workout");
20    controller1: TextController = new TextController();
21    controller2: TextController = new TextController();
22
23    async onPageShow() {
24      this.controller1.setStyledString(this.styledString1);
25      this.controller2.setStyledString(this.mutableStyledString1);
26    }
27
28    build() {
29      Column() {
30        // Display the styled string.
31        Text(undefined, { controller: this.controller1 })
32        Text(undefined, { controller: this.controller2 })
33      }
34      .width('100%')
35    }
36  }
37  ```
38  ![StyledString_Init](figures/span_string_init.png)
39
40## Setting the Text Style
41
42Styled strings offer multiple style objects, such as [TextStyle](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md#textstyle), [TextShadowStyle](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md#textshadowstyle), [DecorationStyle](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md#decorationstyle), [BaselineOffsetStyle](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md#baselineoffsetstyle), [LineHeightStyle](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md#lineheightstyle), and [LetterSpacingStyle](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md#letterspacingstyle), for setting text styles.
43
44- Creating and applying a **TextStyle** object
45
46  ```ts
47  import { LengthMetrics } from '@kit.ArkUI';
48
49  @Entry
50  @Component
51  struct styled_string_demo2 {
52    textStyleAttrs: TextStyle =
53      new TextStyle({ fontWeight: FontWeight.Bolder, fontSize: LengthMetrics.vp(24), fontStyle: FontStyle.Italic });
54    mutableStyledString: MutableStyledString = new MutableStyledString("35-minute workout goal achieved", [
55      {
56        start: 2,
57        length: 2,
58        styledKey: StyledStringKey.FONT,
59        styledValue: this.textStyleAttrs
60      },
61      {
62        start: 7,
63        length: 4,
64        styledKey: StyledStringKey.FONT,
65        styledValue: new TextStyle({ fontColor: Color.Orange, fontSize: LengthMetrics.vp(12) })
66      }
67    ]);
68    controller: TextController = new TextController();
69
70    async onPageShow() {
71      this.controller.setStyledString(this.mutableStyledString);
72    }
73
74    build() {
75      Column() {
76        // Display the styled string.
77        Text(undefined, { controller: this.controller })
78          .margin({ top: 10 })
79      }
80      .width('100%')
81    }
82  }
83  ```
84  ![StyledString_TextStyle](figures/StyledString_TextStyle.png)
85
86- Creating and applying a **TextShadowStyle** object
87
88  ```ts
89  // xxx.ets
90  @Entry
91  @Component
92  struct styled_string_demo3 {
93    mutableStyledString: MutableStyledString = new MutableStyledString("35-minute workout", [
94      {
95        start: 0,
96        length: 3,
97        styledKey: StyledStringKey.TEXT_SHADOW,
98        styledValue: new TextShadowStyle({
99          radius: 5,
100          type: ShadowType.COLOR,
101          color: Color.Red,
102          offsetX: 10,
103          offsetY: 10
104        })
105      }
106    ]);
107    controller: TextController = new TextController();
108
109    async onPageShow() {
110      this.controller.setStyledString(this.mutableStyledString);
111    }
112
113    build() {
114      Column() {
115        // Display the styled string.
116        Text(undefined, { controller: this.controller })
117      }
118      .width('100%')
119    }
120  }
121  ```
122  ![StyledString_TextShadow](figures/styled_string_text_shadow.png)
123
124- Creating and applying a **Text DecorationStyle** object
125
126  ```ts
127  // xxx.ets
128  @Entry
129  @Component
130  struct styled_string_demo4 {
131    mutableStyledString: MutableStyledString = new MutableStyledString("35-minute workout", [
132      {
133        start: 0,
134        length: 3,
135        styledKey: StyledStringKey.DECORATION,
136        styledValue: new DecorationStyle({ type: TextDecorationType.LineThrough, color: Color.Red })
137      }
138    ]);
139    controller: TextController = new TextController();
140
141    async onPageShow() {
142      this.controller.setStyledString(this.mutableStyledString);
143    }
144
145    build() {
146      Column() {
147        // Display the styled string.
148        Text(undefined, { controller: this.controller })
149      }
150      .width('100%')
151    }
152  }
153  ```
154  ![StyledString_Decoration](figures/styled_string_decoration.png)
155
156- Creating and applying a **Text BaselineOffsetStyle** object
157
158  ```ts
159  import { LengthMetrics } from '@kit.ArkUI';
160
161  // xxx.ets
162  @Entry
163  @Component
164  struct styled_string_demo5 {
165    mutableStyledString: MutableStyledString = new MutableStyledString("35-minute workout", [
166      {
167        start: 0,
168        length: 3,
169        styledKey: StyledStringKey.BASELINE_OFFSET,
170        styledValue: new BaselineOffsetStyle(LengthMetrics.px(20))
171      }
172    ]);
173    controller: TextController = new TextController();
174
175    async onPageShow() {
176      this.controller.setStyledString(this.mutableStyledString);
177    }
178
179    build() {
180      Column() {
181        // Display the styled string.
182        Text(undefined, { controller: this.controller })
183      }
184      .width('100%')
185    }
186  }
187  ```
188  ![StyledString_Baseline](figures/styled_string_baselineoffset.png)
189
190- Creating and applying a **LineHeightStyle** object
191
192  ```ts
193  import { LengthMetrics } from '@kit.ArkUI';
194
195  // xxx.ets
196  @Entry
197  @Component
198  struct styled_string_demo6 {
199    mutableStyledString: MutableStyledString = new MutableStyledString("35-minute workout\nFighting\nAchieved", [
200      {
201        start: 8,
202        length: 3,
203        styledKey: StyledStringKey.LINE_HEIGHT,
204        styledValue: new LineHeightStyle(LengthMetrics.vp(50))
205      }
206    ]);
207    controller: TextController = new TextController();
208
209    async onPageShow() {
210      this.controller.setStyledString(this.mutableStyledString);
211    }
212
213    build() {
214      Column() {
215        // Display the styled string.
216        Text(undefined, { controller: this.controller })
217      }
218      .width('100%')
219      .margin({ top: 10 })
220    }
221  }
222  ```
223  ![StyledString_lineHeight](figures/styled_string_lineHeight.png)
224
225- Creating and applying a **LetterSpacingStyle** object
226
227  ```ts
228  import { LengthMetrics, LengthUnit } from '@kit.ArkUI';
229
230  // xxx.ets
231  @Entry
232  @Component
233  struct styled_string_demo7 {
234    mutableStyledString: MutableStyledString = new MutableStyledString("35-minute workout", [
235      {
236        start: 0,
237        length: 2,
238        styledKey: StyledStringKey.LETTER_SPACING,
239        styledValue: new LetterSpacingStyle(new LengthMetrics(20, LengthUnit.VP))
240      }
241    ]);
242    controller: TextController = new TextController();
243
244    async onPageShow() {
245      this.controller.setStyledString(this.mutableStyledString);
246    }
247
248    build() {
249      Column() {
250        // Display the styled string.
251        Text(undefined, { controller: this.controller })
252      }
253      .width('100%')
254    }
255  }
256  ```
257  ![StyledString_letterSpacing](figures/styled_string_letterspacing.png)
258
259## Setting the Paragraph Style
260
261You can set the paragraph style using [ParagraphStyle](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md#paragraphstyle). The figure below shows how to divide paragraphs in the text, with each paragraph ending with a newline character \n.
262
263![paragraphs](figures/styledstringParagraphs.png)
264
265The following example shows how to create and apply a paragraph style. The style is applied to the start, end or any position within a paragraph; it does not apply to non-paragraph areas.
266
267  ```ts
268  import { LengthMetrics } from '@kit.ArkUI';
269  titleParagraphStyleAttr: ParagraphStyle = new ParagraphStyle({ textAlign: TextAlign.Center });
270  // Create a paragraph style for a 15 vp first-line text indent.
271  paragraphStyleAttr1: ParagraphStyle = new ParagraphStyle({ textIndent: LengthMetrics.vp(15) });
272  // Line height style object
273  lineHeightStyle1: LineHeightStyle= new LineHeightStyle(new LengthMetrics(24));
274  // Create a paragraph style object paragraphStyledString1.
275  paragraphStyledString1: MutableStyledString = new MutableStyledString("Paragraph Title\nFirst paragraph starts 0123456789 First paragraph ends.", [
276    {
277      start: 0,
278      length: 4,
279      styledKey: StyledStringKey.PARAGRAPH_STYLE,
280      styledValue: this.titleParagraphStyleAttr
281    },
282    {
283      start: 0,
284      length: 4,
285      styledKey: StyledStringKey.LINE_HEIGHT,
286      styledValue: new LineHeightStyle(new LengthMetrics(50))
287    },{
288    start: 0,
289    length: 4,
290    styledKey: StyledStringKey.FONT,
291    styledValue: new TextStyle({ fontSize: LengthMetrics.vp(24), fontWeight: FontWeight.Bolder })
292  },
293    {
294      start: 5,
295      length: 3,
296      styledKey: StyledStringKey.PARAGRAPH_STYLE,
297      styledValue: this.paragraphStyleAttr1
298    },
299    {
300      start: 5,
301      length: 20,
302      styledKey: StyledStringKey.LINE_HEIGHT,
303      styledValue: this.lineHeightStyle1
304    }
305  ]);
306  ```
307
308  In addition to presetting styles when creating a styled string, you can also clear the original styles and replace them with new ones later using the [replaceStyle](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md#replacestyle) API. After the replacement, you need to proactively trigger an update to the bound styled string on the attached text component's controller.
309
310  ```ts
311  import { LengthMetrics } from '@kit.ArkUI';
312  // Set the maximum number of lines and text overflow mode for the paragraph, without setting the indent.
313  paragraphStyleAttr3: ParagraphStyle = new ParagraphStyle({ textAlign: TextAlign.End, maxLines: 1, wordBreak: WordBreak.BREAK_ALL, overflow: TextOverflow.Ellipsis});
314  // Later in the code, trigger an update to the paragraph style.
315  controller: TextController = new TextController();
316  this.paragraphStyledString1.replaceStyle({
317    start: 5,
318    length: 3,
319    styledKey: StyledStringKey.PARAGRAPH_STYLE,
320    styledValue: this.paragraphStyleAttr3
321  });
322  this.controller.setStyledString(this.paragraphStyledString1);
323  ```
324
325## Using Images
326
327You can add images using [ImageAttachment](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md#imageattachment).
328
329The following example shows how to attach images and text to the same **MutableStyledString** object for mixed display of text and images.
330
331  ```ts
332  // xxx.ets
333  import { image } from '@kit.ImageKit';
334  import { LengthMetrics } from '@kit.ArkUI';
335
336  @Entry
337  @Component
338  struct styled_string_demo4 {
339    @State message: string = 'Hello World';
340    imagePixelMap: image.PixelMap | undefined = undefined;
341    @State imagePixelMap3: image.PixelMap | undefined = undefined;
342    mutableStr: MutableStyledString = new MutableStyledString('123');
343    controller: TextController = new TextController();
344    mutableStr2: MutableStyledString = new MutableStyledString('This is set decoration line style to the mutableStr2', [{
345      start: 0,
346      length: 15,
347      styledKey: StyledStringKey.DECORATION,
348      styledValue: new DecorationStyle({
349        type: TextDecorationType.Overline,
350        color: Color.Orange,
351        style: TextDecorationStyle.DOUBLE
352      })
353    }]);
354
355    async aboutToAppear() {
356      console.info("aboutToAppear initial imagePixelMap");
357      this.imagePixelMap = await this.getPixmapFromMedia($r('app.media.sea'));
358    }
359
360    private async getPixmapFromMedia(resource: Resource) {
361      let unit8Array = await this.getUIContext().getHostContext()?.resourceManager?.getMediaContent({
362        bundleName: resource.bundleName,
363        moduleName: resource.moduleName,
364        id: resource.id
365      });
366      let imageSource = image.createImageSource(unit8Array?.buffer?.slice(0, unit8Array?.buffer?.byteLength));
367      let createPixelMap: image.PixelMap = await imageSource.createPixelMap({
368        desiredPixelFormat: image.PixelMapFormat.RGBA_8888
369      });
370      await imageSource.release();
371      return createPixelMap;
372    }
373
374    leadingMarginValue: ParagraphStyle = new ParagraphStyle({ leadingMargin: LengthMetrics.vp(5)});
375    // Line height style object
376    lineHeightStyle1: LineHeightStyle= new LineHeightStyle(new LengthMetrics(24));
377    //Bold style
378    boldTextStyle: TextStyle = new TextStyle({ fontWeight: FontWeight.Bold });
379    // Create a paragraph style object paragraphStyledString1.
380    paragraphStyledString1: MutableStyledString = new MutableStyledString("\n30 HD prints\nCYN5.15 off Limited offer", [
381      {
382        start: 0,
383        length: 28,
384        styledKey: StyledStringKey.PARAGRAPH_STYLE,
385        styledValue: this.leadingMarginValue
386      },
387      {
388        start: 14,
389        length: 9,
390        styledKey: StyledStringKey.FONT,
391        styledValue: new TextStyle({ fontSize: LengthMetrics.vp(14), fontColor: '#B22222' })
392      },
393      {
394        start: 24,
395        length: 4,
396        styledKey: StyledStringKey.FONT,
397        styledValue: new TextStyle({ fontSize: LengthMetrics.vp(14), fontWeight: FontWeight.Lighter })
398      },
399      {
400        start: 11,
401        length: 4,
402        styledKey: StyledStringKey.LINE_HEIGHT,
403        styledValue: this.lineHeightStyle1
404      }
405    ]);
406    paragraphStyledString2: MutableStyledString = new MutableStyledString("\n¥16.21 3000+ reviews", [
407      {
408        start: 0,
409        length: 5,
410        styledKey: StyledStringKey.PARAGRAPH_STYLE,
411        styledValue: this.leadingMarginValue
412      },
413      {
414        start: 0,
415        length: 4,
416        styledKey: StyledStringKey.LINE_HEIGHT,
417        styledValue: new LineHeightStyle(new LengthMetrics(60))
418      },
419      {
420        start: 0,
421        length: 7,
422        styledKey: StyledStringKey.FONT,
423        styledValue: this.boldTextStyle
424      },
425      {
426        start: 1,
427        length: 1,
428        styledKey: StyledStringKey.FONT,
429        styledValue: new TextStyle({ fontSize: LengthMetrics.vp(18) })
430      },
431      {
432        start: 2,
433        length: 2,
434        styledKey: StyledStringKey.FONT,
435        styledValue: new TextStyle({ fontSize: LengthMetrics.vp(36) })
436      },
437      {
438        start: 4,
439        length: 3,
440        styledKey: StyledStringKey.FONT,
441        styledValue: new TextStyle({ fontSize: LengthMetrics.vp(20) })
442      },
443      {
444        start: 7,
445        length: 9,
446        styledKey: StyledStringKey.FONT,
447        styledValue: new TextStyle({ fontColor: Color.Grey, fontSize: LengthMetrics.vp(14)})
448      }
449    ]);
450
451    build() {
452      Row() {
453        Column({ space: 10 }) {
454          Text(undefined, { controller: this.controller })
455            .copyOption(CopyOptions.InApp)
456            .draggable(true)
457            .backgroundColor('#FFFFFF')
458            .borderRadius(5)
459
460          Button('View Product Details')
461            .onClick(() => {
462              if (this.imagePixelMap !== undefined) {
463                this.mutableStr = new MutableStyledString(new ImageAttachment({
464                  value: this.imagePixelMap,
465                  size: { width: 180, height: 160 },
466                  verticalAlign: ImageSpanAlignment.BASELINE,
467                  objectFit: ImageFit.Fill
468                }));
469                this.paragraphStyledString1.appendStyledString(this.paragraphStyledString2);
470                this.mutableStr.appendStyledString(this.paragraphStyledString1);
471                this.controller.setStyledString(this.mutableStr);
472              }
473            })
474        }
475        .width('100%')
476      }
477      .height('100%')
478      .backgroundColor('#F8F8FF')
479    }
480  }
481  ```
482  ![StyledString_ImageAttachment](figures/StyledStringImageAttachment.png)
483
484## Setting Events
485
486You can use [GestureStyle](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md#gesturestyle) to set up **onClick** and **onLongPress** events to enable text to respond to click and long-press actions.
487
488In addition to initializing styled strings with initial style objects, you can also use the [setStyle](../reference/apis-arkui/arkui-ts/ts-universal-styled-string.md#setstyle) API to overlay new styles or update existing ones. After making changes, you need to manually trigger an update of the bound styled string on the attached text component's controller.
489
490  ```ts
491  import { drawing } from '@kit.ArkGraphics2D';
492
493  class MyCustomSpan extends CustomSpan {
494    constructor(word: string, width: number, height: number, fontSize: number) {
495      super();
496      this.word = word;
497      this.width = width;
498      this.height = height;
499      this.fontSize = fontSize;
500    }
501
502    onMeasure(measureInfo: CustomSpanMeasureInfo): CustomSpanMetrics {
503      return { width: this.width, height: this.height };
504    }
505
506    onDraw(context: DrawContext, options: CustomSpanDrawInfo) {
507      let canvas = context.canvas;
508
509      const brush = new drawing.Brush();
510      brush.setColor({
511        alpha: 255,
512        red: 0,
513        green: 0,
514        blue: 0
515      });
516      const font = new drawing.Font();
517      font.setSize(vp2px(this.fontSize));
518      const textBlob =
519        drawing.TextBlob.makeFromString(this.word.substring(0, 5), font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
520      canvas.attachBrush(brush);
521
522      this.onDrawRectByRadius(context, options.x, options.x + vp2px(this.width), options.lineTop, options.lineBottom, 20);
523      brush.setColor({
524        alpha: 255,
525        red: 255,
526        green: 255,
527        blue: 255
528      });
529      canvas.attachBrush(brush);
530      canvas.drawTextBlob(textBlob, options.x, options.lineBottom - 30);
531      brush.setColor({
532        alpha: 255,
533        red: 255,
534        green: 228,
535        blue: 196
536      });
537      canvas.attachBrush(brush);
538      const textBlob1 =
539        drawing.TextBlob.makeFromString(this.word.substring(5), font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
540      canvas.drawTextBlob(textBlob1, options.x + vp2px(100), options.lineBottom - 30);
541
542      canvas.detachBrush();
543    }
544
545    onDrawRectByRadius(context: DrawContext, left: number, right: number, top: number, bottom: number, radius: number) {
546      let canvas = context.canvas;
547      let path = new drawing.Path();
548
549      // Draw a rectangle with rounded corners.
550      path.moveTo(left + radius, top);
551      path.lineTo(right - radius, top);
552      path.arcTo(right - 2 * radius, top, right, top + 2 * radius, 270, 90);
553      path.lineTo(right, bottom - radius);
554      path.arcTo(right - 2 * radius, bottom - 2 * radius, right, bottom, 0, 90);
555
556      path.lineTo(left + 2 * radius, bottom);
557      path.arcTo(left, bottom - 2 * radius, left + 2 * radius, bottom, 90, 90);
558      path.lineTo(left, top + 2 * radius);
559      path.arcTo(left, top, left + 2 * radius, top + 2 * radius, 180, 90);
560
561      canvas.drawPath(path);
562    }
563
564    setWord(word: string) {
565      this.word = word;
566    }
567
568    width: number = 160;
569    word: string = "drawing";
570    height: number = 10;
571    fontSize: number = 16;
572  }
573
574  @Entry
575  @Component
576  struct styled_string_demo6 {
577    customSpan3: MyCustomSpan = new MyCustomSpan("99VIP88%off", 200, 40, 30);
578    textStyle: MutableStyledString = new MutableStyledString("123");
579    textController: TextController = new TextController();
580    isPageShow: boolean = true;
581
582    async onPageShow() {
583      if (!this.isPageShow) {
584        return;
585      }
586      this.isPageShow = false;
587      this.textController.setStyledString(new StyledString(this.customSpan3));
588    }
589
590    build() {
591      Row() {
592        Column() {
593          Text(undefined, { controller: this.textController })
594            .copyOption(CopyOptions.InApp)
595            .fontSize(30)
596        }
597        .width('100%')
598      }
599      .height('100%')
600    }
601  }
602  ```
603![CustomSpanDemo](figures/StyledString_CustomSpan_Scene.PNG)
604
605## Example
606
607This example shows how to implement an expired membership notification using **ParagraphStyle**, **LineHeightStyle**, and **TextStyle** objects.
608
609```ts
610import { LengthMetrics } from '@kit.ArkUI';
611
612@Entry
613@Component
614struct Index {
615  alignCenterParagraphStyleAttr: ParagraphStyle = new ParagraphStyle({ textAlign: TextAlign.Center });
616  // Line height style object
617  lineHeightStyle1: LineHeightStyle = new LineHeightStyle(LengthMetrics.vp(24));
618  //Bold style
619  boldTextStyle: TextStyle = new TextStyle({ fontWeight: FontWeight.Bold });
620  // Create a paragraph style object paragraphStyledString1.
621  paragraphStyledString1: MutableStyledString =
622    new MutableStyledString("Diamond Membership expired\nRenew to keep your perks", [
623      {
624        start: 0,
625        length: 4,
626        styledKey: StyledStringKey.PARAGRAPH_STYLE,
627        styledValue: this.alignCenterParagraphStyleAttr
628      },
629      {
630        start: 0,
631        length: 4,
632        styledKey: StyledStringKey.LINE_HEIGHT,
633        styledValue: new LineHeightStyle(LengthMetrics.vp(40))
634      },
635      {
636        start: 11,
637        length: 14,
638        styledKey: StyledStringKey.FONT,
639        styledValue: new TextStyle({ fontSize: LengthMetrics.vp(14), fontColor: Color.Grey })
640      },
641      {
642        start: 11,
643        length: 4,
644        styledKey: StyledStringKey.PARAGRAPH_STYLE,
645        styledValue: this.alignCenterParagraphStyleAttr
646      },
647      {
648        start: 11,
649        length: 4,
650        styledKey: StyledStringKey.LINE_HEIGHT,
651        styledValue: this.lineHeightStyle1
652      }
653    ]);
654  paragraphStyledString2: MutableStyledString = new MutableStyledString("\n¥4.88¥15", [
655    {
656      start: 0,
657      length: 4,
658      styledKey: StyledStringKey.PARAGRAPH_STYLE,
659      styledValue: this.alignCenterParagraphStyleAttr
660    },
661    {
662      start: 0,
663      length: 4,
664      styledKey: StyledStringKey.LINE_HEIGHT,
665      styledValue: new LineHeightStyle(LengthMetrics.vp(60))
666    },
667    {
668      start: 0,
669      length: 6,
670      styledKey: StyledStringKey.FONT,
671      styledValue: this.boldTextStyle
672    },
673    {
674      start: 1,
675      length: 1,
676      styledKey: StyledStringKey.FONT,
677      styledValue: new TextStyle({ fontSize: LengthMetrics.vp(18) })
678    },
679    {
680      start: 2,
681      length: 4,
682      styledKey: StyledStringKey.FONT,
683      styledValue: new TextStyle({ fontSize: LengthMetrics.vp(40) })
684    },
685    {
686      start: 6,
687      length: 3,
688      styledKey: StyledStringKey.FONT,
689      styledValue: new TextStyle({ fontColor: Color.Grey, fontSize: LengthMetrics.vp(14) })
690    },
691    {
692      start: 6,
693      length: 3,
694      styledKey: StyledStringKey.DECORATION,
695      styledValue: new DecorationStyle({ type: TextDecorationType.LineThrough, color: Color.Grey })
696    }
697  ]);
698  paragraphStyledString3: MutableStyledString = new MutableStyledString("\nOffer ends in 02:06", [
699    {
700      start: 0,
701      length: 4,
702      styledKey: StyledStringKey.PARAGRAPH_STYLE,
703      styledValue: this.alignCenterParagraphStyleAttr
704    },
705    {
706      start: 0,
707      length: 4,
708      styledKey: StyledStringKey.LINE_HEIGHT,
709      styledValue: new LineHeightStyle(LengthMetrics.vp(30))
710    },
711    {
712      start: 1,
713      length: 2,
714      styledKey: StyledStringKey.FONT,
715      styledValue: new TextStyle({ fontColor: '#FFD700', fontWeight: FontWeight.Bold })
716    },
717    {
718      start: 4,
719      length: 2,
720      styledKey: StyledStringKey.FONT,
721      styledValue: new TextStyle({ fontColor: '#FFD700', fontWeight: FontWeight.Bold })
722    }
723  ]);
724  controller: TextController = new TextController();
725
726  build() {
727    Row() {
728      Column({ space: 5 }) {
729        Text(undefined, { controller: this.controller })
730          .width(240)
731          .copyOption(CopyOptions.InApp)
732          .draggable(true)
733          .onAppear(() => {
734            this.paragraphStyledString2.appendStyledString(this.paragraphStyledString3);
735            this.paragraphStyledString1.appendStyledString(this.paragraphStyledString2);
736            this.controller.setStyledString(this.paragraphStyledString1);
737          })
738
739        Button("Renew")
740          .width(200)
741          .fontColor(Color.White)
742          .fontSize(18)
743          .backgroundColor('#3CB371')
744          .margin({ bottom: 10 })
745      }
746      .borderWidth(1).borderColor('#FFDEAD')
747      .margin({ left: 10 })
748    }
749    .height('60%')
750  }
751}
752```
753![StyledString_SceneDemo](figures/styledString_sceneDemo.png)
754