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

场景:文本组件在超出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
相关问题
HarmonyOS Text多行文本不能居中对齐
431浏览 • 1回复 待解决
多行文字后面添加标签
186浏览 • 1回复 待解决
ArkTS实现Text文本【...展开
1535浏览 • 2回复 待解决
Text组件是否支持多行显示
1912浏览 • 1回复 待解决
如何计算文本是否溢出省略
1618浏览 • 1回复 待解决
如何实现文本展开收起功能
749浏览 • 1回复 待解决
HarmonyOS Text超出显示省略
385浏览 • 1回复 待解决
HarmonyOS 如何进行文本文件读取?
109浏览 • 1回复 待解决
webviewControllerloadData无法显示文本
1854浏览 • 1回复 待解决
如何获取文本显示宽度和高度?
277浏览 • 1回复 待解决
Text怎么显示带html标签文本
4276浏览 • 1回复 待解决