HarmonyOS 多条文字滚动

多条文字每条文字如果长度超出屏幕就进行滚动显示(跑马灯效果),每条只滚动一次,等全部滚动显示完再进行第二轮滚动。滚动显示到最后一个字就停止。Marquee组件会全部文字滚动出屏幕,然后停止的时候文字全部在屏幕外。

HarmonyOS
2024-12-25 13:23:35
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
Heiang

两种实现思路:

1、可以使用scroll自行封装的替代方案,scroll参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-container-scroll-V5

参考示例如下:

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  @State textList: string[] = [
    'this is a test string1 this is a test string1 this is a test string1',
    'this is a test string2 this is a test string2',
    'this is a test string3 this is a test string3 this is a test string3 this is a test string3',
  ]

  build() {
    Row() {
      Column() {
        myMarqueeCard({
          textList: this.textList,
        })
      }
      .width('100%')
      .margin(20)
    }
    .height('100%')
  }
}

@Component
struct myMarqueeCard {
  @Prop textList: string[]
  scroller1: Scroller = new Scroller()
  scroller2: Scroller = new Scroller()
  scroller3: Scroller = new Scroller()

  build() {
    Column() {
      this.SingleText(this.textList[0], this.scroller1)
      this.SingleText(this.textList[1], this.scroller2)
      this.SingleText(this.textList[2], this.scroller3)
    }
  }

  @Builder
  SingleText(text: string, scroller: Scroller) {
    Scroll(scroller) {
      Row() {
        Text(text).fontSize(30)
      }
    }
    .width(300)
    .scrollable(ScrollDirection.Horizontal)
    .enableScrollInteraction(false)
    .scrollBar(BarState.Off)
    .onAppear(() => {
      this.handleScroll(scroller)
    })
  }

  handleScroll(scroller: Scroller) {
    let timer: number = setInterval(() => {
      const curOffset: OffsetResult = scroller.currentOffset()
      scroller.scrollTo({
        xOffset: curOffset.xOffset + 50, yOffset: curOffset.yOffset, animation: {
          duration: 1000,
          curve: Curve.Linear
        }
      })
      if (scroller.isAtEnd()) {
        clearInterval(timer);
        if (this.scroller1.isAtEnd() && this.scroller2.isAtEnd() && this.scroller3.isAtEnd()) {
          // 其他操作
        }
      }
    }, 500)
  }
}

2、使用measure.measureText计算文本宽度,结合animation动画实现滚动效果,measure.measureText参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-measure-V5#measuretextmeasuretext

animation动画参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-animatorproperty-V5

示例参考:

import measure from '@ohos.measure';

@Entry
@Component
struct TextDemo {
  string1: string = 'start|测试文本测试文本测试文本测试文本测试文本测试文本测|end'
  string2: string = 'start|测试文本2测试文本2测试文本2测试文本2测试文本2测试|end'
  @State src: string = this.string1
  @State textOffset: number = 0
  @State textWidth: number = measure.measureText({
    textContent: this.src,
    fontWeight: FontWeight.Medium,
  })
  private columnWidth: number = 300;
  @State finishFlag: boolean = false;
  @State iterations: number = 1

  build() {
    Row() {
      Column() {
        Column() {
          if (this.finishFlag) {
            Text(this.src)
              .width(px2vp(this.textWidth))
              .maxLines(1)
              .fontWeight(FontWeight.Medium)
              .textAlign(TextAlign.Center)
              .offset({ x: 0 })
              .onAppear(() => {
                this.textOffset = 0
                this.textWidth = measure.measureText({
                  textContent: this.src,
                  fontWeight: FontWeight.Medium,
                })
                this.finishFlag = !this.finishFlag
              })
          } else {
            Text(this.src)
              .width(px2vp(this.textWidth))
              .maxLines(1)
              .fontWeight(FontWeight.Medium)
              .textAlign(TextAlign.Center)
              .offset({ x: this.textOffset })
              .animation({
                duration: 5000,
                iterations: this.iterations,
                curve: Curve.Linear,
                onFinish: () => {
                  //动画播放完的回调
                  if (this.src === this.string1) {
                    this.src = this.string2
                  } else {
                    this.src = this.string1
                  }
                  this.finishFlag = !this.finishFlag
                }
              })
              .onAppear(() => {
                this.textOffset = -px2vp(this.textWidth) + this.columnWidth
              })
          }
        }
        .alignItems(HorizontalAlign.Start)
        .backgroundColor(Color.Pink)
        .clip(true)
        .width(this.columnWidth)
      }
      .width('100%')
    }
    .height('100%')
  }
}

另外也可以使用animator模块对动画进一步封装,可以使动画重新播放等。animator参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-animator-V5

