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 跳转鸿蒙原生界面的知识,若有更好的方案,欢迎大家在评论区与我讨论,一起进度!

相关推荐
摘星编程3 小时前
React Native鸿蒙:Loading加载动画效果
react native·react.js·harmonyos
灰灰勇闯IT3 小时前
Flutter for OpenHarmony:图标与 Asset 资源管理 —— 构建高性能、可维护的视觉资源体系
flutter
Swift社区4 小时前
HarmonyOS 页面路由与导航开发
华为·harmonyos
子春一4 小时前
Flutter for OpenHarmony:构建一个 Flutter 记忆翻牌游戏,深入解析状态管理、动画交互与经典配对逻辑
flutter·游戏·交互
希望上岸的大菠萝5 小时前
HarmonyOS 6.0 开发环境搭建完全指南 - DevEco Studio 配置 + 真机调试实战
华为·harmonyos
大雷神6 小时前
HarmonyOS智慧农业管理应用开发教程--高高种地--第28篇:用户中心与个人资料
华为·harmonyos
2601_949847756 小时前
Flutter for OpenHarmony音乐播放器App实战13:歌手列表实现
flutter
雨季6666 小时前
破界与共生:HarmonyOS原生应用生态全景图谱与PC时代三重变局
flutter·华为·harmonyos
一路阳光8516 小时前
华为mate80现在确实没有日日新了,看来华为是对鸿蒙6有信心了
华为·harmonyos
三掌柜6666 小时前
如何从一个开发者成为鸿蒙KOL
华为·harmonyos