OpenHarmony开发者论坛

标题: RichEditor组件样例开发 [打印本页]

作者: 深开鸿_董伟    时间: 2024-3-22 15:45
标题: RichEditor组件样例开发
[md]# RichEditor组件样例开发

使用richEditor组件实现一个富文本编辑框,包含富文本编辑区域和功能栏,功能栏中有多个按键,可以调整字体大小、字体样式、字体颜色、布局,并可以插入图片。

api版本:api11

## 主页面

```
import { TitleBar } from '../../../../common/TitleBar';
import { Title } from './Title';

@Extend(Column) function cardStyle() {
  .backgroundColor(Color.White)
  .borderRadius(24)
  .width('100%')
  .padding(5)
}

@Entry
@Component
struct RichEditorSample {
  @State setStyle: Boolean = false;
  @State setStyle1: Boolean = false;
  @State setStyle2: Boolean = false;
  @State setStyle3: Boolean = false;
  @State setStyle4: Boolean = false;
  @State setStyle5: Boolean = false;
  @State setStyle6: Boolean = false;
  @State styleDialog: Visibility = Visibility.None;
  @State fontWeightSet: FontWeight = FontWeight.Normal;
  @State fontStyleSet: FontStyle = FontStyle.Normal;
  @State fontDecorationSet: TextDecorationType = TextDecorationType.None;
  @State fontAlignLeftSet: TextAlign = TextAlign.Start;
  @State fontAlignMiddleSet: TextAlign = TextAlign.Center;
  @State fontAlignRightSet: TextAlign = TextAlign.End;
  @State tipsValue: number = 32;
  private start: number = -1;
  private end: number = -1;
  private fontColors: string[] = ["#FA2A2D","#FFBF00","#41BA41","#00AAEE","#3F56EA","#8A2BE2","#000000"];

  controller: RichEditorController = new RichEditorController();

  updateVisible(){
   this.setStyle = !this.setStyle;
   if(this.setStyle){
     this.styleDialog = Visibility.Visible;
   }else{
     this.styleDialog = Visibility.None;
   }
  }

  updateFontWeight(){
   this.setStyle1 = !this.setStyle1;
   if(this.setStyle1){
     this.fontWeightSet = FontWeight.Bolder;
   }else{
     this.fontWeightSet = FontWeight.Normal;
   }
  }

  updateFontStyle(){
   this.setStyle2 = !this.setStyle2;
   if(this.setStyle2){
     this.fontStyleSet = FontStyle.Italic;
   }else{
     this.fontStyleSet = FontStyle.Normal;
   }
  }

  updateFontDecoration(){
   this.setStyle3 = !this.setStyle3;
   if(this.setStyle3){
     this.fontDecorationSet = TextDecorationType.Underline;
   }else{
     this.fontDecorationSet = TextDecorationType.None;
   }
  }

  updateFontAlignLeft(){
   this.setStyle4 = !this.setStyle4;
   if(this.setStyle4){
     this.fontAlignLeftSet = TextAlign.Start;
   }else{
     this.fontAlignLeftSet = TextAlign.JUSTIFY;
   }
  }

  updateFontAlignMiddle(){
   this.setStyle5 = !this.setStyle5;
   if(this.setStyle5){
     this.fontAlignMiddleSet = TextAlign.Center;
   }else{
     this.fontAlignMiddleSet = TextAlign.JUSTIFY;
   }
  }

  updateFontAlignRight(){
   this.setStyle6 = !this.setStyle6;
   if(this.setStyle6){
     this.fontAlignRightSet = TextAlign.End;
   }else{
     this.fontAlignRightSet = TextAlign.JUSTIFY;
   }
  }

  build() {
   Column() {
     TitleBar({ title: $r('app.string.rich_editor_title') })
     Scroll() {
       Column() {
         Title({titler('app.string.rich_editor_title')})
           .height("10%")
         RichEditor({ controller: this.controller })
           .onReady(() => {
             this.controller.addTextSpan("Hello World。\n" +
               "Familiar images automatically give people a sense of calm and nostalgia. " +
               "Early web designers liked the elements of the 1980s, but today, the aesthetics of the 1990s.\n",
               {
                 style:
                 {
                   fontColor: Color.Black,
                   fontSize: 16
                 }
               })
             this.controller.addImageSpan($r("app.media.addPhoto"),
               {
                 imageStyle:
                 {
                   size: ["100px", "54px"]
                 }
               })
           })
           .onSelect((value: RichEditorSelection) => {
             this.start = value.selection[0];
             this.end = value.selection[1];
           })
           .height("50%")
           .width("100%")
         Stack() {
           Column() {
             Row({ space: 250 }) {
               Text($r('app.string.rich_editor_style'))
                 .fontSize(14)
                 .padding({top:5})
               Image($r('app.media.ic_close'))
                 .width(25)
                 .height(25)
                 .onClick(() => {
                   this.styleDialog = Visibility.None
                 })
             }.height(25)
             .margin({bottom:10})

             Row({ space: 38 }) {
               Image($r('app.media.ic_B_normal'))
                 .width(15)
                 .height(15)
                 .onClick(() => {
                   this.updateFontWeight()
                   if(this.end!=this.start){
                     this.controller.updateSpanStyle({
                       start: this.start,
                       end: this.end,
                       textStyle:
                       {
                         fontWeight: this.fontWeightSet
                       }
                     })
                   }
                 })
               Image($r('app.media.ic_I_normal'))
                 .width(15)
                 .height(15)
                 .onClick(() => {
                   this.updateFontStyle()
                   if(this.end!=this.start) {
                     this.controller.updateSpanStyle({
                       start: this.start,
                       end: this.end,
                       textStyle:
                       {
                         fontStyle: this.fontStyleSet
                       }
                     })
                   }
                 })
               Image($r('app.media.ic_U_normal'))
                 .width(15)
                 .height(15)
                 .onClick(() => {
                   this.updateFontDecoration()
                   if(this.end!=this.start) {
                     this.controller.updateSpanStyle({
                       start: this.start,
                       end: this.end,
                       textStyle:
                       {
                         decoration: {
                           type: this.fontDecorationSet
                         }
                       }
                     })
                   }
                 })
               Image($r('app.media.ic_left_normal'))
                 .width(15)
                 .height(15)
                 .onClick(() => {
                   this.updateFontAlignLeft()
                   if(this.end!=this.start) {
                     this.controller.updateParagraphStyle({
                       start: this.start,
                       end: this.end,
                       style:
                       {
                         textAlign:this.fontAlignLeftSet
                       }
                     })
                   }
                 })
               Image($r('app.media.ic_middle_normal'))
                 .width(15)
                 .height(15)
                 .onClick(() => {
                   this.updateFontAlignMiddle()
                   if(this.end!=this.start) {
                     this.controller.updateParagraphStyle({
                       start: this.start,
                       end: this.end,
                       style:
                       {
                         textAlign:this.fontAlignMiddleSet
                       }
                     })
                   }
                 })
               Image($r('app.media.ic_right_normal'))
                 .width(15)
                 .height(15)
                 .onClick(() => {
                   this.updateFontAlignRight()
                   if(this.end!=this.start) {
                     this.controller.updateParagraphStyle({
                       start: this.start,
                       end: this.end,
                       style:
                       {
                         textAlign:this.fontAlignRightSet
                       }
                     })
                   }
                 })
             }
             .height(25)
             .margin({bottom:10})

             Row({ space: 30 }) {
               ForEach(this.fontColors,(item: string) => {
                 Circle({ width: 15, height: 15 }).fill(item)
                   .onClick(() => {
                     if(this.end!=this.start){
                       this.controller.updateSpanStyle({
                         start: this.start,
                         end: this.end,
                         textStyle:
                         {
                           fontColor: item
                         }
                       })
                     }
                   })
               })
             }.height(25)
             .margin({bottom:10})

             Row({ space: 30 }) {
               Text("Aa")
                 .width(24)
                 .height(24)
                 .fontSize(11)
                 .fontWeight(400)
                 .onClick(() => {
                   this.tipsValue = this.tipsValue - 2
                   if(this.end!=this.start){
                     this.controller.updateSpanStyle({
                       start: this.start,
                       end: this.end,
                       textStyle:
                       {
                         fontSize: this.tipsValue/2
                       }
                     })
                   }
                 })
               Slider({ style: SliderStyle.InSet, value: this.tipsValue })
                 .width(210)
                 .showTips(true, 'Size:' + this.tipsValue.toFixed())
                 .onChange(value => {
                   this.tipsValue = value
                   if(this.end!=this.start){
                     this.controller.updateSpanStyle({
                       start: this.start,
                       end: this.end,
                       textStyle:
                       {
                         fontSize: this.tipsValue/2
                       }
                     })
                   }
                 })
               Text("Aa")
                 .width(24)
                 .height(24)
                 .fontSize(17)
                 .fontWeight(400)
                 .onClick(() => {
                   this.tipsValue = this.tipsValue + 2
                   if(this.end!=this.start){
                     this.controller.updateSpanStyle({
                       start: this.start,
                       end: this.end,
                       textStyle:
                       {
                         fontSize: this.tipsValue/2
                       }
                     })
                   }
                 })
             }.height(25).margin({bottom:60})

           }.visibility(this.styleDialog)
           .width("100%")
           .height("85%")
           .margin({bottom:"85%"})
           .zIndex(1)
           .border({
             radius: { topLeft: 15, topRight: 15 },
           })
           .backgroundColor($r('app.color.background_light_gray'))

           Row({ space: 150 }) {
             Image($r('app.media.ic_textstyle_normal'))
               .width(40)
               .height(40)
               .onClick(() => {
                 this.updateVisible()
               })
             Image($r('app.media.ic_picture_normal'))
               .width(35)
               .height(35)
               .onClick(() => {
                 this.controller.addImageSpan($r("app.media.addPhoto"),
                   {
                     imageStyle:
                     {
                       size: ["100px", "54px"]
                     }
                   })
               })
           }
           .padding({top:"50%"})
           .justifyContent(FlexAlign.Center)
           .width("100%")
           .height("15%")
           .zIndex(3)
         }.height("30%")
       }
       .alignItems(HorizontalAlign.Start)
       .cardStyle()
       .constraintSize({ minHeight: '100%' })
     }
     .width('95%')
     .height('80%')
     .backgroundColor($r('app.color.divider_block_color'))
   }.height('100%')
   .width('100%')
   .backgroundColor($r('app.color.divider_block_color'))
   .padding({ left: 20, right: 20 })
  }
}

```

