美文网首页
flutter android 原生浮窗组件 android_w

flutter android 原生浮窗组件 android_w

作者: 7c00 | 来源:发表于2021-10-08 17:44 被阅读0次

    仓库地址:https://github.com/qiuxiang/flutter-android-window
    pub 地址:https://pub.dartlang.org/packages/android_window

    功能

    • 使用 android 原生接口实现,可以让 flutter app 覆盖在其他 app 上面
    • 浮窗作为 android 前台服务运行,可完全脱离主应用
    • 默认支持拖拽移动浮窗,且可以与 flutter 手势共存
    • 提供浮窗大小、位置控制接口
    • 提供主应用与浮窗应用相互通信接口

    安装与配置

    flutter pub add android_window
    

    修改 MainActivity.ktMainActivity 继承 qiuxiang.android_window.AndroidWindowActivity

    class MainActivity : qiuxiang.android_window.AndroidWindowActivity()
    

    创建 MainApplication.kt

    package your_package // 和 MainActivity.kt 保持一致即可
    
    class MainApplication : qiuxiang.android_window.AndroidWindowApplication()
    

    修改 AndroidManifest.xml<application> 新增属性 android:name=".MainApplication"

    <application
      android:name=".MainApplication"
      ...
    >
    

    用法

    main.dart:

    import 'package:android_window/main.dart' as android_window;
    import 'package:flutter/material.dart';
    
    import 'android_window.dart';
    
    @pragma('vm:entry-point')
    void androidWindow() {
      runApp(const AndroidWindowApp());
    }
    
    void main() {
      runApp(const App());
    }
    
    class App extends StatelessWidget {
      const App({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(title: 'Flutter Demo', home: HomePage());
      }
    }
    
    class HomePage extends StatelessWidget {
      const HomePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          floatingActionButton: FloatingActionButton(
            onPressed: () => android_window.open(size: const Size(300, 200)),
            child: const Icon(Icons.add),
          ),
        );
      }
    }
    

    我们需要用 @pragma('vm:entry-point') 声明一个入口函数,默认函数名是 androidWindow,当然你可以随意指定一个,只是调用 open 的时候需要同时指定参数 entryPoint:

    android_window.dart:

    import 'package:android_window/android_window.dart';
    import 'package:flutter/material.dart';
    
    class AndroidWindowApp extends StatelessWidget {
      const AndroidWindowApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          home: HomePage(),
          debugShowCheckedModeBanner: false,
        );
      }
    }
    
    class HomePage extends StatelessWidget {
      const HomePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return AndroidWindow(
          child: Scaffold(
            backgroundColor: Colors.lightGreen.withOpacity(0.9),
            body: const Padding(
              padding: EdgeInsets.all(8),
              child: Text('Hello android window'),
            ),
          ),
        );
      }
    }
    

    浮窗 app 的写法就和我们平时写的 app 没什么区别了,如果需要支持窗口拖拽移动,则要在最外层使用 AndroidWindow

    最终效果:

    image

    更完整的示例请参考:https://github.com/qiuxiang/flutter-android-window/tree/main/example

    浮窗与主应用的通信

    主应用和浮窗都有 postsetHandler 方法用于发送消息以及设置监听处理函数。用法举例:

    主应用发送消息到浮窗:

    final response = await android_window.post('message_name', 'data');
    

    浮窗监听并处理主应用消息:

    AndroidWindow.setHandler((name, data) async {
      switch(name) {
        case 'bar':
          return 'data';
      }
    });
    

    反过来同理。

    聊聊这个库的一些实现细节

    • 核心功能参考了官方文档 Adding a Flutter View to an Android app
    • 为了让主应用与浮窗进行通信,需要自定义 Application,并存储两个互通的 channel。
    • 这个库并没有直接用 MethodChannel,而是实验性地用了 pigeon,总的来说,MethodChannel 更灵活高效,而 pigeon 更规范且类型安全,之后我应该都会考虑用 pigeon 而不是 MethodChannel。

    相关文章

      网友评论

          本文标题:flutter android 原生浮窗组件 android_w

          本文链接:https://www.haomeiwen.com/subject/hmbxoltx.html