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

相关推荐
哲科软件1 小时前
跨平台开发的抉择:Flutter vs 原生安卓(Kotlin)的优劣对比与选型建议
android·flutter·kotlin
天涯海风1 小时前
Kuikly 与 Flutter 的全面对比分析,结合技术架构、性能、开发体验等核心维度
flutter·kuikly
aiprtem1 小时前
基于Flutter的web登录设计
前端·flutter
coder_pig5 小时前
跟🤡杰哥一起学Flutter (三十四、玩转Flutter手势✋)
前端·flutter·harmonyos
simple丶5 小时前
【HarmonyOS】鸿蒙蓝牙连接与通信技术
harmonyos·arkts·arkui
前端世界7 小时前
HarmonyOS开发实战:鸿蒙分布式生态构建与多设备协同发布全流程详解
分布式·华为·harmonyos
程序员老刘8 小时前
Android 16开发者全解读
android·flutter·客户端
zhanshuo9 小时前
开发者必看!如何在HarmonyOS中快速调用摄像头功能
harmonyos
HMSCore9 小时前
借助HarmonyOS SDK,《NBA巅峰对决》实现“分钟级启动”到“秒级进场”
harmonyos