## title组件

```

@Component
export struct Title {
  private title!: Resource;

  build() {
   Column() {
     Row() {
       Text(this.title)
         .fontSize(24)
         .fontWeight(FontWeight.Bold)
     }
     .margin({top:"2%",left:"5%"})
     .width('100%')
   }
   .height('100%')
  }
}
```

## 更新字体样式

```
@State setStyle: Boolean = false;
@State fontWeightSet: FontWeight = FontWeight.Normal;
private start: number = -1;
private end: number = -1;
controller: RichEditorController = new RichEditorController();

updateFontWeight(){
  this.setStyle1 = !this.setStyle1;
  if(this.setStyle1){
   this.fontWeightSet = FontWeight.Bolder;
  }else{
   this.fontWeightSet = FontWeight.Normal;
  }
}

Image($r('app.media.ic_B_normal'))
  .width(15)
  .height(15)
  .onClick(() => {  
    this.updateFontWeight()
    if(this.end!=this.start){
      this.controller.updateSpanStyle({
        start: this.start,
        end: this.end,
        textStyle:
        {
           fontWeight: this.fontWeightSet
        }
     })
    }
})
```

设置一个boolean类型变量setStyle1,设置字体是否加粗,以setStyle1的值来控制

点击加粗按钮,setStyle变为true,修改fontWeightSet的值,再通过RichEditor组件控制器的方法updateSpanStyle改变选中字段的样式