示例参考如下:

//Index.ets
import { AnimatorText, ChildController } from './AnimatorText' //引入文字动画模块

interface TextType {
  src: string,
  delayTime: number,
  controller: ChildController
}

@Entry
@Component
struct Index {
  textArr: TextType[] = [{
    src: 'start|我是一段很长很长很长很长很长很长很长很长很长的可以滚动的文字|end',
    delayTime: 0,
    controller: new ChildController()
  }, {
    src: 'start|我是第二段很长很长很长很长很长很长很长很长很长的可以滚动的文字哈哈哈|end',
    delayTime: 3000,
    controller: new ChildController()
  }, {
    src: 'start|我是第三段很长很长很长很长很长很长很长很长很长的可以滚动的文字啦啦啦|end',
    delayTime: 6000,
    controller: new ChildController()
  }]

  //开始/重新播放
  rePlay() {
    this.textArr.forEach(item => {
      item.controller.play();
    })
  }

  build() {
    Column() {
      Column({ space: 10 }) {
        ForEach(this.textArr, (item: TextType) => {
          AnimatorText({ textSrc: item.src, delayTime: item.delayTime, controller: item.controller })
        })
        Button('开始/重新播放').onClick(() => {
          this.rePlay()
        })
      }
    }
    .width('100%')
    .height('100%')
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
  }
}
//AnimatorText.ets 文字动画模块
import animator, { AnimatorResult } from '@ohos.animator';
import measure from '@ohos.measure';

//定义Controller类用于向父组件提供方法调用
export class ChildController {
  play = () => {
  }
}

@Component
export struct AnimatorText {
  private controller: ChildController = new ChildController();
  @Prop textSrc: string; //文本
  @Prop delayTime: number; //延时时间
  @State textOffset: number = 0
  @State textWidth: number = measure.measureText({
    textContent: this.textSrc,
    fontWeight: FontWeight.Medium,
  })
  private columnWidth: number = 300;
  @State finishFlag: boolean = true;
  @State iterations: number = 1
  private TAG: string = '[AnimatorTest]'
  private backAnimator: AnimatorResult | undefined = undefined
  create() {
    let _this = this
    this.backAnimator = animator.create({
      duration: 3000,
      easing: "linear",
      delay: this.delayTime,
      fill: "forwards",
      direction: "normal",
      iterations: 1,
      begin: 0,
      end: -px2vp(this.textWidth) + this.columnWidth
    })

    this.backAnimator.onFinish = () => {
      console.info(_this.TAG, 'backAnimator onfinish')
    }
    this.backAnimator.onFrame = (value: number) => {
      _this.textOffset = value
    }
    this.backAnimator.play()
  }

  private play = () => {
    if (this.backAnimator) {
      this.backAnimator.play()
    } else {
      this.create();
    }
  }

  aboutToAppear() {
    //绑定play方法提供给父组件调用
    if (this.controller) {
      this.controller.play = this.play
    }
  }

  aboutToDisappear() {
    // 由于backAnimator在onframe中引用了this, this中保存了backAnimator,
    // 在自定义组件消失时应该将保存在组件中的backAnimator置空,避免内存泄漏
    this.backAnimator = undefined;
  }

  build() {
    Column() {
      Text(this.textSrc)
        .width(px2vp(this.textWidth))
        .maxLines(1)
        .fontWeight(FontWeight.Medium)
        .textAlign(TextAlign.Center)
        .offset({ x: this.textOffset })
    }
    .alignItems(HorizontalAlign.Start)
    .backgroundColor(Color.Pink)
    .clip(true)
    .width(this.columnWidth)
  }
}
分享
微博
QQ
微信
回复
2024-12-25 14:59:18
相关问题
过长文字如何滚动显示
1983浏览 • 1回复 待解决
请问下有没有文字滚动动画组件?
601浏览 • 1回复 待解决
过长文字如何滚动显示,有人知道吗?
2060浏览 • 1回复 待解决
mysql存储过程中处理多条数据
2262浏览 • 1回复 待解决
HarmonyOS 文字行高设定后文字不居中
513浏览 • 1回复 待解决
HarmonyOS 文字测量
40浏览 • 1回复 待解决
HarmonyOS 计算文字高度
239浏览 • 1回复 待解决
HarmonyOS 文字fontFamily未生效
208浏览 • 1回复 待解决
HarmonyOS 嵌套滚动冲突
286浏览 • 1回复 待解决
HarmonyOS 文字前缀
68浏览 • 1回复 待解决
HarmonyOS 文字显示问题
544浏览 • 1回复 待解决
HarmonyOS 滚动列表问题?
262浏览 • 0回复 待解决
HarmonyOS 滚动列表问题
180浏览 • 1回复 待解决