Skip to content

一个文本组件,支持特殊文本效果(比如图片,@人),自定义文本溢出效果(ellipsis), 多行文本溢出效果位置(ellipsisMode)的支持.

License

Notifications You must be signed in to change notification settings

HarmonyCandies/extended_text

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ea3a2d0 · Dec 12, 2024

History

18 Commits
Nov 12, 2024
Dec 12, 2024
Dec 12, 2024
Nov 12, 2024
Nov 14, 2024
Nov 12, 2024
Dec 12, 2024
Nov 12, 2024
Nov 12, 2024
Nov 12, 2024
Nov 12, 2024
Nov 21, 2024

Repository files navigation

extended_text

一个文本组件,支持特殊文本效果(比如图片,@人),自定义文本溢出效果(ellipsis), 多行文本溢出效果位置(ellipsisMode)的支持.

text_demo.png overflow.png
joinZeroWidthSpace.png textOverflowPosition_auto.png

关注公众号 糖果代码铺 ,获取更多鸿蒙开发资讯.

candies.png

安装

ohpm install @candies/extended_text

使用

完整例子: https://github.com/HarmonyCandies/extended_text/blob/main/entry/src/main/ets/pages/Index.ets

参数

参数 类型 描述
text string 字符串内容
textSpan InlineSpan 用于创建特殊文本的基类
joinZeroWidthSpace boolean 是否添加零宽度的空白
paragraphStyle text.ParagraphStyle (import { text } from "@kit.ArkGraphics2D") 文本的样式
overflowWidget TextOverflowWidget 用于定义溢出效果
specialTextSpanBuilder SpecialTextSpanBuilder 用于创建特殊文本
fontCollection text.FontCollection 自定义字体
import { ColorUtils, ExtendedText } from '@candies/extended_text'
import { MySpecialTextSpanBuilder } from '../text/special/MySpecialTextSpanBuilder';
 
@Entry
@Component
struct Index {
  private specialTextSpanBuilder: MySpecialTextSpanBuilder = new MySpecialTextSpanBuilder();
  context: Context = getContext(this);
  content: string = MySpecialTextSpanBuilder.content;
  @State joinZeroWidthSpace: boolean = false;

  build() {
    Column() {
      ExtendedText({
        text: this.content,
        specialTextSpanBuilder: this.specialTextSpanBuilder,
        paragraphStyle: {
          textStyle: {
            color: ColorUtils.resourceColorTo2DColor($r('sys.color.font'), this.context),
            fontSize: vp2px(18),
          },
        },
        joinZeroWidthSpace: this.joinZeroWidthSpace,
      })
    }
  }
}

InlineSpan

用于创建特殊文本的基类

参数 类型 描述
style text.TextStyle 文本的样式
actualText string 该特殊文本的真实文本(不一定等于显示的文本)
start number 该特殊文本位于整个文本中的位置
export interface InlineSpanOptions {
  style?: text.TextStyle;
  actualText?: string;
  start?: number;
}

TextSpan

继承于 InlineSpan ,用于显示纯文本。

参数 类型 描述
text string 显示的文案
children Array 作为子节点,类型是 InlineSpan
export interface TextSpanOptions extends InlineSpanOptions {
  text?: string;
  children?: Array<InlineSpan>;
}

PlaceholderSpan

用于占位符的 Span

参数 类型 描述
align text.PlaceholderAlignment 占位符的对齐方式
baseline text.TextBaseline 占位符的基线类型
baselineOffset number 位符的基线偏移量
export interface PlaceholderSpanOptions extends InlineSpanOptions {
  /**
   * Alignment mode of placeholder.
   * @type { PlaceholderAlignment }
   * @syscap SystemCapability.Graphics.Drawing
   * @since 12
   */
  align?: text.PlaceholderAlignment;

  /**
   * Baseline of placeholder.
   * @type { TextBaseline }
   * @syscap SystemCapability.Graphics.Drawing
   * @since 12
   */
  baseline?: text.TextBaseline;

  /**
   * Baseline offset of placeholder.
   * @type { number }
   * @syscap SystemCapability.Graphics.Drawing
   * @since 12
   */
  baselineOffset?: number;
}

WidgetSpan

继承于 PlaceholderSpan ,用于显示显示组件。

参数 类型 描述
builder WrappedBuilder<[ESObject]> 用于显示组件的 WrappedBuilder
builderArgs ESObject 用于显示组件的 WrappedBuilder 的参数
hide boolean 是否需要显示该组件
export interface WidgetSpanOptions extends PlaceholderSpanOptions {
  builder: WrappedBuilder<[ESObject]>;
  builderArgs: ESObject;
  hide?: boolean,
}

注意: buildHyperlink 只能是全局的 @Builder

@Builder
export function buildHyperlink(builderArgs: ESObject) {
  Row(){
     Hyperlink(builderArgs[0], builderArgs[1])
  }
}

  return new WidgetSpan({
    builder: wrapBuilder<[ESObject]>(buildHyperlink),
    builderArgs: [href, content],
    style: {
      fontSize: vp2px(18), color: extended_text.ColorUtils.resourceColorTo2DColor(Color.Blue),
      fontWeight: text.FontWeight.W600,
    },
    actualText: this.toString(),
    start: this.start,
  });

