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

相关推荐
不羁的木木2 小时前
《HarmonyOS底部页签-沉浸光感组件实战》基础入门:认识HdsTabs容器与核心配置
华为·harmonyos
不羁的木木2 小时前
《HarmonyOS技术精讲》三:记忆链接 ── 跨场景数据融合
pytorch·华为·harmonyos
2501_919749032 小时前
鸿蒙 Flutter 实战:image_crop 0.4.1 适配 3.27-ohos 全流程
flutter·华为·harmonyos
祭曦念2 小时前
鸿蒙应用的生命周期与页面跳转:从入门到实战
华为·harmonyos
轻口味3 小时前
HarmonyOS 6.1.1 全栈实战录 - 88 实战 Ability Kit 启动生命周期预热与快照恢复机
华为·harmonyos·鸿蒙
Goway_Hui4 小时前
【鸿蒙原生应用开发--ArkUI--013】Exercise-tracker 运动记录应用开发教程
华为·harmonyos
想你依然心痛4 小时前
HarmonyOS 6(API 23)实战:基于悬浮导航、沉浸光感与HMAF的“图谱智脑“——PC端AI智能体沉浸式知识图谱构建工作台
人工智能·ar·知识图谱·harmonyos·智能体
想你依然心痛4 小时前
HarmonyOS 6(API 23)实战:基于悬浮导航、沉浸光感与HMAF的“律界智脑“——PC端AI智能体沉浸式法律文档智能审查工作台
人工智能·华为·ar·harmonyos·智能体
特立独行的猫a4 小时前
鸿蒙 PC 平台 Python 第三方库移植全景指南
python·华为·harmonyos·三方库移植·鸿蒙pc
大雷神5 小时前
第31篇|位置信息写入照片记录:为什么拍照时要带上地点
harmonyos