HarmonyOS鸿蒙Next中怎么实现当前朗读的段落内容来匹配页面中的内容,对页面中匹配的方案高亮显示,并且在读完当前页面的内容自动翻页的功能

HarmonyOS鸿蒙Next中怎么实现当前朗读的段落内容来匹配页面中的内容,对页面中匹配的方案高亮显示,并且在读完当前页面的内容自动翻页的功能 现在听书,每次都只能从章节头开始读,我是想通过TextReader中当前朗读的段落内容来匹配页面中的内容,对页面中匹配的方案高亮显示,并获取到当前domPos,通过PageDataInfo中的startDomPos,endDomPos来实现自动翻页;  但好像Reader Kit提供是的黑盒服务,没有对当前页面属性操作的方法?

4 回复

当前朗读的段落内容来匹配页面中的内容功能:

朗读位置高亮显示:

@Component
export struct HighlightTextReader {
  @State text: string = '这是一段示例文本,用于演示朗读时的高亮效果。这是第二句话。这是第三句话,比较长一些,包含更多的内容。';
  @State currentSentenceIndex: number = -1;
  private textReader: TextReader = new TextReader();
  private sentences: string[] = [];
  
  aboutToAppear() {
    // 分割文本为句子
    this.sentences = this.text.split(/(?<=[。?!.?!])/);
    
    // 注册朗读状态和进度监听
    this.textReader.on('stateChange', (state) => {
      if (state === TextReader.ReadState.COMPLETED) {
        this.currentSentenceIndex = -1;
      }
    });
    
    this.textReader.on('progressChange', (progress) => {
      // 根据进度计算当前句子索引
      const sentenceCount = this.sentences.length;
      const estimatedIndex = Math.floor(progress * sentenceCount);
      if (estimatedIndex !== this.currentSentenceIndex) {
        this.currentSentenceIndex = estimatedIndex;
      }
    });
  }
  
  build() {
    Column() {
      // 显示文本,当前句子高亮
      ForEach(this.sentences, (sentence: string, index: number) => {
        Text(sentence)
          .fontSize(16)
          .fontColor(index === this.currentSentenceIndex ? '#0000FF' : '#000000')
          .fontWeight(index === this.currentSentenceIndex ? 500 : 400)
      })
      
      Button('开始朗读')
        .onClick(() => {
          const readInfo = textReaderInfo('highlight_text', this.text);
          this.textReader.start(readInfo);
        })
    }
    .width('100%')
    .padding(15)
  }
  
  aboutToDisappear() {
    this.textReader.off('stateChange');
    this.textReader.off('progressChange');
    this.textReader.stop();
  }
}

自动翻页功能:通过注册朗读状态监听当状态TextReader.ReadState.COMPLETED时,播放下一章内容

  // 注册朗读状态监听
  this.textReader.on('stateChange', (state) => {
    switch (state) {
      case TextReader.ReadState.READING:
        console.info('正在朗读...');
        this.isReading = true;
        break;
      case TextReader.ReadState.PAUSED:
        console.info('朗读已暂停');
        this.isReading = false;
        break;
      case TextReader.ReadState.COMPLETED:
        console.info('朗读已完成');
        this.isReading = false;
        this.autoPlayNext();
        break;
      case TextReader.ReadState.STOPPED:
        console.info('朗读已停止');
        this.isReading = false;
        break;
    }
  });
  
  // 注册朗读进度监听
textReader.on('stateChange', (state: TextReader.ReadState) => {
this.currentProgress = progress * 100;
  if (state === TextReader.ReadState.COMPLETED) {
    const nextPageIndex = this.currentParagraphIndex + 1;
    if (nextPageIndex < this.readInfoList.length) {
      this.currentParagraphIndex = nextPageIndex;
      this.selectedReadInfo = this.readInfoList[nextPageIndex];
      textReader.start(this.selectedReadInfo);
      this.scrollToPage(nextPageIndex); // 滚动到对应位置
    }
  }
});

更多关于HarmonyOS鸿蒙Next中怎么实现当前朗读的段落内容来匹配页面中的内容,对页面中匹配的方案高亮显示,并且在读完当前页面的内容自动翻页的功能的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


通过ReadInfo结构中的id字段建立朗读段落与页面DOM元素的映射关系,结合startDomPos/endDomPos记录每个段落的位置信息:

interface PageDataInfo {
  id: string;
  startDomPos: number;
  endDomPos: number;
  highlightStyle: object; // 高亮样式对象
}
const readInfoList: TextReader.ReadInfo[] = [{
  id: 'para1',
  bodyInfo: '段落1内容',
  customData: { // 自定义扩展字段
    domPositions: { start: 0, end: 100 }
  }
}];

利用TextReader的状态回调与段落切换事件

// 监听朗读段落切换
TextReader.on('setArticle', (id: string) => {
  const currentPara = readInfoList.find(item => item.id === id);
  updateHighlight(currentPara.customData.domPositions);
});

// 监听朗读状态变化
TextReader.onStateChanged((state: TextReader.ReadState) => {
  if (state.state === 'completed') {
    handleAutoPageTurn();
  }
});

当朗读完成当前段落且到达页面末尾时触发翻页

function handleAutoPageTurn() {
  const currentIndex = this.dataSource.indexOf(this.currentHighlightId);
  if (currentIndex === this.dataSource.length - 1) {
    this.swiperController.showNext(); // Swiper翻页
    loadNextPageData(); // 加载下一页数据
  }
}

采用Swiper组件实现翻页动画:

Swiper(this.swiperController) {
  LazyForEach(this.dataSource, (item) => {
    Text(item.content)
      .onClick(() => TextReader.jumpTo(item.id)) // 点击段落跳转朗读
  })
}
.cacheCount(2) // 优化性能
.loop(false)

在HarmonyOS鸿蒙Next中,可通过AccessibilityExtensionAbility实现朗读匹配高亮与自动翻页。使用ArkTS声明式开发,通过AccessibilityEvent监听朗读位置变化,利用AccessibilityNode获取页面节点信息。当朗读到对应段落时,通过UI组件的状态属性动态修改文本样式实现高亮。监听TTS播放进度,结合ScrollContainer或List组件的scrollToIndex方法,在朗读完成时触发翻页动作。需在config.json中配置accessibilityCapabilities权限。

在HarmonyOS Next中,可以通过以下方案实现朗读段落匹配与高亮显示:

  1. 文本匹配与高亮

    • 使用TextReaderonParagraphStart回调获取当前朗读段落内容
    • 通过DOM查询匹配页面中的对应文本节点
    • 使用ElementsetStyle方法动态添加高亮样式:
    matchedElement.setStyle({
      backgroundColor: '#FFF2CC',
      transition: 'background-color 0.3s'
    })
    
  2. DOM位置追踪

    • 通过getBoundingClientRect()获取元素位置信息
    • 记录当前朗读段落的startDomPosendDomPos
    • 使用IntersectionObserver监听元素可见性
  3. 自动翻页实现

    const checkPageTurn = () => {
      if (currentDomPos.endDomPos > viewportHeight) {
        pageController.turnNextPage()
      }
    }
    
  4. 事件协调

    • onParagraphEnd回调中触发翻页检查
    • 使用防抖处理避免频繁翻页

需要自定义文本解析逻辑来建立朗读内容与DOM元素的映射关系,虽然Reader Kit不直接暴露DOM操作,但可以通过事件回调与页面元素联动实现需求。

回到顶部