## 自定义字体选择滑动条

```
@State tipsValue: number = 32;

Slider({ style: SliderStyle.InSet, value: this.tipsValue })
  .width(210)
  .showTips(true, 'Size:' + this.tipsValue.toFixed())
  .onChange(value => {
   this.tipsValue = value
   if(this.end!=this.start){
     this.controller.updateSpanStyle({
       start: this.start,
       end: this.end,
       textStyle:
       {
         fontSize: this.tipsValue/2
       }
     })
   }
  })
```

初始字号为16,随着slider组件的滑动,字号随之变化

## 总结:

通过controller.updateSpanStyle接口修改字体的样式,通过controller.addImageSpan来插入图片,使用了RichEditor、Slider等组件实现一个富文本编辑功能页面。

## 注意:

RichEditor组件框架层未处理拉起输入法时的界面规避,需要应用层处理,代码如下:

```
import { KeyboardAvoidMode } from '@ohos.arkui.UIContext';

onWindowStageCreate(windowStage){
   windowStage.loadContent('pages/Index', (err, data) => {
    let a = windowStage.getMainWindowSync().getUIContext().getKeyboardAvoidMode();
    windowStage.getMainWindowSync().getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.OFFSET);
    if (err) {
       Logger.error(TAG, `Failed to load the content. Cause: ${JSON.stringify(err)}`)
       return
     }
    Logger.info(TAG, `Succeeded in loading the content. Data: ${JSON.stringify(data)}`)
  })
}
```

在应用MainAbility/MainAbility.ts文件中实现
[/md]
作者: mean    时间: 2024-4-7 11:42
学习了




欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/) Powered by Discuz! X3.5