实现文字自动上下轮播
方案选取:
- Marquee组件只支持横向滚动,因此,并不支持。
- 而鸿蒙中能支持上下滚动效果的组件包括:List、Swiper和Scroll。
- 通过支持上下滚动效果的组件自定义实现
目前使用的是Swiper方案
呈现出来的效果如图:

代码解释:
- 方法getBannerSwiperMaxText:这个方法主要是获取到最大字数的字符串,用于实现固定宽度使用。
- 方法getBannerSwiperWidth:这个方法主要是通过获取到的字符串,通过MeasureText,动态计算当前容器所需要的的宽度
- 方法refundCardOverdueBuilder:核心方法,使用Swiper来实现。
核心代码如下:
getBannerSwiperWidth(): number {
let textSize: SizeOptions = MeasureText.measureTextSize({
textContent: this.getBannerSwiperMaxText(),
fontSize: 11
});
return px2vp(Number(`${textSize.width}`)) + 20
}
getBannerSwiperMaxText(): string {
let maxText = '默认文本';
if (ArrayUtil.isNotEmpty(this.viewModel.returnGoodListBean)) {
this.viewModel.returnGoodListBean?.forEach((info: RefundCardBeanInfo) => {
if (StrUtil.isNotBlank(info?.content) && info?.content?.length > maxText?.length) {
maxText = info?.content
}
})
}
return maxText
}
@Builder
refundCardOverdueBuilder() {
Stack({ alignContent: Alignment.Bottom }) {
Image($r('app.media.ic_bg2_overdue'))
.height(24)
Swiper() {
ForEach(this.viewModel.returnGoodListBean, (info: RefundCardBeanInfo) => {
Text(info?.content)
.fontColor(Color.White)
.fontSize(11)
.padding({
left: 10,
right: 10
})
})
}
.vertical(true)
.autoPlay(true)
.interval(2000)
.indicator(false)
.loop(true)
.width(this.getBannerSwiperWidth())
.height(20)
.margin({ bottom: 4 })
.borderRadius(50)
.backgroundColor('#FF66AA')
}
.visibility(ArrayUtil.isNotEmpty(this.viewModel.returnGoodListBean) ? Visibility.Visible :
Visibility.None)
.alignRules({
top: { anchor: '__container__', align: VerticalAlign.Top },
left: { anchor: 'refund_card_money', align: HorizontalAlign.Start },
right: { anchor: 'refund_card_money', align: HorizontalAlign.End }
})
}
其他方案:Scroll:
- 需要实现自动轮播的定时器:setInterval
- clearTimeout:取消由 setTimeout 设置的定时器
核心代码如下
@Builder
SingleText($$: Tmp) {
Scroll($$.scroller) {
Row() {
Text($$.text)
.fontSize(30)
.onAppear(() => {
this.handleScroll($$.scroller);
})
}
}
.width(300)
.scrollable(ScrollDirection.Horizontal)
.enableScrollInteraction(false)
.scrollBar(BarState.Off)
}
handleScroll(scroller: Scroller) {
setInterval(() => {
const curOffset: OffsetResult = scroller.currentOffset();
scroller.scrollTo({
xOffset: curOffset.xOffset + 50, yOffset: curOffset.yOffset, animation: {
duration: 1000,
curve: Curve.Linear
}
});
if (scroller.isAtEnd()) {
if (this.scroller1.isAtEnd() && this.scroller2.isAtEnd() && this.scroller3.isAtEnd()) {
if (this.updateList) {
this.scroller1.scrollTo({ xOffset: 0, yOffset: 0, animation: { duration: 0 } });
this.scroller2.scrollTo({ xOffset: 0, yOffset: 0, animation: { duration: 0 } });
this.scroller3.scrollTo({ xOffset: 0, yOffset: 0, animation: { duration: 0 } });
this.updateList();
}
}
}
}, 500);
}
}