OverflowWidget

用于自定义文本的溢出效果。

  • 目前官方支持修改 ellipsis ,但是只能是字符串
  • 目前官方支持 ellipsisMode,但是只支持单行文本
参数 类型 描述
builder WrappedBuilder<[ESObject]> 用于显示溢出组件的 WrappedBuilder
builderArgs ESObject 用于显示溢出组件的 WrappedBuilder 的参数
position TextOverflowPosition 用于控制溢出组件的位置(start,middle,end)
export enum TextOverflowPosition {
  /// at the start of text view.
  start,
  /// at the middle of text view.
  middle,
  /// at the end of text view.
  end,
  /// make sure the keepVisible span in text view.
  /// [See also]: https://github.com/HarmonyCandies/extended_text/blob/main/entry/src/main/ets/pages/SearchHighlightDemo.ets  
  auto,
}

export interface TextOverflowWidgetOptions {
  builder: WrappedBuilder<[ESObject]>;
  position?: TextOverflowPosition;
  builderArgs?: ESObject;
}

SpecialTextSpanBuilder

帮助将字符串文本快速转换为特殊的 InlineSpan

SpecialText

下面的例子告诉你怎么创建一个 $xxx$

具体思路是对字符串进行进栈遍历,通过判断 flag 来判定是否是一个特殊字符。 例子:$xxx$ ,以 $ 开头并且以 $ 结束,我们就认为它是一个 $xxx$ 的特殊文本

export class DollarText extends extended_text.SpecialText {
  static flag: string = '$';

  constructor(context: Context, start?: number, textStyle?: text.TextStyle,) {
    super(DollarText.flag, DollarText.flag, context, start, textStyle);
  }

  finishText(): extended_text.InlineSpan {
    let text = this.getContent();
    return new TextSpan({
      text: text,
      style: {
        fontSize: vp2px(18), color: extended_text.ColorUtils.resourceColorTo2DColor(Color.Orange),
      },
      actualText: this.toString(),
      start: this.start,
    });
  }
}

特殊文本 Builder

创建属于你自己规则的 Builder,上面说了你可以继承 SpecialText 来定义各种各样的特殊文本。

  • build 方法中,是通过具体思路是对字符串进行进栈遍历,通过判断 flag 来判定是否是一个特殊文本。 感兴趣的,可以看一下 SpecialTextSpanBuilder 里面 build 方法的实现,当然你也可以写出属于自己的 build 逻辑
  • createSpecialText 通过判断 flag 来判定是否是一个特殊文本
import * as extended_text from '@candies/extended_text'
import { text } from "@kit.ArkGraphics2D"
import { DollarText } from './DollarText';
import { EmojiText } from './EmojiText';
import { LinkText } from './LinkText';

export class MySpecialTextSpanBuilder extends extended_text.SpecialTextSpanBuilder {
  createSpecialText(flag: string, index: number, context: Context,
    textStyle?: text.TextStyle | undefined): extended_text.SpecialText | null {
    if (this.isStart(flag, EmojiText.flag)) {
      return new EmojiText(context, index - (EmojiText.flag.length - 1), textStyle,);
    } else if (this.isStart(flag, DollarText.flag)) {
      return new DollarText(context, index - (DollarText.flag.length - 1), textStyle);
    } else if (this.isStart(flag, LinkText.flag)) {
      return new LinkText(context, index - (LinkText.flag.length - 1), textStyle);
    }
    return null;
  }
}

RegExpSpecialTextSpanBuilder

当然,也提供了通过正则的方式,创建特殊文本的方式。

RegExpSpecialText

下面的例子告诉你怎么创建一个 $xxx$

你只需要继承 RegExpSpecialText , 并且写出来对应的正则表达式即可。

import * as extended_text from '@candies/extended_text'
import { TextSpan } from '@candies/extended_text';
import { text } from "@kit.ArkGraphics2D"


export class RegExpDollarText extends extended_text.RegExpSpecialText {
  get regExp(): RegExp {
    return new RegExp('\\$(.+?)\\$', 'g');
  }
  finishText(start: number,
    match: RegExpExecArray,
    context: Context,
    textStyle?: text.TextStyle,): extended_text.InlineSpan {
    let text = match[0];
    return new TextSpan({
      text: text.replaceAll('$', ''),
      style: {
        fontSize: vp2px(18), color: extended_text.ColorUtils.resourceColorTo2DColor(Color.Orange),
      },
      actualText: this.toString(),
      start: start,
    });
  }
}

特殊文本 Builder

将上一步创建的 RegExpSpecialText,放到 regExps 当中即可。

import { RegExpSpecialTextSpanBuilder } from '@candies/extended_text';
import { RegExpEmojiText } from './EmojiText';
import { RegExpDollarText } from './DollarText';
import { RegExpLinkText } from './LinkText';


export class MyRegExpSpecialTextSpanBuilder extends RegExpSpecialTextSpanBuilder {
  get regExps() {
    return [
      new RegExpDollarText(),
      new RegExpEmojiText(),
      new RegExpLinkText(),
    ];
  }
}

About

一个文本组件,支持特殊文本效果(比如图片,@人),自定义文本溢出效果(ellipsis), 多行文本溢出效果位置(ellipsisMode)的支持.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published