Flutter + 鸿蒙 | Flutter 跳转鸿蒙原生界面

前言

虽然大部分场景下,Flutter可以通过Channel等与原生进行数据交互,但也存在一些情况需要自己写个原生的UI以使用部分原生的控件。

1. 在原有Index.ets包裹Navigation

官方目前主推的是Navigation,其好处就是会自带一些鸿蒙的UI,如AppBar等。因此我们需要Flutter的宿主UI下外面嵌套一个Navigation。实现代码如下:

ts 复制代码
build() {
  Navigation(pageInfos) {
    Column() {
      FlutterPage({ viewId: this.viewId })
    }
  }.hideToolBar(true) \\取消底部导航栏,否则会有一大片的空白
}

这个pageInfo则是通过一个ets文件导出的,文件的内容如下:

ts 复制代码
const pageInfos: NavPathStack = new NavPathStack();

export default pageInfos

2. 写一个原生UI

新开一个ets文件写UI

ts 复制代码
@Builder
export function PageOneBuilder() {
  PageOne()
}

@Component
struct PageOne {

    @StorageProp('bottomRectHeight') bottomRectHeight: number = 0;
    @StorageProp('topRectHeight') topRectHeight: number = 0;

    pathStack: NavPathStack = new NavPathStack();

    build() {
      NavDestination() {
          // 你的内容
      }
      .title('原生UI')
      .padding({ top: this.topRectHeight, left: 8, right: 8 })
      .onReady((context: NavDestinationContext) => {
        this.pathStack = context.pathStack;
      })
    }

}

但写完UI还不行,你还得告诉鸿蒙UI在哪里,因此你需要在resource/base/profile下弄一个配置文件route_map.json。配置如下内容:

json 复制代码
{
  "routerMap": [
    {
      "name": "PageOne",
      "pageSourceFile": "src/main/ets/pages/PageOne.ets",
      "buildFunction": "PageOneBuilder",
      "data": {
        "description": "this is pageOne"
      }
    }
  ]
}

最后在module.json5中的module加入一个key-value:

json 复制代码
"routerMap": "$profile:route_map"

3. Flutter 跳转到原生

ts 复制代码
openPreviewPage(){
  pageInfos.pushPathByName('PageOne', null); // 这里就写struct的名字
}

async onMethodCall(call: MethodCall, result: MethodResult): Promise<void> {
  switch (call.method) {
    case "jumpToArkTs":
      this.openPreviewPage()
      result.success(null);
      break;
    default:
      result.notImplemented();
  }
}

完成以上代码后,就在Flutter端使用Channel就可以实现原生界面的跳转啦。

4. 坑

然而,你会发现这个原生界面AppBar与状态栏重合了。我们的上面的代码设置了Padding来解决这个问题。但怎么获取这个准确的状态栏高度呢?

EntryAbility.ets下增加下面这个函数,就可以获取到准确的状态栏高度啦。

ts 复制代码
onWindowStageCreate(windowStage: window.WindowStage): void {
  super.onWindowStageCreate(windowStage)
  let windowClass: window.Window = windowStage.getMainWindowSync(); // 获取应用主窗口

  let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; // 此处以导航条避让为例
  let avoidArea = windowClass.getWindowAvoidArea(type);
  let bottomRectHeight = avoidArea.bottomRect.height; // 获取到导航区域的高度
  AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);

  type = window.AvoidAreaType.TYPE_SYSTEM; // 以状态栏避让为例
  avoidArea = windowClass.getWindowAvoidArea(type);
  let topRectHeight = avoidArea.topRect.height; // 获取状态栏区域高度
  console.debug("top" + topRectHeight);
  display.getDefaultDisplaySync().getCutoutInfo().then((data) => {
    data.boundingRects.forEach((rect) => {
      AppStorage.setOrCreate('topRectHeight', rect.top);
      console.debug("rect = " + JSON.stringify(rect));
    })
  })
}

以上便是所有关于Flutter 跳转鸿蒙原生界面的知识,若有更好的方案,欢迎大家在评论区与我讨论,一起进度!

相关推荐
HwJack201 小时前
UIAbility 生命周期全链路:从冷启动到热启动的实战笔记
笔记·华为·harmonyos
梦想不只是梦与想1 小时前
鸿蒙 AppGallery Connect:应用创建(二)
harmonyos·appgallery·创建应用
●VON3 小时前
芯笺 Markdown:面向 HarmonyOS PC 的本地优先 Markdown 编辑器
华为·编辑器·harmonyos·鸿蒙
世人万千丶4 小时前
鸿蒙项目实战 - 社区活动编排板:标签云布局算法与自动换行
学习·算法·华为·harmonyos·鸿蒙
YM52e5 小时前
鸿蒙ArkTS项目实战 - 门店陈列巡检台:完整代码与运行效果
学习·华为·harmonyos
贾伟康6 小时前
【中国方言题库|06】HarmonyOS ArkTS 闽南语与客家话实战:统一分库页面导航与空状态
harmonyos·arkts·arkui·router·空状态
贾伟康6 小时前
【中国方言题库|07】HarmonyOS ArkTS 方言练习实战:推进题目、提交答案并同步统计
harmonyos·arkts·数据持久化·状态管理·arkui
iFlyCai6 小时前
深入理解Flutter:StatefulWidget生命周期全解析(一)
flutter·dart·状态管理·statefulwidget
贾伟康7 小时前
【中国方言题库|05】HarmonyOS ArkTS 东北话分库实战:让地区内容与通用列表解耦
harmonyos·arkts·路由·arkui·数据架构