多行文本省略的展开与显示

场景:文本组件在超出n行省略,并后面点击箭头展开收起,如下图所示:

多行文本省略的展开与显示-鸿蒙开发者社区

HarmonyOS
2024-05-26 11:27:54
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
wjmfzsz

使用的核心API

组件区域变化事件

RichText

核心代码解释

实现该功能目前平台的Text组件不支持功能,所以我们自己想办法来实现,我这里总结了两种平替解决方案,都有瑕疵,希望后续HarmonyOS能支持该功能。

解决方案一:配合定位实现

思路:获取组件的Area区域,配合定位给按钮设置Position位置来实现。

核心代码如下

@Entry 
@Component 
struct TextEllipsis { 
  @State open: boolean = false 
  @State textMaxLines: number = this.open ? 999 : 3 
  @State btnText: string = this.open ? "收起" : "展开" 
  @State btnPosition: Position = { x: 0, y: 0 } 
 
  build() { 
    Flex({ 
      direction: FlexDirection.Column, alignItems: ItemAlign.Center, 
      justifyContent: FlexAlign.Center 
    }) { 
      Row() { 
        Text() { 
          Span("我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略我要省略") 
        } 
        .backgroundColor(Color.White) 
        .padding(20) 
        .textOverflow({ overflow: TextOverflow.Ellipsis }) 
        .maxLines(this.textMaxLines) // text组件支持设置多行文本省略但是不支持后面的展开与隐藏按钮 
        .padding({ 
          left: 10, 
          right: 30, 
          top: 10, 
          bottom: 10, 
        }) 
        .onAreaChange((oldValue: Area, newValue: Area) => { 
          this.btnPosition.x = Number(newValue.width) - 32 
          this.btnPosition.y = Number(newValue.height) - 20 
        }) 
 
        Text(this.btnText) 
          .onClick(() => { 
            this.open = !this.open 
            this.textMaxLines = this.open ? 3 : 999 
            this.btnText = this.open ? "展开" : "收起" 
          }) 
          .position(this.btnPosition) 
          .backgroundColor(Color.Green) 
      } 
 
    }.width("100%").height("100%").backgroundColor(Color.Pink) 
  } 
}

效果如下所示:

但是这种方案有一个小瑕疵,按钮会挡住后面的省略号,要么就是加大右侧空间让省略号展示,但是这样很不美观,这个目前没有办法解决

还有一种同思路的解决方案是将文字进行裁剪,但是需要计算文字宽度对应到多少字的时候省略,这样逻辑会比较复杂,而且针对移动端多设备切换不好兼容。【暂不考虑】

解决方案二:使用RichText富文本实现

RichText可以展示HTML的内容,而HTML可以使用强大的CSS来实现该功能。

核心代码如下:

@Entry 
@Component 
struct RichTextExample { 
  @State data: string = ` 
  <!DOCTYPE html> 
  <html lang="en"> 
    <head> 
      <meta charset="UTF-8" /> 
      <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 
      <title>Document</title> 
      <style> 
        .wrapper { 
          display: flex; 
          overflow: hidden; 
          border-radius: 8px; 
          padding: 15px; 
          box-shadow: 20px 20px 60px #bebebe, -20px -20px 60px #ffffff; 
        } 
        .text { 
          font-size: 20px; 
          overflow: hidden; 
          text-overflow: ellipsis; 
          text-align: justify; 
          display: -webkit-box; 
          -webkit-line-clamp: 3; 
          -webkit-box-orient: vertical; 
          position: relative; 
        } 
        .text::before { 
          content: ''; 
          height: calc(100% - 20px); 
          float: right; 
        } 
        .btn { 
          float: right; 
          clear: both; 
          margin-left: 10px; 
          font-size: 20px; 
          padding: 0 8px; 
          background: #3f51b5; 
          line-height: 20px; 
          border-radius: 4px; 
          color: #fff; 
          cursor: pointer; 
        } 
        .btn::before { 
          content: '展开'; 
        } 
        .exp { 
          display: none; 
        } 
        .exp:checked + .text { 
          -webkit-line-clamp: 999; 
        } 
        .exp:checked + .text::after { 
          visibility: hidden; 
        } 
        .exp:checked + .text .btn::before { 
          content: '收起'; 
        } 
      </style> 
    </head> 
    <body> 
      <div class="wrapper"> 
        <input id="exp1" class="exp" type="checkbox" /> 
        <div class="text"> 
          <label class="btn" for="exp1"></label> 
          浮动元素是如何定位的 
          正如我们前面提到的那样,当一个元素浮动之后,它会被移出正常的文档流,然后向左或者向右平移,一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素。 
          在下面的图片中,有三个红色的正方形。其中有两个向左浮动,一个向右浮动。要注意到第二个向左浮动的正方形被放在第一个向左浮动的正方形的右边。如果还有更多的正方形这样浮动,它们会继续向右堆放,直到填满容器一整行,之后换行至下一行。 
        </div> 
      </div> 
    </body> 
  </html> 
  `; 
 
  build() { 
    Flex({ 
      direction: FlexDirection.Column, alignItems: ItemAlign.Center, 
      justifyContent: FlexAlign.Center 
    }) { 
      RichText(this.data) 
        .onStart(() => { 
          console.info('RichText onStart'); 
        }) 
        .onComplete(() => { 
          console.info('RichText onComplete'); 
        }) 
        .width("100%") 
        .height("100%") 
        .backgroundColor(0XBDDB69) 
    } 
  } 
}

效果如下所示:

如上图,使用RichText可以实现该效果,不遮挡省略号,也能支持展开收起添加动画等等,但是该方法有一个弊端是——无法动态渲染数据,只能用于静态展示数据,业务RichText中渲染的是HTML字符串,无法做到数据更新页面刷新,也无法监听事件。

注明适配的版本信息

IDE:DevEco    Studio 4.0.3.600

SDK:HarmoneyOS    4.0.10.11

分享
微博
QQ
微信
回复
2024-05-27 11:27:31
相关问题
ArkTS实现Text文本【...展开
345浏览 • 1回复 待解决
如何实现文本展开收起功能
160浏览 • 1回复 待解决
如何计算文本是否溢出省略
453浏览 • 1回复 待解决
Text组件是否支持多行显示
569浏览 • 1回复 待解决
Text怎么显示带html标签文本
2918浏览 • 1回复 待解决
webview 如何显示文本html内容?
532浏览 • 1回复 待解决
使用Drawing实现图形绘制显示
365浏览 • 1回复 待解决
DevEco Studio如何打开多行页签?
205浏览 • 1回复 待解决
如何实现多行输入,你知道吗?
623浏览 • 1回复 待解决
camera demo可执行文件编译
2418浏览 • 0回复 待解决