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