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

相关推荐
zhanshuo8 小时前
用鸿蒙做多人协作,真的可以跨屏秒同步!
harmonyos
zhanshuo8 小时前
HarmonyOS 开发:基于 ArkUI 实现复杂表单验证的最佳实践
harmonyos
嵌入之梦13 小时前
鸿蒙智能居家养老系统构思(续二)—— 适老化烹饪中心详细构思
智能家居·harmonyos·居家养老
用户7360043755613 小时前
【Flutter 必备插件】HTTP 封装 dio
flutter
鸿蒙开发工程师—阿辉14 小时前
HarmonyOS 应用拉起系列(一):应用与元服务互通方式
华为·harmonyos·arkts·鸿蒙
风清云淡_A14 小时前
【Flutter3.8x】flutter从入门到实战基础教程(四):自定义实现一个自增的StatefulWidget组件
前端·flutter
用户59514332217720 小时前
HarmonyOS开发:ArkUI相对布局RelativeContainer解决层级嵌套较多问题
harmonyos
叽哥20 小时前
dart学习第1节: 变量与数据类型 —— 程序的 “基本元素”
flutter
用户59514332217720 小时前
HarmonyOS开发:ArkUI视觉效果之透明度、渐变、模糊、阴影、高亮一网打尽
harmonyos
用户59514332217720 小时前
HarmonyOS开发:ArkUI线性布局(Column/Row)完全解析
harmonyos