写点什么

鸿蒙 Next Text 长文本实现展开收起 2 种模式

作者:auhgnixgnahz
  • 2025-06-23
    北京
  • 本文字数:2954 字

    阅读完需:约 10 分钟

当展示长文本时,通过会设置 maxLines(value: number),则文本最多不会超过指定的行。如果有多余的文本,可以通过 textOverflow 来指定截断方式。单独设置 textOverflow 不生效。设置 TextOverflow.None 与 TextOverflow.Clip 效果相同。


本文介绍 2 种样式的展开、收起样式:这里以 2 行为例


1.仿朋友圈样式,在内容文字下一行增加展开收起,这种实现比较简单,直接在文字下一行增加一个 Text,通过设置 maxLines 的值即可实现,如果想实现当大于指定行数才显示展开,可参考第二种方式计算文字行数。


2.仿头条新闻标题展开、收起样式,文本的末尾是…展开,由于直接设置 TextOverflow.Ellipsis 展开不能和第一行文字对齐。因此我们需要动态计算一下**(实际展示的文字+…展开)正好占两行时可展示多少个文字,这样就可以实现…展开展示到第二行的末尾。动态计算文本高度,需要用到 MeasureText.measureTextSize**代码种有注释,可以参考

实现效果:
实现代码:
import { LengthUnit, MeasureText } from '@kit.ArkUI';import { getScreenWidth } from '../utils/DisplayUtil';
@Entry@ComponentV2struct textExpand{ allContent:string = '道可道,非常道;名可名,非常名。无名,天地之始;有名,万物之母。故常无,欲以观其妙;常有,欲以观其徼。此两者,同出而异名,同谓之玄。玄之又玄,众妙之门。' @Local title:string= this.allContent; @Local title2:string=this.allContent; @Local titleMaxLine:number=2; @Local isExpand:boolean = false; @Local isExpand2:boolean = false; @Local textWidth:number = getScreenWidth()-20 textFontSize:number = 18
aboutToAppear(): void { this.collapseText() } build() {
Column({space:5}){ Text('仿微信朋友圈文本底部展开收起样式').fontSize(20).fontColor(Color.Red) Text(this.title).fontSize(this.textFontSize).fontColor(Color.Black) .textOverflow({overflow:TextOverflow.Ellipsis}) .maxLines(this.titleMaxLine) .lineSpacing({value:5,unit:LengthUnit.VP}) //设置文本的行间距
Text(this.isExpand?'收起':'展开').fontSize(this.textFontSize).fontColor(Color.Blue) .onClick(()=>{ if (this.isExpand) { this.titleMaxLine=2; this.isExpand=false; }else { this.titleMaxLine=-1; this.isExpand=true; }
}) Text('仿微头条文本末尾展开收起样式').fontSize(20).fontColor(Color.Red)

Text('文本组件宽:'+this.textWidth) Text(){ Span(this.title2).fontColor(Color.Black) Span(this.isExpand2?'收起':'展开').fontColor(Color.Blue) .onClick(()=>{ if (this.isExpand2) { this.collapseText() }else { this.expandText() } }) } .fontSize(this.textFontSize) .onSizeChange( (oldValue: SizeOptions, newValue: SizeOptions)=>{ this.textWidth = newValue.width as number })
}.alignItems(HorizontalAlign.Start) .padding({left:10,right:10})

} expandText(): void { this.isExpand2 = true; this.title2 = this.allContent; } //收起文本 collapseText(): void { // 展开文本的size let expandSize: SizeOptions = MeasureText.measureTextSize({ textContent: this.title2, //设置被计算文本内容 constraintWidth: this.textWidth,//设置被计算文本布局宽度 fontSize: this.textFontSize //设置被计算文本字体大小 });
// 将要收起的文本size let collapseSize: SizeOptions = MeasureText.measureTextSize({ textContent: this.title2, //设置被计算文本内容 constraintWidth: this.textWidth,//设置被计算文本布局宽度 fontSize: this.textFontSize, //设置被计算文本字体大小 maxLines: this.titleMaxLine //设置被计算文本最大行数 });
//收起的文本高度和展开时的文本高度相等时,不需要展示收起和展开,即不需要处理 if ((expandSize.height as number) == (collapseSize.height as number)) { this.isExpand2 = false; return; }
let clipTitle: string = this.title2 //因为设置Ellipsis之后,省略号显示到文本末尾 想要在省略号后面加展开, // 可以通过截断文字,然后再拼接...展开展示到文本末尾 //因此,需要计算展示多少个文字拼接上(...展开) 刚好展示到文本末尾
//这里介绍2种方法
//1.逐个遍历计算文字长度,找到最多可以展示多少个字符 let indexCursor = 0; while (true){ let tempTitle = this.title2.substring(0, indexCursor) + '...展开'; const currentLinesTextSize: SizeOptions = this.calcTextSize(tempTitle) //从第一个字符开始计算,直到.....展开内容高度刚好大于第二行时,截取上一个字符即 能展示的所有文字 if ((currentLinesTextSize.height as number) > (collapseSize.height as number)) { break }else { indexCursor++ } } clipTitle = this.title2.substring(0, indexCursor - 1); this.title2 = clipTitle + '...';
//2. 使用二分法查找正好两行的长度的字符串 // let leftCursor: number = 0; // let rightCursor: number = this.title2.length; // let cursor: number = Math.floor(rightCursor / 2); // let tempTitle: string = ''; // while (true) { // tempTitle = this.title2.substring(0, cursor) + '...展开'; // const currentLinesTextSize: SizeOptions = this.calTextSize(tempTitle) // // if ((currentLinesTextSize.height as number) > (collapseSize.height as number)) { // // 当前字符已超过两行,向左继续找 // rightCursor = cursor; // cursor = leftCursor + Math.floor((cursor - leftCursor) / 2); // } else { // // 当前字符小于两行了,可能已经ok,但仍需向右查找 // leftCursor = cursor; // cursor += Math.floor((rightCursor - cursor) / 2); // } // if (Math.abs(rightCursor - leftCursor) <= 1) { // // 两次指针基本重合了,代表已找到 // break; // } // } // clipTitle = this.title2.substring(0, cursor - 1); // this.title2 = clipTitle + '...'; this.isExpand2 = false; } calcTextSize(text:string):SizeOptions{ return MeasureText.measureTextSize({ textContent: text, fontSize: this.textFontSize, wordBreak: WordBreak.BREAK_ALL, //设置断行规则 constraintWidth: this.textWidth }); }}
复制代码


发布于: 刚刚阅读数: 3
用户头像

auhgnixgnahz

关注

还未添加个人签名 2018-07-10 加入

还未添加个人简介

评论

发布
暂无评论
鸿蒙Next Text长文本实现展开收起2种模式_鸿蒙Next_auhgnixgnahz_InfoQ写作社区