HarmonyOS鸿蒙Next中Diaolog实现侧边栏效果

HarmonyOS鸿蒙Next中Diaolog实现侧边栏效果

1、控件选型

UX需求侧边栏从右侧划出,上下撑满全屏。应用首页Tabs+content布局。

测试后Sidebarcontainer只能在content布局中展示,无法覆盖导航栏区域实现撑满全屏效果,故放弃使用

  • 自定义Dialog

通过设置Dialog出场与退场动画来模拟侧边栏显示

2、实现代码

SideBarDialog

import { display } from '@kit.ArkUI';
import { SideBarViewModel } from './SideBarViewModel';

@CustomDialog
export struct SideBarDialog {
  controller: CustomDialogController;
  @Require viewModel?: SideBarViewModel;

  aboutToAppear(): void {
    setTimeout(()=>{
      if (this.viewModel) {
        this.viewModel.showFlag = Visibility.Visible;
      }
    }, 200)
  }

  build() {
    Column() {
      // 侧边栏布局
    }
    .width('80%')
    .height(this.getDisplayHeight())
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
    .transition(TransitionEffect.OPACITY.animation({ duration: 200, curve: Curve.EaseOut })
      .combine(TransitionEffect.translate({ x: 282 }))) // 出场退场动画
    .visibility(this.viewModel?.showFlag)
  }

  closeDialog() {
    if (this.viewModel) {
      this.viewModel.showFlag = Visibility.Hidden;
    }
    setTimeout(() => {
      this.controller.close();
    }, 200);
  }

  getDisplayHeight() {
    const displayWindow = display.getDefaultDisplaySync();
    return this.getUIContext().px2vp(displayWindow.height);
  }
}

SideBarViewModel

@ObservedV2
export class SideBarViewModel {
  @Trace showFlag: Visibility = Visibility.Visible;
}

@Local sideBarDialog?: CustomDialogController;
@Local viewModel:SideBarViewModel = new SideBarViewModel()

  showSideBarDialog() {
    this.sideBarDialog = new CustomDialogController({
      builder: SideBarDialog({
        viewModel: this.viewModel,
      }),
      autoCancel: true,
      customStyle: true,
      alignment: DialogAlignment.CenterEnd,
      onWillDismiss:()=>{
        // 点击空白处,执行退场动画消失
        this.viewModel.showFlag = Visibility.Hidden;
        setTimeout(()=>{
          this.sideBarDialog?.close();
        }, 200)
      }
    })
    this.sideBarDialog.open();
  }

更多关于HarmonyOS鸿蒙Next中Diaolog实现侧边栏效果的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

楼主学到了,感谢!

更多关于HarmonyOS鸿蒙Next中Diaolog实现侧边栏效果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,Dialog组件本身不直接支持侧边栏效果。若需实现侧边栏,应使用SideBarContainer组件。SideBarContainer是专门用于创建侧边栏布局的容器组件,支持设置侧边栏的宽度、位置(左侧或右侧)及显示/隐藏控制。可通过绑定状态变量来动态管理侧边栏的展开与收起。

你通过自定义Dialog实现全屏侧边栏的思路是正确的,特别是在SideBarContainer无法满足全屏覆盖需求时,这是一个实用的替代方案。

你的代码实现有几个关键点处理得很好:

  1. 动画与状态分离:通过showFlag控制visibility属性,配合transition实现平滑的滑入滑出动画,避免了直接控制Dialog开闭导致的生硬切换。
  2. 全屏高度适配:使用display.getDefaultDisplaySync()获取屏幕高度并配合expandSafeArea,确保了侧边栏在不同设备上都能上下撑满。
  3. 对齐方式:设置DialogAlignment.CenterEnd使Dialog初始位置在屏幕右侧,这是实现侧边栏效果的基础。

这里可以补充一个优化点:手势关闭。目前你的代码通过点击Dialog外部(autoCancel: true)触发关闭。为了体验更完整,可以在侧边栏内容区域添加一个PanGesture,监听水平向左的滑动,当滑动距离超过阈值时,调用你的closeDialog方法,这样能实现手势滑出关闭,更符合侧边栏的交互直觉。

另外,关于动画数值,你代码中translate({ x: 282 })是一个固定值。为了更精确地实现“从右侧完全划入”的效果,这个值可以动态计算为侧边栏本身的宽度(即'80%'对应的VP值),这样动画的起始位置就在屏幕外右侧,视觉上会更连贯。

总的来说,这是一个利用现有组件实现特定UX需求的典型且有效的方案。

回到顶部