HarmonyOS 鸿蒙Next中页签随滚动收缩隐藏的效果

HarmonyOS 鸿蒙Next中页签随滚动收缩隐藏的效果 本应用社区页面,在滚动话题后页签会自动收缩隐藏。这个效果有提供选项来开启吗?还是说这是自定义动画来实现的?

9 回复

当使用bindTabsToScrollablebindTabsToNestedScrollable等接口绑定了Tabs组件和可滚动容器组件后,在滑动可滚动容器组件时,会触发所有与其绑定的Tabs组件的TabBar的显示和隐藏动效。

参考示例:

cke_8142.gif

@Entry
@Component
struct TabsExample {
  private arr: string[] = [];
  private parentTabsController: TabsController = new TabsController();
  private childTabsController: TabsController = new TabsController();
  private listScroller: Scroller = new Scroller();
  private parentScroller: Scroller = new Scroller();
  private childScroller: Scroller = new Scroller();

  aboutToAppear(): void {
    for (let i = 0; i < 20; i++) {
      this.arr.push(i.toString());
    }
    let context = this.getUIContext();
    context.bindTabsToScrollable(this.parentTabsController, this.listScroller);
    context.bindTabsToScrollable(this.childTabsController, this.listScroller);
    context.bindTabsToNestedScrollable(this.parentTabsController, this.parentScroller, this.childScroller);
  }

  aboutToDisappear(): void {
    let context = this.getUIContext();
    context.unbindTabsFromScrollable(this.parentTabsController, this.listScroller);
    context.unbindTabsFromScrollable(this.childTabsController, this.listScroller);
    context.unbindTabsFromNestedScrollable(this.parentTabsController, this.parentScroller, this.childScroller);
  }

  build() {
    Tabs({ barPosition: BarPosition.End, controller: this.parentTabsController }) {
      TabContent() {
        Tabs({ controller: this.childTabsController }) {
          TabContent() {
            List({ space: 20, initialIndex: 0, scroller: this.listScroller }) {
              ForEach(this.arr, (item: string) => {
                ListItem() {
                  Text(item)
                    .width('100%')
                    .height(100)
                    .fontSize(16)
                    .textAlign(TextAlign.Center)
                    .borderRadius(10)
                    .backgroundColor(Color.Gray)
                }
              }, (item: string) => item)
            }
            .scrollBar(BarState.Off)
            .width('90%')
            .height('100%')
            .contentStartOffset(56)
            .contentEndOffset(52)
          }.tabBar(SubTabBarStyle.of('顶部页签'))
        }
        .width('100%')
        .height('100%')
        .barOverlap(true) // 使TabBar叠加在TabContent上,当TabBar向上或向下隐藏后,原位置处不为空白
        .clip(true) // 对超出Tabs组件范围的子组件进行裁剪,防止TabBar向上或向下隐藏后误触TabBar
      }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'scroller联动多个TabsController'))

      TabContent() {
        Scroll(this.parentScroller) {
            List({ space: 20, initialIndex: 0, scroller: this.childScroller }) {
              ForEach(this.arr, (item: string) => {
                ListItem() {
                  Text(item)
                    .width('100%')
                    .height(100)
                    .fontSize(16)
                    .textAlign(TextAlign.Center)
                    .borderRadius(10)
                    .backgroundColor(Color.Gray)
                }
              }, (item: string) => item)
            }
            .scrollBar(BarState.Off)
            .width('90%')
            .height('100%')
            .contentEndOffset(52)
            .nestedScroll({ scrollForward: NestedScrollMode.SELF_FIRST, scrollBackward: NestedScrollMode.SELF_FIRST })
        }
        .width('100%')
        .height('100%')
        .scrollBar(BarState.Off)
        .scrollable(ScrollDirection.Vertical)
        .edgeEffect(EdgeEffect.Spring)
      }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), '嵌套的scroller联动TabsController'))
    }
    .width('100%')
    .height('100%')
    .barOverlap(true) // 使TabBar叠加在TabContent上,当TabBar向上或向下隐藏后,原位置处不为空白
    .clip(true) // 对超出Tabs组件范围的子组件进行裁剪,防止TabBar向上或向下隐藏后误触TabBar
  }
}

更多关于HarmonyOS 鸿蒙Next中页签随滚动收缩隐藏的效果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


测试发现,在 API 23 使用 barFloatingStyle 开启 TabBar 的沉浸光感效果后,实际的效果是有问题的。关闭后没问题,但开启后只有图标会下沉,而且有旧效果的顶部边缘残留。

API 23还在beta阶段,我暂时没有升级。你反馈的这个问题,建议直接提工单,这样能让API 23 更完善。

与官方对话后得知,HdsTabs 中要启用该效果,需要对其绑定的 HdsTabsController,在组件滑动时调用 applyHideAnimation 或 applyShowAnimation。具体还要配合滚动组件滑动回调事件给出的 offset 的大小,决定应用哪一个接口。

可参考以下内容:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ui-design-hdstabs#applyhideanimationhttps://developer.huawei.com/consumer/cn/doc/harmonyos-references/ui-design-hdstabs#applyshowanimation

核心代码:this.controller.applyHideAnimation(HdsAnimationMode.SCROLL_ANIMATION);

其中 SCROLL_ANIMATION 是我想要的效果,另一个可选的 CLICK_ANIMATION 也不错。

这个“页签随滚动收缩/隐藏”的效果,目前 没有一个 HdsTabs/HDS 组件级的开关可以直接开启(不像有些系统 App 内置行为那样一键配置)。一般是:

  • 自定义实现:监听滚动 → 判断方向/速度 → 用动画改变 TabBar(或标题栏/筛选栏)的高度、位移、透明度;
  • 如果你看到的是“系统应用/官方应用”的体验,那更多是它们在业务层做了这套交互,不是 HdsTabs 自带选项。

典型实现方式(你可以照这个思路做)

  1. List/Scroll 的滚动回调拿到 offset
  2. 计算本次 offset 与上次 offset 的差值:
    • 上滑(内容向上滚,offset 增大)→ 隐藏/收缩
    • 下滑(offset 减小)→ 显示/展开
  3. 对页签容器做动画(translateY / height / opacity + animation/animateTo

如果你用的是沉浸悬浮页签,建议用 叠层(Stack 底部 overlay)+ translateY,这样不会触发布局重排,抖动更少。

在HarmonyOS Next中,可通过监听ScrollListonScroll事件,获取偏移量,调用animateTo动态改变页签组件的visibilitytranslate属性,实现收缩/隐藏效果。使用@State管理状态,配合.transition()添加平滑动画即可。

鸿蒙Next中页签随滚动收缩隐藏的效果并非系统预设开关,需通过自定义动画实现。一般利用滚动事件监听,动态改变页签高度或透明度,并配合animateTo平滑过渡。例如在Scroll组件的onScroll回调中,根据滚动偏移量计算页签收缩比例,再触发UI变化。

回到顶部